commit
message
[Cell] setting and getting Cell fields, more thurough testing
author
Ben Vogt <[email protected]>
date
2017-09-04 16:40:46
stats
8 file(s) changed,
201 insertions(+),
41 deletions(-)
files
DOCS.md
TODO.md
dist/Cell.js
dist/Sheet.js
src/Cell.ts
src/Sheet.ts
tests/CellTest.ts
tests/Utils/Asserts.ts
1diff --git a/DOCS.md b/DOCS.md
2index 3e408c8..737ce5a 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -24,7 +24,10 @@
6 ### TO_PERCENT
7
8 ```
9- Converts a number to a percent value where 1 = 100
10+ Converts a number to a percent value where 1 = 100 percent.
11+@param value - Value to convert. If the input is a number, will return as a percent value. If value is non-numeric, will return value unchanged.
12+@returns {any}
13+@constructor
14 ```
15
16 ### TO_TEXT
17diff --git a/TODO.md b/TODO.md
18index 07d1804..0eb49fb 100644
19--- a/TODO.md
20+++ b/TODO.md
21@@ -5,9 +5,6 @@
22 Instead of having non-primitives, (i.e. Date, DateTime, Time, Dollar), cells should have formats based on the highest-order type that was used during the compilation and execution of a cell's dependency. For example, `DATE` might return a number, but the cell that called `DATE` would be aware of it calling a formula that returns an non-primitive type, and would display the returned number as a Date. If you're using `DATE` in conjunction with `DOLLAR` it would still display the returned value as a Date. The hierarchy would look like: [Date, DateTime, Time, Dollar, number, boolean, string]. Advantages to this would include not having to cast down when using primitive operators, and flexibility in display. It would also simplify the types themselves, by having types be constants and just having helpers to convert, display, and do normal operations with them. Requires changes to `TO_DATE`, `TO_PERCENT`, `TO_DOLLAR`, and `TO_TEXT`.
23
24
25-### Cell.rawFormulaText does not get reset when updating a cell for the second time.
26-
27-
28 ### CONVERT could offer more accurate conversions for units in the same system
29 For example 64 tbs to a qt.
30
31diff --git a/dist/Cell.js b/dist/Cell.js
32index f7b249d..c88c5b9 100644
33--- a/dist/Cell.js
34+++ b/dist/Cell.js
35@@ -1,5 +1,31 @@
36 "use strict";
37+var __extends = (this && this.__extends) || (function () {
38+ var extendStatics = Object.setPrototypeOf ||
39+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
40+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
41+ return function (d, b) {
42+ extendStatics(d, b);
43+ function __() { this.constructor = d; }
44+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
45+ };
46+})();
47 exports.__esModule = true;
48+var CELL_ID_ERROR = "CELL_ID_ERROR";
49+exports.CELL_ID_ERROR = CELL_ID_ERROR;
50+/**
51+ * Represents a cell id error, and is thrown when a cells id does not conform to A1 notation.
52+ */
53+var CellIdError = (function (_super) {
54+ __extends(CellIdError, _super);
55+ function CellIdError(msg) {
56+ var _this = _super.call(this) || this;
57+ _this.message = msg;
58+ _this.name = CELL_ID_ERROR;
59+ return _this;
60+ }
61+ return CellIdError;
62+}(Error));
63+exports.CellIdError = CellIdError;
64 /**
65 * Cell represents a cell in the spreadsheet. It contains a nullable rawFormulaText, and a value, which is not nullable unless
66 * the parsing of the rawFormulaText results in an error.
67@@ -18,6 +44,9 @@ var Cell = (function () {
68 this.typedValue = null;
69 this.dependencies = [];
70 this.error = null;
71+ if (!id.match(/^(?:[A-Za-z]+[0-9]+)$/)) {
72+ throw new CellIdError("Cell id " + id + " not valid");
73+ }
74 var key = parseKey(id);
75 this.id = id;
76 this.row = key.y;
77@@ -77,21 +106,13 @@ var Cell = (function () {
78 Cell.prototype.hasFormula = function () {
79 return this.rawFormulaText !== null;
80 };
81- /**
82- * Set the value of this cell. If this cell has a primitive value (does not contain a rawFormulaText), it could be set to a
83- * value while the rawFormulaText field is still null.
84- * @param value to set
85- */
86- Cell.prototype.setValue = function (value) {
87- this.typedValue = value;
88- };
89 /**
90 * Sets the value or rawFormulaText for this cell. If the input begins with =, then it is considered to be a rawFormulaText. If it
91 * is not, then it is a value, and set as the raw value for this cell.
92 * @param rawFormula
93 */
94- Cell.prototype.setRawValue = function (rawFormula) {
95- if (rawFormula.charAt(0) === "=") {
96+ Cell.prototype.setValue = function (rawFormula) {
97+ if (typeof rawFormula === "string" && rawFormula.charAt(0) === "=") {
98 this.rawFormulaText = rawFormula.substr(1);
99 }
100 else {
101@@ -99,7 +120,15 @@ var Cell = (function () {
102 }
103 };
104 /**
105- * Get the value of this cell. Since value could be null do to an error in the rawFormulaText, this could return null.
106+ * Gets the rawFormulaText for this cell, which is either null or a string.
107+ * @returns {string}
108+ */
109+ Cell.prototype.getRawFormulaText = function () {
110+ return this.rawFormulaText;
111+ };
112+ /**
113+ * Get the value of this cell if a value is present. If this cell was given a formula but not a value, this may return
114+ * null.
115 * @returns {any}
116 */
117 Cell.prototype.getValue = function () {
118@@ -157,7 +186,7 @@ var Cell = (function () {
119 /**
120 * Build a cell with an id and value.
121 * @param id - A1-notation id or key.
122- * @param value - value of the cell.
123+ * @param value - value of the cell as a string
124 * @returns {Cell}
125 * @constructor
126 */
127diff --git a/dist/Sheet.js b/dist/Sheet.js
128index d6e27e2..9c4844b 100644
129--- a/dist/Sheet.js
130+++ b/dist/Sheet.js
131@@ -135,7 +135,7 @@ var Sheet = (function () {
132 */
133 Matrix.prototype.setCell = function (id, rawFormula) {
134 var cell = new Cell_1.Cell(id);
135- cell.setRawValue(rawFormula);
136+ cell.setValue(rawFormula);
137 registerCellInMatrix(cell);
138 recalculateCellDependencies(cell);
139 };
140diff --git a/src/Cell.ts b/src/Cell.ts
141index 5557686..071cb02 100644
142--- a/src/Cell.ts
143+++ b/src/Cell.ts
144@@ -1,3 +1,16 @@
145+const CELL_ID_ERROR = "CELL_ID_ERROR";
146+
147+/**
148+ * Represents a cell id error, and is thrown when a cells id does not conform to A1 notation.
149+ */
150+class CellIdError extends Error {
151+ constructor(msg: string) {
152+ super();
153+ this.message = msg;
154+ this.name = CELL_ID_ERROR;
155+ }
156+}
157+
158 /**
159 * Cell represents a cell in the spreadsheet. It contains a nullable rawFormulaText, and a value, which is not nullable unless
160 * the parsing of the rawFormulaText results in an error.
161@@ -20,6 +33,9 @@ class Cell {
162 * @param id key of the cell in A1-format.
163 */
164 constructor(id: string) {
165+ if (!id.match(/^(?:[A-Za-z]+[0-9]+)$/)) {
166+ throw new CellIdError("Cell id " + id + " not valid");
167+ }
168 let key = parseKey(id);
169
170 this.id = id;
171@@ -88,22 +104,13 @@ class Cell {
172 return this.rawFormulaText !== null;
173 }
174
175- /**
176- * Set the value of this cell. If this cell has a primitive value (does not contain a rawFormulaText), it could be set to a
177- * value while the rawFormulaText field is still null.
178- * @param value to set
179- */
180- setValue(value: any) {
181- this.typedValue = value;
182- }
183-
184 /**
185 * Sets the value or rawFormulaText for this cell. If the input begins with =, then it is considered to be a rawFormulaText. If it
186 * is not, then it is a value, and set as the raw value for this cell.
187 * @param rawFormula
188 */
189- setRawValue(rawFormula: string) {
190- if (rawFormula.charAt(0) === "=") {
191+ setValue(rawFormula: string) {
192+ if (typeof rawFormula === "string" && rawFormula.charAt(0) === "=") {
193 this.rawFormulaText = rawFormula.substr(1);
194 } else {
195 this.typedValue = rawFormula;
196@@ -111,7 +118,17 @@ class Cell {
197 }
198
199 /**
200- * Get the value of this cell. Since value could be null do to an error in the rawFormulaText, this could return null.
201+ * Gets the rawFormulaText for this cell, which is either null or a string.
202+ * @returns {string}
203+ */
204+ getRawFormulaText() : string | null {
205+ return this.rawFormulaText;
206+ }
207+
208+
209+ /**
210+ * Get the value of this cell if a value is present. If this cell was given a formula but not a value, this may return
211+ * null.
212 * @returns {any}
213 */
214 getValue() : any {
215@@ -177,7 +194,7 @@ class Cell {
216 /**
217 * Build a cell with an id and value.
218 * @param id - A1-notation id or key.
219- * @param value - value of the cell.
220+ * @param value - value of the cell as a string
221 * @returns {Cell}
222 * @constructor
223 */
224@@ -211,5 +228,7 @@ function parseKey(cell) {
225 }
226
227 export {
228- Cell
229+ Cell,
230+ CellIdError,
231+ CELL_ID_ERROR
232 }
233\ No newline at end of file
234diff --git a/src/Sheet.ts b/src/Sheet.ts
235index e79987e..8e48590 100644
236--- a/src/Sheet.ts
237+++ b/src/Sheet.ts
238@@ -161,7 +161,7 @@ let Sheet = (function () {
239 */
240 setCell(id: string, rawFormula: string) {
241 let cell = new Cell(id);
242- cell.setRawValue(rawFormula);
243+ cell.setValue(rawFormula);
244 registerCellInMatrix(cell);
245 recalculateCellDependencies(cell);
246 }
247diff --git a/tests/CellTest.ts b/tests/CellTest.ts
248index a8bab0a..9ecee59 100644
249--- a/tests/CellTest.ts
250+++ b/tests/CellTest.ts
251@@ -1,46 +1,148 @@
252 import {
253- Cell
254+ Cell,
255+ CELL_ID_ERROR
256 } from "../src/Cell";
257 import {
258- assertEquals,
259 assertArrayEquals,
260- test, assertIsNull
261+ assertEquals,
262+ assertIsNull,
263+ catchAndAssertEquals,
264+ test
265 } from "./Utils/Asserts";
266
267 test("Cell.constructor", function(){
268- var cell = new Cell("A1");
269+ let cell = new Cell("A1");
270 assertEquals(cell.getColumn(), 0);
271 assertEquals(cell.getRow(), 0);
272 assertArrayEquals(cell.getDependencies(), []);
273 assertEquals(cell.getId(), "A1");
274 assertIsNull(cell.getFormula());
275 assertEquals(cell.hasFormula(), false);
276+ catchAndAssertEquals(function () {
277+ new Cell("C");
278+ }, CELL_ID_ERROR)
279+ catchAndAssertEquals(function () {
280+ new Cell("111");
281+ }, CELL_ID_ERROR)
282+ catchAndAssertEquals(function () {
283+ new Cell("BAD11BAD");
284+ }, CELL_ID_ERROR)
285 });
286
287 test("Cell.updateDependencies", function(){
288- var one = new Cell("A1");
289+ let one = new Cell("A1");
290 one.updateDependencies(["B2", "C1", "D12", "D13"]);
291 assertArrayEquals(one.getDependencies(), ["B2", "C1", "D12", "D13"]);
292 one.updateDependencies(["M4"]);
293 assertArrayEquals(one.getDependencies(), ["B2", "C1", "D12", "D13", "M4"]);
294 });
295
296-test("Cell.setValue", function(){
297- var v = new Cell("A1");
298+test("Cell.getDependencies", function(){
299+ let one = new Cell("A1");
300+ assertArrayEquals(one.getDependencies(), []);
301+ one.updateDependencies(["M4"]);
302+ assertArrayEquals(one.getDependencies(), ["M4"]);
303+});
304+
305+test("Cell.getColumn", function(){
306+ assertEquals(Cell.BuildFrom("A1", 0).getColumn(), 0);
307+ assertEquals(Cell.BuildFrom("B1", 0).getColumn(), 1);
308+ assertEquals(Cell.BuildFrom("M1", 0).getColumn(), 12);
309+ assertEquals(Cell.BuildFrom("N1", 0).getColumn(), 13);
310+ assertEquals(Cell.BuildFrom("AA1", 0).getColumn(), 26);
311+ assertEquals(Cell.BuildFrom("AB1", 0).getColumn(), 27);
312+ assertEquals(Cell.BuildFrom("AM1", 0).getColumn(), 38);
313+});
314+
315+test("Cell.getRow", function(){
316+ assertEquals(Cell.BuildFrom("A1", 0).getRow(), 0);
317+ assertEquals(Cell.BuildFrom("B2", 0).getRow(), 1);
318+ assertEquals(Cell.BuildFrom("M13", 0).getRow(), 12);
319+ assertEquals(Cell.BuildFrom("N14", 0).getRow(), 13);
320+ assertEquals(Cell.BuildFrom("AA27", 0).getRow(), 26);
321+ assertEquals(Cell.BuildFrom("AB28", 0).getRow(), 27);
322+ assertEquals(Cell.BuildFrom("AM39", 0).getRow(), 38);
323+});
324+
325+test("Cell.getId", function(){
326+ assertEquals(Cell.BuildFrom("A1", 0).getId(), "A1");
327+ assertEquals(Cell.BuildFrom("M1400", 0).getId(), "M1400");
328+});
329+
330+test("Cell.setValue, Cell.getValue", function(){
331+ let v = new Cell("A1");
332 v.setValue("100");
333- assertEquals("100", v.getValue());
334+ assertEquals(v.getValue(), "100");
335+ v = new Cell("A1");
336+ v.setValue("=SUM(10, 10)");
337+ assertIsNull(v.getValue());
338+});
339+
340+test("Cell.clearValue", function(){
341+ let v = Cell.BuildFrom("A1", 100);
342+ assertEquals(v.getValue(), 100);
343+ v.clearValue();
344+ assertIsNull(v.getValue());
345+});
346+
347+test("Cell.setError, Cell.getError", function(){
348+ let v = Cell.BuildFrom("A1", 100);
349+ let e = new Error("e");
350+ assertIsNull(v.getError());
351+ v.setError(e);
352+ assertEquals(v.getError(), e);
353+});
354+
355+test("Cell.hasError", function(){
356+ let v = Cell.BuildFrom("A1", 100);
357+ let e = new Error("e");
358+ assertEquals(v.hasError(), false);
359+ v.setError(e);
360+ assertEquals(v.hasError(), true);
361+});
362+
363+test("Cell.getFormula", function(){
364+ assertIsNull(Cell.BuildFrom("A1", "100").getFormula());
365+ assertEquals(Cell.BuildFrom("A1", "=SUM(1, 2)").getFormula(), "SUM(1, 2)");
366+ assertEquals(Cell.BuildFrom("A1", "= 100,000,000").getFormula(), " 100,000,000");
367+});
368+
369+test("Cell.hasFormula", function(){
370+ assertEquals(Cell.BuildFrom("A1", "100").hasFormula(), false);
371+ assertEquals(Cell.BuildFrom("A1", "=SUM(1, 2)").hasFormula(), true);
372+ assertEquals(Cell.BuildFrom("A1", "= 100,000,000").hasFormula(), true);
373+});
374+
375+test("Cell.getRawFormulaText", function(){
376+ assertIsNull(Cell.BuildFrom("A1", "100").getRawFormulaText());
377+ assertEquals(Cell.BuildFrom("A1", "=10e1").getRawFormulaText(), "10e1");
378+ assertEquals(Cell.BuildFrom("A1", "=SUM(1, 2)").getRawFormulaText(), "SUM(1, 2)");
379+ assertEquals(Cell.BuildFrom("A1", "= 100,000,000").getRawFormulaText(), " 100,000,000");
380 });
381
382 test("Cell.isBlank", function(){
383- var v = new Cell("A1");
384+ let v = new Cell("A1");
385 assertIsNull(v.getValue());
386 assertIsNull(v.getError());
387 assertEquals(v.isBlank(), true);
388 });
389
390 test("Cell.BuildFrom", function(){
391- var v = Cell.BuildFrom("A1", 10);
392+ let v = Cell.BuildFrom("A1", 10);
393 assertEquals(v.getValue(), 10);
394 assertIsNull(v.getError());
395 assertEquals(v.isBlank(), false);
396 });
397+
398+test("Cell.tosString", function(){
399+ assertEquals(new Cell("A1").toString(), "id=A1, value=null, rawFormulaText=null, error=null");
400+ assertEquals(Cell.BuildFrom("A1", 100).toString(), "id=A1, value=100, rawFormulaText=null, error=null");
401+ assertEquals(Cell.BuildFrom("A1", "100").toString(), "id=A1, value=100, rawFormulaText=null, error=null");
402+ assertEquals(Cell.BuildFrom("A1", "=SUM(A1:A10)").toString(), "id=A1, value=null, rawFormulaText=SUM(A1:A10), error=null");
403+});
404+
405+test("Cell.equals", function(){
406+ assertEquals(new Cell("A1").equals(new Cell("A1")), true);
407+ assertEquals(new Cell("M100").equals(new Cell("A1")), false);
408+ assertEquals(Cell.BuildFrom("A1", 100).equals(Cell.BuildFrom("A1", 100)), true);
409+});
410\ No newline at end of file
411diff --git a/tests/Utils/Asserts.ts b/tests/Utils/Asserts.ts
412index 0de1f76..a0fc5d3 100644
413--- a/tests/Utils/Asserts.ts
414+++ b/tests/Utils/Asserts.ts
415@@ -46,7 +46,7 @@ function assertArrayEquals(actual: Array<any>, expected: Array<any>, ) {
416 console.trace();
417 return;
418 }
419- for (var index in expected) {
420+ for (let index in expected) {
421 if (expected[index] != actual[index]) {
422 console.log("expected: ", expected, " actual:", actual);
423 console.trace();
424@@ -60,7 +60,7 @@ function assertArrayEquals(actual: Array<any>, expected: Array<any>, ) {
425 * @param expected error message
426 */
427 function catchAndAssertEquals(toExecute : Function, expected) {
428- var toThrow = null;
429+ let toThrow = null;
430 try {
431 toExecute();
432 toThrow = true;