@odoo/o-spreadsheet 14.0.1 → 14.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/o_spreadsheet.cjs.js +17836 -0
  2. package/dist/o_spreadsheet.d.ts +4102 -0
  3. package/dist/o_spreadsheet.esm.js +17801 -0
  4. package/dist/o_spreadsheet.iife.js +17838 -0
  5. package/dist/o_spreadsheet.iife.min.js +1440 -0
  6. package/package.json +27 -7
  7. package/readme.md +10 -0
  8. package/.eslintrc.json +0 -20
  9. package/.husky/post-checkout +0 -9
  10. package/.husky/pre-commit +0 -39
  11. package/.prettierignore +0 -1
  12. package/astToFormula.patch +0 -0
  13. package/demo/data.js +0 -255
  14. package/demo/index.html +0 -9
  15. package/demo/libs/Chart.bundle.js +0 -20755
  16. package/demo/main.js +0 -101
  17. package/doc/readme.md +0 -46
  18. package/rollup.config.js +0 -23
  19. package/src/base_plugin.ts +0 -102
  20. package/src/components/autofill.ts +0 -146
  21. package/src/components/bottom_bar.ts +0 -199
  22. package/src/components/color_picker.ts +0 -150
  23. package/src/components/composer/autocomplete_dropdown.ts +0 -135
  24. package/src/components/composer/composer.ts +0 -487
  25. package/src/components/composer/content_editable_helper.ts +0 -146
  26. package/src/components/figures/chart.ts +0 -70
  27. package/src/components/figures/container.ts +0 -268
  28. package/src/components/figures/text_figure.ts +0 -36
  29. package/src/components/grid.ts +0 -635
  30. package/src/components/helpers/dom_helpers.ts +0 -7
  31. package/src/components/helpers/drag_and_drop.ts +0 -17
  32. package/src/components/icons.ts +0 -36
  33. package/src/components/index.ts +0 -1
  34. package/src/components/menu.ts +0 -288
  35. package/src/components/overlay.ts +0 -457
  36. package/src/components/scrollbar.ts +0 -22
  37. package/src/components/selection_input.ts +0 -168
  38. package/src/components/side_panel/cell_is_rule_editor.ts +0 -169
  39. package/src/components/side_panel/chart_panel.ts +0 -104
  40. package/src/components/side_panel/color_scale_rule_editor.ts +0 -145
  41. package/src/components/side_panel/conditional_formatting.ts +0 -396
  42. package/src/components/side_panel/side_panel.ts +0 -127
  43. package/src/components/side_panel/translations_terms.ts +0 -45
  44. package/src/components/spreadsheet.ts +0 -198
  45. package/src/components/top_bar.ts +0 -535
  46. package/src/constants.ts +0 -26
  47. package/src/data.ts +0 -149
  48. package/src/fonts.ts +0 -41
  49. package/src/formulas/compiler.ts +0 -258
  50. package/src/formulas/composer_tokenizer.ts +0 -70
  51. package/src/formulas/index.ts +0 -15
  52. package/src/formulas/normalize.ts +0 -52
  53. package/src/formulas/parser.ts +0 -280
  54. package/src/formulas/range_tokenizer.ts +0 -97
  55. package/src/formulas/tokenizer.ts +0 -242
  56. package/src/functions/arguments.ts +0 -114
  57. package/src/functions/dates.ts +0 -302
  58. package/src/functions/helpers.ts +0 -592
  59. package/src/functions/index.ts +0 -52
  60. package/src/functions/module_database.ts +0 -282
  61. package/src/functions/module_date.ts +0 -743
  62. package/src/functions/module_info.ts +0 -69
  63. package/src/functions/module_logical.ts +0 -208
  64. package/src/functions/module_lookup.ts +0 -185
  65. package/src/functions/module_math.ts +0 -1252
  66. package/src/functions/module_operators.ts +0 -291
  67. package/src/functions/module_statistical.ts +0 -882
  68. package/src/functions/module_text.ts +0 -370
  69. package/src/helpers/color.ts +0 -30
  70. package/src/helpers/coordinates.ts +0 -71
  71. package/src/helpers/grid_manipulation.ts +0 -68
  72. package/src/helpers/index.ts +0 -7
  73. package/src/helpers/misc.ts +0 -76
  74. package/src/helpers/numbers.ts +0 -117
  75. package/src/helpers/uuid.ts +0 -19
  76. package/src/helpers/zones.ts +0 -263
  77. package/src/history.ts +0 -186
  78. package/src/index.ts +0 -84
  79. package/src/model.ts +0 -261
  80. package/src/plugins/autofill.ts +0 -412
  81. package/src/plugins/chart.ts +0 -404
  82. package/src/plugins/clipboard.ts +0 -461
  83. package/src/plugins/conditional_format.ts +0 -445
  84. package/src/plugins/core.ts +0 -1502
  85. package/src/plugins/edition.ts +0 -157
  86. package/src/plugins/evaluation.ts +0 -428
  87. package/src/plugins/figures.ts +0 -123
  88. package/src/plugins/formatting.ts +0 -630
  89. package/src/plugins/highlight.ts +0 -187
  90. package/src/plugins/index.ts +0 -32
  91. package/src/plugins/merge.ts +0 -524
  92. package/src/plugins/renderer.ts +0 -571
  93. package/src/plugins/selection.ts +0 -562
  94. package/src/plugins/selection_inputs.ts +0 -326
  95. package/src/registries/autofill_modifiers.ts +0 -76
  96. package/src/registries/autofill_rules.ts +0 -98
  97. package/src/registries/figure_registry.ts +0 -30
  98. package/src/registries/index.ts +0 -7
  99. package/src/registries/menu_items_registry.ts +0 -110
  100. package/src/registries/menus/cell_menu_registry.ts +0 -79
  101. package/src/registries/menus/col_menu_registry.ts +0 -63
  102. package/src/registries/menus/index.ts +0 -6
  103. package/src/registries/menus/menu_items_actions.ts +0 -425
  104. package/src/registries/menus/row_menu_registry.ts +0 -63
  105. package/src/registries/menus/sheet_menu_registry.ts +0 -75
  106. package/src/registries/menus/topbar_menu_registry.ts +0 -204
  107. package/src/registries/side_panel_registry.ts +0 -26
  108. package/src/registries/topbar_component_registry.ts +0 -12
  109. package/src/registry.ts +0 -51
  110. package/src/translation.ts +0 -44
  111. package/src/types/autofill.ts +0 -48
  112. package/src/types/chart.ts +0 -26
  113. package/src/types/commands.ts +0 -716
  114. package/src/types/conditional_formatting.ts +0 -124
  115. package/src/types/env.ts +0 -13
  116. package/src/types/functions.ts +0 -35
  117. package/src/types/getters.ts +0 -103
  118. package/src/types/index.ts +0 -20
  119. package/src/types/misc.ts +0 -143
  120. package/src/types/rendering.ts +0 -41
  121. package/src/types/workbook_data.ts +0 -62
  122. package/tests/__mocks__/uuid.ts +0 -7
  123. package/tests/canvas.mock.ts +0 -34
  124. package/tests/components/__mocks__/content_editable_helper.ts +0 -79
  125. package/tests/components/__mocks__/scrollbar.ts +0 -18
  126. package/tests/components/__snapshots__/autocomplete_dropdown_test.ts.snap +0 -29
  127. package/tests/components/__snapshots__/bottom_bar_test.ts.snap +0 -75
  128. package/tests/components/__snapshots__/context_menu_test.ts.snap +0 -88
  129. package/tests/components/__snapshots__/grid_test.ts.snap +0 -60
  130. package/tests/components/__snapshots__/spreadsheet_test.ts.snap +0 -455
  131. package/tests/components/__snapshots__/top_bar_test.ts.snap +0 -705
  132. package/tests/components/autocomplete_dropdown_test.ts +0 -315
  133. package/tests/components/autofill_test.ts +0 -167
  134. package/tests/components/bottom_bar_test.ts +0 -262
  135. package/tests/components/chart_side_panel_test.ts +0 -123
  136. package/tests/components/composer_test.ts +0 -400
  137. package/tests/components/context_menu_test.ts +0 -825
  138. package/tests/components/grid_manipulation_test.ts +0 -163
  139. package/tests/components/grid_test.ts +0 -581
  140. package/tests/components/overlay_test.ts +0 -541
  141. package/tests/components/selection_input_test.ts +0 -259
  142. package/tests/components/side_panel_test.ts +0 -148
  143. package/tests/components/spreadsheet_test.ts +0 -194
  144. package/tests/components/top_bar_test.ts +0 -427
  145. package/tests/data_test.ts +0 -175
  146. package/tests/dom_helper.ts +0 -42
  147. package/tests/formulas/__snapshots__/compiler_test.ts.snap +0 -302
  148. package/tests/formulas/compiler_test.ts +0 -266
  149. package/tests/formulas/composer_tokenizer_test.ts +0 -137
  150. package/tests/formulas/expressions_test.ts +0 -57
  151. package/tests/formulas/formulas_test.ts +0 -80
  152. package/tests/formulas/normalize_test.ts +0 -82
  153. package/tests/formulas/parser_test.ts +0 -224
  154. package/tests/formulas/range_tokenizer_test.ts +0 -187
  155. package/tests/formulas/tokenizer_test.ts +0 -164
  156. package/tests/functions/arguments_test.ts +0 -141
  157. package/tests/functions/dates_test.ts +0 -1081
  158. package/tests/functions/functions_test.ts +0 -53
  159. package/tests/functions/helper_test.ts +0 -98
  160. package/tests/functions/module_database_test.ts +0 -311
  161. package/tests/functions/module_date_test.ts +0 -941
  162. package/tests/functions/module_info_test.ts +0 -139
  163. package/tests/functions/module_logical_test.ts +0 -369
  164. package/tests/functions/module_lookup_test.ts +0 -541
  165. package/tests/functions/module_math_test.ts +0 -2482
  166. package/tests/functions/module_operators_test.ts +0 -955
  167. package/tests/functions/module_statistical_test.ts +0 -2014
  168. package/tests/functions/module_text_test.ts +0 -667
  169. package/tests/helpers/coordinates_test.ts +0 -25
  170. package/tests/helpers/misc_test.ts +0 -95
  171. package/tests/helpers/numbers_test.ts +0 -196
  172. package/tests/helpers/zones_test.ts +0 -97
  173. package/tests/helpers.ts +0 -384
  174. package/tests/menu_items_registry_test.ts +0 -540
  175. package/tests/model/plugins/__snapshots__/chart_test.ts.snap +0 -90
  176. package/tests/model/plugins/chart_test.ts +0 -562
  177. package/tests/model_test.ts +0 -82
  178. package/tests/plugins/__snapshots__/conditional_formatting_test.ts.snap +0 -131
  179. package/tests/plugins/__snapshots__/renderer_test.ts.snap +0 -371
  180. package/tests/plugins/autofill_test.ts +0 -457
  181. package/tests/plugins/borders_test.ts +0 -295
  182. package/tests/plugins/clipboard_test.ts +0 -1180
  183. package/tests/plugins/conditional_formatting_test.ts +0 -1253
  184. package/tests/plugins/core_test.ts +0 -614
  185. package/tests/plugins/edition_test.ts +0 -100
  186. package/tests/plugins/evaluation_async_test.ts +0 -332
  187. package/tests/plugins/evaluation_dates_test.ts +0 -79
  188. package/tests/plugins/evaluation_test.ts +0 -901
  189. package/tests/plugins/figures_test.ts +0 -327
  190. package/tests/plugins/formatting_test.ts +0 -391
  191. package/tests/plugins/grid_manipulation_test.ts +0 -1366
  192. package/tests/plugins/highlight_test.ts +0 -413
  193. package/tests/plugins/history_test.ts +0 -142
  194. package/tests/plugins/import_export_test.ts +0 -276
  195. package/tests/plugins/merges_test.ts +0 -490
  196. package/tests/plugins/navigation_test.ts +0 -181
  197. package/tests/plugins/plugins/evaluation_test.ts +0 -111
  198. package/tests/plugins/renderer_test.ts +0 -598
  199. package/tests/plugins/resizing_test.ts +0 -152
  200. package/tests/plugins/selection_input_test.ts +0 -409
  201. package/tests/plugins/selection_test.ts +0 -442
  202. package/tests/plugins/sheets_test.ts +0 -643
  203. package/tests/plugins/style_test.ts +0 -90
  204. package/tsconfig.json +0 -22
@@ -1,901 +0,0 @@
1
- import { args, functionRegistry } from "../../src/functions";
2
- import { Model } from "../../src/model";
3
- import "../canvas.mock";
4
- import { evaluateCell, evaluateGrid, getCell, waitForRecompute } from "../helpers";
5
-
6
- describe("evaluateCells", () => {
7
- test("Simple Evaluation", () => {
8
- const grid = { A1: "1", B1: "2", C1: "=SUM(A1,B1)" };
9
- expect(evaluateCell("C1", grid)).toBe(3);
10
- });
11
-
12
- test("Various numbers representations", () => {
13
- const grid = {
14
- A1: "1",
15
- A2: "1.1",
16
- A3: "1,234",
17
- A4: "1,234.43",
18
- A5: ".3",
19
- B1: "1%",
20
- B2: "1.5%",
21
- B3: "-3.3%",
22
- C1: "1.2e4",
23
- C2: "1e5",
24
- C3: "-1e3",
25
- D1: "1.1.1", // not a number
26
- };
27
- expect(evaluateGrid(grid)).toEqual({
28
- A1: 1,
29
- A2: 1.1,
30
- A3: 1234,
31
- A4: 1234.43,
32
- A5: 0.3,
33
- B1: 0.01,
34
- B2: 0.015,
35
- B3: -0.033,
36
- C1: 12000,
37
- C2: 100000,
38
- C3: -1000,
39
- D1: "1.1.1",
40
- });
41
- });
42
-
43
- test("Various numbers representations in formulas", () => {
44
- const grid = {
45
- A1: "=1",
46
- A2: "=1.1",
47
- A3: "=1,234",
48
- A4: "=1,234.43",
49
- A5: "=.3",
50
- B1: "=1%",
51
- B2: "=1.5%",
52
- B3: "=-3.3%",
53
- C1: "=1.2e4",
54
- C2: "=1e5",
55
- C3: "=-1e3",
56
- D1: "=1.1.1", // not a number
57
- };
58
- expect(evaluateGrid(grid)).toEqual({
59
- A1: 1,
60
- A2: 1.1,
61
- A3: "#BAD_EXPR", // commas are not allowed as thousand separator in formulas
62
- A4: "#BAD_EXPR",
63
- A5: 0.3,
64
- B1: 0.01,
65
- B2: 0.015,
66
- B3: -0.033,
67
- C1: 12000,
68
- C2: 100000,
69
- C3: -1000,
70
- D1: "#BAD_EXPR",
71
- });
72
- });
73
-
74
- test("With empty content", () => {
75
- const grid = { A1: "1", B1: "", C1: "=SUM(A1,B1)" };
76
- expect(evaluateCell("C1", grid)).toBe(1);
77
- });
78
-
79
- test("With empty cell", () => {
80
- const grid = { A1: "1", C1: "=SUM(A1,B1)" };
81
- expect(evaluateCell("C1", grid)).toBe(1);
82
- });
83
-
84
- test("handling some errors", () => {
85
- const grid = { A1: "=A1", A2: "=A1", A3: "=+", A4: "=1 + A3", A5: "=sum('asdf')" };
86
- const result = evaluateGrid(grid);
87
- expect(result.A1).toBe("#CYCLE");
88
- expect(result.A2).toBe("#ERROR");
89
- expect(result.A3).toBe("#BAD_EXPR");
90
- expect(result.A4).toBe("#ERROR");
91
- expect(result.A5).toBe("#BAD_EXPR");
92
- });
93
-
94
- test("error in some function calls", () => {
95
- const model = new Model();
96
- model.dispatch("SET_VALUE", { xc: "A1", text: '=Sum("asdf")' });
97
-
98
- expect(getCell(model, "A1")!.value).toBe("#ERROR");
99
- expect(getCell(model, "A1")!.error).toBe(
100
- `The function SUM expects a number value, but 'asdf' is a string, and cannot be coerced to a number.`
101
- );
102
-
103
- model.dispatch("SET_VALUE", { xc: "A1", text: "=DECIMAL(1,100)" });
104
- expect(getCell(model, "A1")!.error).toBe(
105
- `Function DECIMAL expects the parameter 'base' to be between 2 and 36 inclusive. Change 'base' from [100] to a value between 2 and 36.`
106
- );
107
- });
108
-
109
- test("error in an addition", () => {
110
- const model = new Model();
111
- model.dispatch("SET_VALUE", { xc: "A1", text: "1" });
112
- model.dispatch("SET_VALUE", { xc: "A2", text: "2" });
113
- model.dispatch("SET_VALUE", { xc: "A3", text: "=A1+A2" });
114
-
115
- expect(getCell(model, "A3")!.value).toBe(3);
116
- model.dispatch("SET_VALUE", { xc: "A2", text: "asdf" });
117
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
118
- expect(getCell(model, "A3")!.error).toBe(
119
- `The function ADD expects a number value, but 'asdf' is a string, and cannot be coerced to a number.`
120
- );
121
- model.dispatch("SET_VALUE", { xc: "A1", text: "33" });
122
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
123
- model.dispatch("SET_VALUE", { xc: "A2", text: "10" });
124
- expect(getCell(model, "A3")!.value).toBe(43);
125
- });
126
-
127
- test("error in an subtraction", () => {
128
- const model = new Model();
129
- model.dispatch("SET_VALUE", { xc: "A1", text: "1" });
130
- model.dispatch("SET_VALUE", { xc: "A2", text: "2" });
131
- model.dispatch("SET_VALUE", { xc: "A3", text: "=A1-A2" });
132
-
133
- expect(getCell(model, "A3")!.value).toBe(-1);
134
- model.dispatch("SET_VALUE", { xc: "A2", text: "asdf" });
135
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
136
- model.dispatch("SET_VALUE", { xc: "A1", text: "33" });
137
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
138
- expect(getCell(model, "A3")!.error).toBe(
139
- `The function MINUS expects a number value, but 'asdf' is a string, and cannot be coerced to a number.`
140
- );
141
- model.dispatch("SET_VALUE", { xc: "A2", text: "10" });
142
- expect(getCell(model, "A3")!.value).toBe(23);
143
- });
144
-
145
- test("error in a multiplication", () => {
146
- const model = new Model();
147
- model.dispatch("SET_VALUE", { xc: "A1", text: "1" });
148
- model.dispatch("SET_VALUE", { xc: "A2", text: "2" });
149
- model.dispatch("SET_VALUE", { xc: "A3", text: "=A1*A2" });
150
-
151
- expect(getCell(model, "A3")!.value).toBe(2);
152
- model.dispatch("SET_VALUE", { xc: "A2", text: "asdf" });
153
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
154
- model.dispatch("SET_VALUE", { xc: "A1", text: "33" });
155
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
156
- model.dispatch("SET_VALUE", { xc: "A2", text: "10" });
157
- expect(getCell(model, "A3")!.value).toBe(330);
158
- });
159
-
160
- test("error in a division", () => {
161
- const model = new Model();
162
- model.dispatch("SET_VALUE", { xc: "A1", text: "1" });
163
- model.dispatch("SET_VALUE", { xc: "A2", text: "2" });
164
- model.dispatch("SET_VALUE", { xc: "A3", text: "=A1/A2" });
165
-
166
- expect(getCell(model, "A3")!.value).toBe(0.5);
167
- model.dispatch("SET_VALUE", { xc: "A2", text: "asdf" });
168
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
169
- model.dispatch("SET_VALUE", { xc: "A1", text: "30" });
170
- expect(getCell(model, "A3")!.value).toBe("#ERROR");
171
- model.dispatch("SET_VALUE", { xc: "A2", text: "10" });
172
- expect(getCell(model, "A3")!.value).toBe(3);
173
- });
174
-
175
- test("error in range vlookup", () => {
176
- const model = new Model();
177
- expect(model.getters.getNumberRows(model.getters.getActiveSheet())).toBeLessThan(200);
178
- model.dispatch("SET_VALUE", { xc: "A1", text: "=VLOOKUP(D12, A2:A200, 2, false)" });
179
-
180
- expect(getCell(model, "A1")!.error!.toString()).toBe(
181
- "VLOOKUP evaluates to an out of bounds range."
182
- );
183
- });
184
-
185
- test("range", () => {
186
- const model = new Model();
187
- model.dispatch("SET_VALUE", { xc: "D4", text: "42" });
188
- model.dispatch("SET_VALUE", { xc: "A1", text: "=sum(A2:Z10)" });
189
-
190
- expect(getCell(model, "A1")!.value).toBe(42);
191
- });
192
-
193
- test("=Range", () => {
194
- const model = new Model();
195
- model.dispatch("SET_VALUE", { xc: "A1", text: "=A2:A3" });
196
- expect(getCell(model, "A1")!.value).toBe("#ERROR");
197
- });
198
-
199
- test("misc math formulas", () => {
200
- const model = new Model();
201
- model.dispatch("SET_VALUE", { xc: "A1", text: "42" });
202
- model.dispatch("SET_VALUE", { xc: "A2", text: "2" });
203
- model.dispatch("SET_VALUE", { xc: "B3", text: "2.3" });
204
- model.dispatch("SET_VALUE", { xc: "C1", text: "=countblank(A1:A10)" });
205
- model.dispatch("SET_VALUE", { xc: "C2", text: "=sum(A1,B1)" });
206
- model.dispatch("SET_VALUE", { xc: "C3", text: "=countblank(B1:A1)" });
207
- model.dispatch("SET_VALUE", { xc: "C4", text: "=floor(B3)" });
208
- model.dispatch("SET_VALUE", { xc: "C5", text: "=floor(A8)" });
209
- model.dispatch("SET_VALUE", { xc: "C6", text: "=sum(A1:A4,B1:B5)" });
210
-
211
- expect(getCell(model, "C1")!.value).toBe(8);
212
- expect(getCell(model, "C2")!.value).toBe(42);
213
- expect(getCell(model, "C3")!.value).toBe(1);
214
- expect(getCell(model, "C4")!.value).toBe(2);
215
- expect(getCell(model, "C5")!.value).toBe(0);
216
- expect(getCell(model, "C6")!.value).toBe(46.3);
217
- });
218
-
219
- test("priority of operations", () => {
220
- const model = new Model();
221
- model.dispatch("SET_VALUE", { xc: "A1", text: "=1 + 2 * 3" });
222
- model.dispatch("SET_VALUE", { xc: "A2", text: "=-2*-2" });
223
- model.dispatch("SET_VALUE", { xc: "A3", text: "=-2^2" });
224
- model.dispatch("SET_VALUE", { xc: "A4", text: "=-2^2 + 3" });
225
- model.dispatch("SET_VALUE", { xc: "A5", text: "= - 1 + - 2 * - 3" });
226
- model.dispatch("SET_VALUE", { xc: "A6", text: "=1 & 8 + 2" });
227
- model.dispatch("SET_VALUE", { xc: "A7", text: "=1 & 10 - 2" });
228
-
229
- expect(getCell(model, "A1")!.value).toBe(7);
230
- expect(getCell(model, "A2")!.value).toBe(4);
231
- expect(getCell(model, "A3")!.value).toBe(-4);
232
- expect(getCell(model, "A4")!.value).toBe(-1);
233
- expect(getCell(model, "A5")!.value).toBe(5);
234
- expect(getCell(model, "A6")!.value).toBe("110");
235
- expect(getCell(model, "A7")!.value).toBe("18");
236
- });
237
-
238
- test("& operator", () => {
239
- expect(evaluateCell("A1", { A1: "=A2&A3", A2: "abc", A3: "def" })).toBe("abcdef");
240
- });
241
-
242
- test("<> operator", () => {
243
- expect(evaluateCell("A1", { A1: "=A2<>A3", A2: "abc", A3: "def" })).toBe(true);
244
- });
245
-
246
- test("if with sub expressions", () => {
247
- expect(evaluateCell("A1", { A1: "=IF(A2>0,1,2)", A2: "0" })).toBe(2);
248
- expect(evaluateCell("A1", { A1: "=IF(A2>0,1,2)", A2: "1" })).toBe(1);
249
- expect(evaluateCell("A1", { A1: "=IF(AND(A2>0,A3>0),1,2)", A2: "1", A3: "0" })).toBe(2);
250
- expect(evaluateCell("A1", { A1: "=IF(AND(A2>0,A3>0),1,2)", A2: "1", A3: "1" })).toBe(1);
251
- expect(evaluateCell("A1", { A1: "=IF(A2>=SUM(A2,A3),1,2)", A2: "1", A3: "0" })).toBe(1);
252
- expect(evaluateCell("A1", { A1: "=IF(A2>SUM(A2,A3),1,2)", A2: "1", A3: "1" })).toBe(2);
253
- expect(evaluateCell("A1", { A1: "=IF(A2=0,1+1,sum(A2,A3))", A2: "0", A3: "10" })).toBe(2);
254
- expect(evaluateCell("A1", { A1: "=IF(A2<>0,1+1,sum(A2,A3))", A2: "0", A3: "10" })).toBe(10);
255
- });
256
-
257
- test("various expressions with boolean", () => {
258
- const model = new Model();
259
-
260
- model.dispatch("SET_VALUE", { xc: "A1", text: "FALSE" });
261
- model.dispatch("SET_VALUE", { xc: "A2", text: "TRUE" });
262
- model.dispatch("SET_VALUE", { xc: "A3", text: "false" });
263
- model.dispatch("SET_VALUE", { xc: "A4", text: "true" });
264
- model.dispatch("SET_VALUE", { xc: "A5", text: "FaLsE" });
265
- model.dispatch("SET_VALUE", { xc: "A6", text: "TrUe" });
266
-
267
- expect(getCell(model, "A1")!.value).toBe(false);
268
- expect(getCell(model, "A2")!.value).toBe(true);
269
- expect(getCell(model, "A3")!.value).toBe(false);
270
- expect(getCell(model, "A4")!.value).toBe(true);
271
- expect(getCell(model, "A5")!.value).toBe(false);
272
- expect(getCell(model, "A6")!.value).toBe(true);
273
-
274
- model.dispatch("SET_VALUE", { xc: "B1", text: "=FALSE" });
275
- model.dispatch("SET_VALUE", { xc: "B2", text: "=TRUE" });
276
- model.dispatch("SET_VALUE", { xc: "B3", text: "=false" });
277
- model.dispatch("SET_VALUE", { xc: "B4", text: "=true" });
278
- model.dispatch("SET_VALUE", { xc: "B5", text: "=FaLsE" });
279
- model.dispatch("SET_VALUE", { xc: "B6", text: "=TrUe" });
280
-
281
- expect(getCell(model, "B1")!.value).toBe(false);
282
- expect(getCell(model, "B2")!.value).toBe(true);
283
- expect(getCell(model, "B3")!.value).toBe(false);
284
- expect(getCell(model, "B4")!.value).toBe(true);
285
- expect(getCell(model, "B5")!.value).toBe(false);
286
- expect(getCell(model, "B6")!.value).toBe(true);
287
-
288
- model.dispatch("SET_VALUE", { xc: "A1", text: " FALSE " });
289
- model.dispatch("SET_VALUE", { xc: "A2", text: " TRUE " });
290
- model.dispatch("SET_VALUE", { xc: "A3", text: " false " });
291
- model.dispatch("SET_VALUE", { xc: "A4", text: " true " });
292
- model.dispatch("SET_VALUE", { xc: "A5", text: " FaLsE " });
293
- model.dispatch("SET_VALUE", { xc: "A6", text: " TrUe " });
294
-
295
- expect(getCell(model, "A1")!.value).toBe(" FALSE ");
296
- expect(getCell(model, "A2")!.value).toBe(" TRUE ");
297
- expect(getCell(model, "A3")!.value).toBe(" false ");
298
- expect(getCell(model, "A4")!.value).toBe(" true ");
299
- expect(getCell(model, "A5")!.value).toBe(" FaLsE ");
300
- expect(getCell(model, "A6")!.value).toBe(" TrUe ");
301
-
302
- model.dispatch("SET_VALUE", { xc: "B1", text: "= FALSE " });
303
- model.dispatch("SET_VALUE", { xc: "B2", text: "= TRUE " });
304
- model.dispatch("SET_VALUE", { xc: "B3", text: "= false " });
305
- model.dispatch("SET_VALUE", { xc: "B4", text: "= true " });
306
- model.dispatch("SET_VALUE", { xc: "B5", text: "= FaLsE " });
307
- model.dispatch("SET_VALUE", { xc: "B6", text: "= TrUe " });
308
-
309
- expect(getCell(model, "B1")!.value).toBe(false);
310
- expect(getCell(model, "B2")!.value).toBe(true);
311
- expect(getCell(model, "B3")!.value).toBe(false);
312
- expect(getCell(model, "B4")!.value).toBe(true);
313
- expect(getCell(model, "B5")!.value).toBe(false);
314
- expect(getCell(model, "B6")!.value).toBe(true);
315
- });
316
-
317
- test("various expressions with whitespace", () => {
318
- const model = new Model();
319
-
320
- model.dispatch("SET_VALUE", { xc: "A1", text: "" });
321
- model.dispatch("SET_VALUE", { xc: "A2", text: "," });
322
- model.dispatch("SET_VALUE", { xc: "A3", text: " " });
323
- model.dispatch("SET_VALUE", { xc: "A4", text: " , " });
324
- model.dispatch("SET_VALUE", { xc: "A5", text: " 42 " });
325
- model.dispatch("SET_VALUE", { xc: "A6", text: " 42 , 24 " });
326
- model.dispatch("SET_VALUE", { xc: "A7", text: " 43 , " });
327
- model.dispatch("SET_VALUE", { xc: "A8", text: " 44 45 " });
328
-
329
- model.dispatch("SET_VALUE", { xc: "B1", text: "=" });
330
- model.dispatch("SET_VALUE", { xc: "B2", text: "=," });
331
- model.dispatch("SET_VALUE", { xc: "B3", text: "= " });
332
- model.dispatch("SET_VALUE", { xc: "B4", text: "= , " });
333
- model.dispatch("SET_VALUE", { xc: "B5", text: "= 42 " });
334
- model.dispatch("SET_VALUE", { xc: "B6", text: "= 42 , 24 " });
335
- model.dispatch("SET_VALUE", { xc: "B7", text: "= 43 , " });
336
- model.dispatch("SET_VALUE", { xc: "B8", text: "= 44 45 " });
337
-
338
- model.dispatch("SET_VALUE", { xc: "C1", text: "=SUM()" });
339
- model.dispatch("SET_VALUE", { xc: "C2", text: "=SUM(,)" });
340
- model.dispatch("SET_VALUE", { xc: "C3", text: "=SUM( )" });
341
- model.dispatch("SET_VALUE", { xc: "C4", text: "=SUM( , )" });
342
- model.dispatch("SET_VALUE", { xc: "C5", text: "=SUM( 42 )" });
343
- model.dispatch("SET_VALUE", { xc: "C6", text: "=SUM( 42 , 24 )" });
344
- model.dispatch("SET_VALUE", { xc: "C7", text: "=SUM( 43 , )" });
345
- model.dispatch("SET_VALUE", { xc: "C8", text: "=SUM( 44 45 )" });
346
-
347
- model.dispatch("SET_VALUE", { xc: "D1", text: "=COUNT()" });
348
- model.dispatch("SET_VALUE", { xc: "D2", text: "=COUNT(,)" });
349
- model.dispatch("SET_VALUE", { xc: "D3", text: "=COUNT( )" });
350
- model.dispatch("SET_VALUE", { xc: "D4", text: "=COUNT( , )" });
351
- model.dispatch("SET_VALUE", { xc: "D5", text: "=COUNT( 42 )" });
352
- model.dispatch("SET_VALUE", { xc: "D6", text: "=COUNT( 42 , 24 )" });
353
- model.dispatch("SET_VALUE", { xc: "D7", text: "=COUNT( 43 , )" });
354
- model.dispatch("SET_VALUE", { xc: "D8", text: "=COUNT( 44 45 )" });
355
-
356
- expect(getCell(model, "A1")!).toBe(null);
357
- expect(getCell(model, "A2")!.value).toBe(",");
358
- expect(getCell(model, "A3")!.value).toBe(" ");
359
- expect(getCell(model, "A4")!.value).toBe(" , ");
360
- expect(getCell(model, "A5")!.value).toBe(42);
361
- expect(getCell(model, "A6")!.value).toBe(" 42 , 24 ");
362
- expect(getCell(model, "A7")!.value).toBe(" 43 , ");
363
- expect(getCell(model, "A8")!.value).toBe(" 44 45 ");
364
-
365
- expect(getCell(model, "B1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return "There was a problem"
366
- expect(getCell(model, "B2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return "There was a problem"
367
- expect(getCell(model, "B3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return "There was a problem"
368
- expect(getCell(model, "B4")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return "There was a problem"
369
- expect(getCell(model, "B5")!.value).toBe(42);
370
- expect(getCell(model, "B6")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
371
- expect(getCell(model, "B7")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return "There was a problem"
372
- expect(getCell(model, "B8")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
373
-
374
- expect(getCell(model, "C1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #N/A
375
- expect(getCell(model, "C2")!.value).toBe(0);
376
- expect(getCell(model, "C3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #N/A
377
- expect(getCell(model, "C4")!.value).toBe(0);
378
- expect(getCell(model, "C5")!.value).toBe(42);
379
- expect(getCell(model, "C6")!.value).toBe(66);
380
- expect(getCell(model, "C7")!.value).toBe(43);
381
- expect(getCell(model, "C8")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
382
-
383
- expect(getCell(model, "D1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #N/A
384
- expect(getCell(model, "D2")!.value).toBe(2);
385
- expect(getCell(model, "D3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #N/A
386
- expect(getCell(model, "D4")!.value).toBe(2);
387
- expect(getCell(model, "D5")!.value).toBe(1);
388
- expect(getCell(model, "D6")!.value).toBe(2);
389
- expect(getCell(model, "D7")!.value).toBe(2);
390
- expect(getCell(model, "D8")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
391
- });
392
-
393
- test("various string expressions with whitespace", () => {
394
- const model = new Model();
395
-
396
- model.dispatch("SET_VALUE", { xc: "A1", text: '""' });
397
- model.dispatch("SET_VALUE", { xc: "A2", text: '","' });
398
- model.dispatch("SET_VALUE", { xc: "A3", text: '" "' });
399
- model.dispatch("SET_VALUE", { xc: "A4", text: '" , "' });
400
- model.dispatch("SET_VALUE", { xc: "A5", text: '" 42 "' });
401
- model.dispatch("SET_VALUE", { xc: "A6", text: '" 42 , 24 "' });
402
- model.dispatch("SET_VALUE", { xc: "A7", text: '" 43 , "' });
403
- model.dispatch("SET_VALUE", { xc: "A8", text: '" 44 45 "' });
404
-
405
- model.dispatch("SET_VALUE", { xc: "B1", text: '=""' });
406
- model.dispatch("SET_VALUE", { xc: "B2", text: '=","' });
407
- model.dispatch("SET_VALUE", { xc: "B3", text: '=" "' });
408
- model.dispatch("SET_VALUE", { xc: "B4", text: '=" , "' });
409
- model.dispatch("SET_VALUE", { xc: "B5", text: '=" 42 "' });
410
- model.dispatch("SET_VALUE", { xc: "B6", text: '=" 42 , 24 "' });
411
- model.dispatch("SET_VALUE", { xc: "B7", text: '=" 43 , "' });
412
- model.dispatch("SET_VALUE", { xc: "B8", text: '=" 44 45 "' });
413
-
414
- model.dispatch("SET_VALUE", { xc: "C1", text: '=SUM("")' });
415
- model.dispatch("SET_VALUE", { xc: "C2", text: '=SUM(",")' });
416
- model.dispatch("SET_VALUE", { xc: "C3", text: '=SUM(" ")' });
417
- model.dispatch("SET_VALUE", { xc: "C4", text: '=SUM(" , ")' });
418
- model.dispatch("SET_VALUE", { xc: "C5", text: '=SUM(" 42 ")' });
419
- model.dispatch("SET_VALUE", { xc: "C6", text: '=SUM(" 42 , 24 ")' });
420
- model.dispatch("SET_VALUE", { xc: "C7", text: '=SUM(" 43 , ")' });
421
- model.dispatch("SET_VALUE", { xc: "C8", text: '=SUM(" 44 45 ")' });
422
-
423
- model.dispatch("SET_VALUE", { xc: "D1", text: '=COUNT("")' });
424
- model.dispatch("SET_VALUE", { xc: "D2", text: '=COUNT(",")' });
425
- model.dispatch("SET_VALUE", { xc: "D3", text: '=COUNT(" ")' });
426
- model.dispatch("SET_VALUE", { xc: "D4", text: '=COUNT(" , ")' });
427
- model.dispatch("SET_VALUE", { xc: "D5", text: '=COUNT(" 42 ")' });
428
- model.dispatch("SET_VALUE", { xc: "D6", text: '=COUNT(" 42 , 24 ")' });
429
- model.dispatch("SET_VALUE", { xc: "D7", text: '=COUNT(" 43 , ")' });
430
- model.dispatch("SET_VALUE", { xc: "D8", text: '=COUNT(" 44 45 ")' });
431
-
432
- expect(getCell(model, "A1")!.value).toBe('""');
433
- expect(getCell(model, "A2")!.value).toBe('","');
434
- expect(getCell(model, "A3")!.value).toBe('" "');
435
- expect(getCell(model, "A4")!.value).toBe('" , "');
436
- expect(getCell(model, "A5")!.value).toBe('" 42 "');
437
- expect(getCell(model, "A6")!.value).toBe('" 42 , 24 "');
438
- expect(getCell(model, "A7")!.value).toBe('" 43 , "');
439
- expect(getCell(model, "A8")!.value).toBe('" 44 45 "');
440
-
441
- expect(getCell(model, "B1")!.value).toBe("");
442
- expect(getCell(model, "B2")!.value).toBe(",");
443
- expect(getCell(model, "B3")!.value).toBe(" ");
444
- expect(getCell(model, "B4")!.value).toBe(" , ");
445
- expect(getCell(model, "B5")!.value).toBe(" 42 ");
446
- expect(getCell(model, "B6")!.value).toBe(" 42 , 24 ");
447
- expect(getCell(model, "B7")!.value).toBe(" 43 , ");
448
- expect(getCell(model, "B8")!.value).toBe(" 44 45 ");
449
-
450
- expect(getCell(model, "C1")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
451
- expect(getCell(model, "C2")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
452
- expect(getCell(model, "C3")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
453
- expect(getCell(model, "C4")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
454
- expect(getCell(model, "C5")!.value).toBe(42);
455
- expect(getCell(model, "C6")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
456
- expect(getCell(model, "C7")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
457
- expect(getCell(model, "C8")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
458
-
459
- expect(getCell(model, "D1")!.value).toBe(0);
460
- expect(getCell(model, "D2")!.value).toBe(0);
461
- expect(getCell(model, "D3")!.value).toBe(0);
462
- expect(getCell(model, "D4")!.value).toBe(0);
463
- expect(getCell(model, "D5")!.value).toBe(1);
464
- expect(getCell(model, "D6")!.value).toBe(0);
465
- expect(getCell(model, "D7")!.value).toBe(0);
466
- expect(getCell(model, "D8")!.value).toBe(0);
467
- });
468
-
469
- test("various expressions with dot", () => {
470
- const model = new Model();
471
-
472
- model.dispatch("SET_VALUE", { xc: "A1", text: "4.2" });
473
- model.dispatch("SET_VALUE", { xc: "A2", text: "4." });
474
- model.dispatch("SET_VALUE", { xc: "A3", text: ".2" });
475
-
476
- model.dispatch("SET_VALUE", { xc: "B1", text: "=4.2" });
477
- model.dispatch("SET_VALUE", { xc: "B2", text: "=4." });
478
- model.dispatch("SET_VALUE", { xc: "B3", text: "=.2" });
479
-
480
- model.dispatch("SET_VALUE", { xc: "C1", text: "=SUM(4.2)" });
481
- model.dispatch("SET_VALUE", { xc: "C2", text: "=SUM(4.)" });
482
- model.dispatch("SET_VALUE", { xc: "C3", text: "=SUM(.2)" });
483
-
484
- model.dispatch("SET_VALUE", { xc: "D1", text: "=COUNT(4.2)" });
485
- model.dispatch("SET_VALUE", { xc: "D2", text: "=COUNT(4.)" });
486
- model.dispatch("SET_VALUE", { xc: "D3", text: "=COUNT(.2)" });
487
-
488
- expect(getCell(model, "A1")!.value).toBe(4.2);
489
- expect(getCell(model, "A2")!.value).toBe(4);
490
- expect(getCell(model, "A3")!.value).toBe(0.2);
491
-
492
- expect(getCell(model, "B1")!.value).toBe(4.2);
493
- expect(getCell(model, "B2")!.value).toBe(4);
494
- expect(getCell(model, "B3")!.value).toBe(0.2);
495
-
496
- expect(getCell(model, "C1")!.value).toBe(4.2);
497
- expect(getCell(model, "C2")!.value).toBe(4);
498
- expect(getCell(model, "C3")!.value).toBe(0.2);
499
-
500
- expect(getCell(model, "D1")!.value).toBe(1);
501
- expect(getCell(model, "D2")!.value).toBe(1);
502
- expect(getCell(model, "D3")!.value).toBe(1);
503
- });
504
-
505
- test("various string expressions with dot", () => {
506
- const model = new Model();
507
- model.dispatch("SET_VALUE", { xc: "A1", text: '"4.2"' });
508
- model.dispatch("SET_VALUE", { xc: "A2", text: '"4."' });
509
- model.dispatch("SET_VALUE", { xc: "A3", text: '".2"' });
510
-
511
- model.dispatch("SET_VALUE", { xc: "B1", text: '="4.2"' });
512
- model.dispatch("SET_VALUE", { xc: "B2", text: '="4."' });
513
- model.dispatch("SET_VALUE", { xc: "B3", text: '=".2"' });
514
-
515
- model.dispatch("SET_VALUE", { xc: "C1", text: '=SUM("4.2")' });
516
- model.dispatch("SET_VALUE", { xc: "C2", text: '=SUM("4.")' });
517
- model.dispatch("SET_VALUE", { xc: "C3", text: '=SUM(".2")' });
518
-
519
- model.dispatch("SET_VALUE", { xc: "D1", text: '=COUNT("4.2")' });
520
- model.dispatch("SET_VALUE", { xc: "D2", text: '=COUNT("4.")' });
521
- model.dispatch("SET_VALUE", { xc: "D3", text: '=COUNT(".2")' });
522
-
523
- expect(getCell(model, "A1")!.value).toBe('"4.2"');
524
- expect(getCell(model, "A2")!.value).toBe('"4."');
525
- expect(getCell(model, "A3")!.value).toBe('".2"');
526
-
527
- expect(getCell(model, "B1")!.value).toBe("4.2");
528
- expect(getCell(model, "B2")!.value).toBe("4.");
529
- expect(getCell(model, "B3")!.value).toBe(".2");
530
-
531
- expect(getCell(model, "C1")!.value).toBe(4.2);
532
- expect(getCell(model, "C2")!.value).toBe(4);
533
- expect(getCell(model, "C3")!.value).toBe(0.2);
534
-
535
- expect(getCell(model, "D1")!.value).toBe(1);
536
- expect(getCell(model, "D2")!.value).toBe(1);
537
- expect(getCell(model, "D3")!.value).toBe(1);
538
- });
539
-
540
- test("various expressions with dot and whitespace", () => {
541
- const model = new Model();
542
- model.dispatch("SET_VALUE", { xc: "A1", text: "42 .24" });
543
- model.dispatch("SET_VALUE", { xc: "A2", text: "42. 24" });
544
- model.dispatch("SET_VALUE", { xc: "A3", text: "42 ." });
545
- model.dispatch("SET_VALUE", { xc: "A4", text: "42. " });
546
- model.dispatch("SET_VALUE", { xc: "A5", text: " .24" });
547
- model.dispatch("SET_VALUE", { xc: "A6", text: ". 24" });
548
-
549
- model.dispatch("SET_VALUE", { xc: "B1", text: "=42 .24" });
550
- model.dispatch("SET_VALUE", { xc: "B2", text: "=42. 24" });
551
- model.dispatch("SET_VALUE", { xc: "B3", text: "=42 ." });
552
- model.dispatch("SET_VALUE", { xc: "B4", text: "=42. " });
553
- model.dispatch("SET_VALUE", { xc: "B5", text: "= .24" });
554
- model.dispatch("SET_VALUE", { xc: "B6", text: "=. 24" });
555
-
556
- model.dispatch("SET_VALUE", { xc: "C1", text: "=SUM(42 .24)" });
557
- model.dispatch("SET_VALUE", { xc: "C2", text: "=SUM(42. 24)" });
558
- model.dispatch("SET_VALUE", { xc: "C3", text: "=SUM(42 .)" });
559
- model.dispatch("SET_VALUE", { xc: "C4", text: "=SUM(42. )" });
560
- model.dispatch("SET_VALUE", { xc: "C5", text: "=SUM( .24)" });
561
- model.dispatch("SET_VALUE", { xc: "C6", text: "=SUM(. 24)" });
562
-
563
- model.dispatch("SET_VALUE", { xc: "D1", text: "=COUNT(42 .24)" });
564
- model.dispatch("SET_VALUE", { xc: "D2", text: "=COUNT(42. 24)" });
565
- model.dispatch("SET_VALUE", { xc: "D3", text: "=COUNT(42 .)" });
566
- model.dispatch("SET_VALUE", { xc: "D4", text: "=COUNT(42. )" });
567
- model.dispatch("SET_VALUE", { xc: "D5", text: "=COUNT( .24)" });
568
- model.dispatch("SET_VALUE", { xc: "D6", text: "=COUNT(. 24)" });
569
-
570
- expect(getCell(model, "A1")!.value).toBe("42 .24");
571
- expect(getCell(model, "A2")!.value).toBe("42. 24");
572
- expect(getCell(model, "A3")!.value).toBe("42 .");
573
- expect(getCell(model, "A4")!.value).toBe(42);
574
- expect(getCell(model, "A5")!.value).toBe(0.24);
575
- expect(getCell(model, "A6")!.value).toBe(". 24");
576
-
577
- expect(getCell(model, "B1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
578
- expect(getCell(model, "B2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
579
- expect(getCell(model, "B3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
580
- expect(getCell(model, "B4")!.value).toBe(42);
581
- expect(getCell(model, "B5")!.value).toBe(0.24);
582
- expect(getCell(model, "B6")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
583
-
584
- expect(getCell(model, "C1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
585
- expect(getCell(model, "C2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
586
- expect(getCell(model, "C3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
587
- expect(getCell(model, "C4")!.value).toBe(42);
588
- expect(getCell(model, "C5")!.value).toBe(0.24);
589
- expect(getCell(model, "C6")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
590
-
591
- expect(getCell(model, "D1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
592
- expect(getCell(model, "D2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
593
- expect(getCell(model, "D3")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
594
- expect(getCell(model, "D4")!.value).toBe(1);
595
- expect(getCell(model, "D5")!.value).toBe(1);
596
- expect(getCell(model, "D6")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
597
- });
598
-
599
- test("various string expressions with dot and whitespace", () => {
600
- const model = new Model();
601
- model.dispatch("SET_VALUE", { xc: "A1", text: '"42 .24"' });
602
- model.dispatch("SET_VALUE", { xc: "A2", text: '"42. 24"' });
603
- model.dispatch("SET_VALUE", { xc: "A3", text: '"42 ."' });
604
- model.dispatch("SET_VALUE", { xc: "A4", text: '"42. "' });
605
- model.dispatch("SET_VALUE", { xc: "A5", text: '" .24"' });
606
- model.dispatch("SET_VALUE", { xc: "A6", text: '". 24"' });
607
-
608
- model.dispatch("SET_VALUE", { xc: "B1", text: '="42 .24"' });
609
- model.dispatch("SET_VALUE", { xc: "B2", text: '="42. 24"' });
610
- model.dispatch("SET_VALUE", { xc: "B3", text: '="42 ."' });
611
- model.dispatch("SET_VALUE", { xc: "B4", text: '="42. "' });
612
- model.dispatch("SET_VALUE", { xc: "B5", text: '=" .24"' });
613
- model.dispatch("SET_VALUE", { xc: "B6", text: '=". 24"' });
614
-
615
- model.dispatch("SET_VALUE", { xc: "C1", text: '=SUM("42 .24")' });
616
- model.dispatch("SET_VALUE", { xc: "C2", text: '=SUM("42. 24")' });
617
- model.dispatch("SET_VALUE", { xc: "C3", text: '=SUM("42 .")' });
618
- model.dispatch("SET_VALUE", { xc: "C4", text: '=SUM("42. ")' });
619
- model.dispatch("SET_VALUE", { xc: "C5", text: '=SUM(" .24")' });
620
- model.dispatch("SET_VALUE", { xc: "C6", text: '=SUM(". 24")' });
621
-
622
- model.dispatch("SET_VALUE", { xc: "D1", text: '=COUNT("42 .24")' });
623
- model.dispatch("SET_VALUE", { xc: "D2", text: '=COUNT("42. 24")' });
624
- model.dispatch("SET_VALUE", { xc: "D3", text: '=COUNT("42 .")' });
625
- model.dispatch("SET_VALUE", { xc: "D4", text: '=COUNT("42. ")' });
626
- model.dispatch("SET_VALUE", { xc: "D5", text: '=COUNT(" .24")' });
627
- model.dispatch("SET_VALUE", { xc: "D6", text: '=COUNT(". 24")' });
628
-
629
- expect(getCell(model, "A1")!.value).toBe('"42 .24"');
630
- expect(getCell(model, "A2")!.value).toBe('"42. 24"');
631
- expect(getCell(model, "A3")!.value).toBe('"42 ."');
632
- expect(getCell(model, "A4")!.value).toBe('"42. "');
633
- expect(getCell(model, "A5")!.value).toBe('" .24"');
634
- expect(getCell(model, "A6")!.value).toBe('". 24"');
635
-
636
- expect(getCell(model, "B1")!.value).toBe("42 .24");
637
- expect(getCell(model, "B2")!.value).toBe("42. 24");
638
- expect(getCell(model, "B3")!.value).toBe("42 .");
639
- expect(getCell(model, "B4")!.value).toBe("42. ");
640
- expect(getCell(model, "B5")!.value).toBe(" .24");
641
- expect(getCell(model, "B6")!.value).toBe(". 24");
642
-
643
- expect(getCell(model, "C1")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
644
- expect(getCell(model, "C2")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
645
- expect(getCell(model, "C3")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
646
- expect(getCell(model, "C4")!.value).toBe(42);
647
- expect(getCell(model, "C5")!.value).toBe(0.24);
648
- expect(getCell(model, "C6")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
649
-
650
- expect(getCell(model, "D1")!.value).toBe(0);
651
- expect(getCell(model, "D2")!.value).toBe(0);
652
- expect(getCell(model, "D3")!.value).toBe(0);
653
- expect(getCell(model, "D4")!.value).toBe(1);
654
- expect(getCell(model, "D5")!.value).toBe(1);
655
- expect(getCell(model, "D6")!.value).toBe(0);
656
- });
657
-
658
- test("various expressions with percent, dot and whitespace", () => {
659
- const model = new Model();
660
- model.dispatch("SET_VALUE", { xc: "A1", text: "%" });
661
- model.dispatch("SET_VALUE", { xc: "A2", text: " %" });
662
- model.dispatch("SET_VALUE", { xc: "A3", text: "40%" });
663
- model.dispatch("SET_VALUE", { xc: "A4", text: " 41% " });
664
- model.dispatch("SET_VALUE", { xc: "A5", text: "42 %" });
665
- model.dispatch("SET_VALUE", { xc: "A6", text: " 43 % " });
666
- model.dispatch("SET_VALUE", { xc: "A7", text: "4.1%" });
667
- model.dispatch("SET_VALUE", { xc: "A8", text: " 4.2% " });
668
- model.dispatch("SET_VALUE", { xc: "A9", text: ".1%" });
669
- model.dispatch("SET_VALUE", { xc: "A10", text: " .2% " });
670
- model.dispatch("SET_VALUE", { xc: "A11", text: "3.%" });
671
- model.dispatch("SET_VALUE", { xc: "A12", text: " 4.% " });
672
-
673
- model.dispatch("SET_VALUE", { xc: "B1", text: "=%" });
674
- model.dispatch("SET_VALUE", { xc: "B2", text: "= %" });
675
- model.dispatch("SET_VALUE", { xc: "B3", text: "=40%" });
676
- model.dispatch("SET_VALUE", { xc: "B4", text: "= 41% " });
677
- model.dispatch("SET_VALUE", { xc: "B5", text: "=42 %" });
678
- model.dispatch("SET_VALUE", { xc: "B6", text: "= 43 % " });
679
- model.dispatch("SET_VALUE", { xc: "B7", text: "=4.1%" });
680
- model.dispatch("SET_VALUE", { xc: "B8", text: "= 4.2% " });
681
- model.dispatch("SET_VALUE", { xc: "B9", text: "=.1%" });
682
- model.dispatch("SET_VALUE", { xc: "B10", text: "= .2% " });
683
- model.dispatch("SET_VALUE", { xc: "B11", text: "=3.%" });
684
- model.dispatch("SET_VALUE", { xc: "B12", text: "= 4.% " });
685
-
686
- model.dispatch("SET_VALUE", { xc: "C1", text: "=SUM(%)" });
687
- model.dispatch("SET_VALUE", { xc: "C2", text: "=SUM( %)" });
688
- model.dispatch("SET_VALUE", { xc: "C3", text: "=SUM(40%)" });
689
- model.dispatch("SET_VALUE", { xc: "C4", text: "=SUM( 41% )" });
690
- model.dispatch("SET_VALUE", { xc: "C5", text: "=SUM(42 %)" });
691
- model.dispatch("SET_VALUE", { xc: "C6", text: "=SUM( 43 % )" });
692
- model.dispatch("SET_VALUE", { xc: "C7", text: "=SUM(4.1%)" });
693
- model.dispatch("SET_VALUE", { xc: "C8", text: "=SUM( 4.2% )" });
694
- model.dispatch("SET_VALUE", { xc: "C9", text: "=SUM(.1%)" });
695
- model.dispatch("SET_VALUE", { xc: "C10", text: "=SUM( .2% )" });
696
- model.dispatch("SET_VALUE", { xc: "C11", text: "=SUM(3.%)" });
697
- model.dispatch("SET_VALUE", { xc: "C12", text: "=SUM( 4.% )" });
698
-
699
- model.dispatch("SET_VALUE", { xc: "D1", text: "=COUNT(%)" });
700
- model.dispatch("SET_VALUE", { xc: "D2", text: "=COUNT( %)" });
701
- model.dispatch("SET_VALUE", { xc: "D3", text: "=COUNT(40%)" });
702
- model.dispatch("SET_VALUE", { xc: "D4", text: "=COUNT( 41% )" });
703
- model.dispatch("SET_VALUE", { xc: "D5", text: "=COUNT(42 %)" });
704
- model.dispatch("SET_VALUE", { xc: "D6", text: "=COUNT( 43 % )" });
705
- model.dispatch("SET_VALUE", { xc: "D7", text: "=COUNT(4.1%)" });
706
- model.dispatch("SET_VALUE", { xc: "D8", text: "=COUNT( 4.2% )" });
707
- model.dispatch("SET_VALUE", { xc: "D9", text: "=COUNT(.1%)" });
708
- model.dispatch("SET_VALUE", { xc: "D10", text: "=COUNT( .2% )" });
709
- model.dispatch("SET_VALUE", { xc: "D11", text: "=COUNT(3.%)" });
710
- model.dispatch("SET_VALUE", { xc: "D12", text: "=COUNT( 4.% )" });
711
-
712
- expect(getCell(model, "A1")!.value).toBe("%");
713
- expect(getCell(model, "A2")!.value).toBe(" %");
714
- expect(getCell(model, "A3")!.value).toBe(0.4);
715
- expect(getCell(model, "A4")!.value).toBe(0.41);
716
- expect(getCell(model, "A5")!.value).toBe(0.42);
717
- expect(getCell(model, "A6")!.value).toBe(0.43);
718
- expect(getCell(model, "A7")!.value).toBeCloseTo(0.041, 3);
719
- expect(getCell(model, "A8")!.value).toBe(0.042);
720
- expect(getCell(model, "A9")!.value).toBe(0.001);
721
- expect(getCell(model, "A10")!.value).toBe(0.002);
722
- expect(getCell(model, "A11")!.value).toBe(0.03);
723
- expect(getCell(model, "A12")!.value).toBe(0.04);
724
-
725
- expect(getCell(model, "B1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
726
- expect(getCell(model, "B2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
727
- expect(getCell(model, "B3")!.value).toBe(0.4);
728
- expect(getCell(model, "B4")!.value).toBe(0.41);
729
- expect(getCell(model, "B5")!.value).toBe(0.42);
730
- expect(getCell(model, "B6")!.value).toBe(0.43);
731
- expect(getCell(model, "B7")!.value).toBeCloseTo(0.041, 3);
732
- expect(getCell(model, "B8")!.value).toBe(0.042);
733
- expect(getCell(model, "B9")!.value).toBe(0.001);
734
- expect(getCell(model, "B10")!.value).toBe(0.002);
735
- expect(getCell(model, "B11")!.value).toBe(0.03);
736
- expect(getCell(model, "B12")!.value).toBe(0.04);
737
-
738
- expect(getCell(model, "C1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
739
- expect(getCell(model, "C2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
740
- expect(getCell(model, "C3")!.value).toBe(0.4);
741
- expect(getCell(model, "C4")!.value).toBe(0.41);
742
- expect(getCell(model, "C5")!.value).toBe(0.42);
743
- expect(getCell(model, "C6")!.value).toBe(0.43);
744
- expect(getCell(model, "C7")!.value).toBeCloseTo(0.041, 3);
745
- expect(getCell(model, "C8")!.value).toBe(0.042);
746
- expect(getCell(model, "C9")!.value).toBe(0.001);
747
- expect(getCell(model, "C10")!.value).toBe(0.002);
748
- expect(getCell(model, "C11")!.value).toBe(0.03);
749
- expect(getCell(model, "C12")!.value).toBe(0.04);
750
-
751
- expect(getCell(model, "D1")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
752
- expect(getCell(model, "D2")!.value).toBe("#BAD_EXPR"); // @compatibility: on google sheet, return #ERROR!
753
- expect(getCell(model, "D3")!.value).toBe(1);
754
- expect(getCell(model, "D4")!.value).toBe(1);
755
- expect(getCell(model, "D5")!.value).toBe(1);
756
- expect(getCell(model, "D6")!.value).toBe(1);
757
- expect(getCell(model, "D7")!.value).toBe(1);
758
- expect(getCell(model, "D8")!.value).toBe(1);
759
- expect(getCell(model, "D9")!.value).toBe(1);
760
- expect(getCell(model, "D10")!.value).toBe(1);
761
- expect(getCell(model, "D11")!.value).toBe(1);
762
- expect(getCell(model, "D12")!.value).toBe(1);
763
- });
764
-
765
- test("various string expressions with percent, dot and whitespace", () => {
766
- const model = new Model();
767
-
768
- model.dispatch("SET_VALUE", { xc: "A1", text: '"%"' });
769
- model.dispatch("SET_VALUE", { xc: "A2", text: '" %"' });
770
- model.dispatch("SET_VALUE", { xc: "A3", text: '"40%"' });
771
- model.dispatch("SET_VALUE", { xc: "A4", text: '" 41% "' });
772
- model.dispatch("SET_VALUE", { xc: "A5", text: '"42 %"' });
773
- model.dispatch("SET_VALUE", { xc: "A6", text: '" 43 % "' });
774
- model.dispatch("SET_VALUE", { xc: "A7", text: '"4.1%"' });
775
- model.dispatch("SET_VALUE", { xc: "A8", text: '" 4.2% "' });
776
- model.dispatch("SET_VALUE", { xc: "A9", text: '".1%"' });
777
- model.dispatch("SET_VALUE", { xc: "A10", text: '" .2% "' });
778
- model.dispatch("SET_VALUE", { xc: "A11", text: '"3.%"' });
779
- model.dispatch("SET_VALUE", { xc: "A12", text: '" 4.% "' });
780
-
781
- model.dispatch("SET_VALUE", { xc: "B1", text: '="%"' });
782
- model.dispatch("SET_VALUE", { xc: "B2", text: '=" %"' });
783
- model.dispatch("SET_VALUE", { xc: "B3", text: '="40%"' });
784
- model.dispatch("SET_VALUE", { xc: "B4", text: '=" 41% "' });
785
- model.dispatch("SET_VALUE", { xc: "B5", text: '="42 %"' });
786
- model.dispatch("SET_VALUE", { xc: "B6", text: '=" 43 % "' });
787
- model.dispatch("SET_VALUE", { xc: "B7", text: '="4.1%"' });
788
- model.dispatch("SET_VALUE", { xc: "B8", text: '=" 4.2% "' });
789
- model.dispatch("SET_VALUE", { xc: "B9", text: '=".1%"' });
790
- model.dispatch("SET_VALUE", { xc: "B10", text: '=" .2% "' });
791
- model.dispatch("SET_VALUE", { xc: "B11", text: '="3.%"' });
792
- model.dispatch("SET_VALUE", { xc: "B12", text: '=" 4.% "' });
793
-
794
- model.dispatch("SET_VALUE", { xc: "C1", text: '=SUM("%")' });
795
- model.dispatch("SET_VALUE", { xc: "C2", text: '=SUM(" %")' });
796
- model.dispatch("SET_VALUE", { xc: "C3", text: '=SUM("40%")' });
797
- model.dispatch("SET_VALUE", { xc: "C4", text: '=SUM(" 41% ")' });
798
- model.dispatch("SET_VALUE", { xc: "C5", text: '=SUM("42 %")' });
799
- model.dispatch("SET_VALUE", { xc: "C6", text: '=SUM(" 43 % ")' });
800
- model.dispatch("SET_VALUE", { xc: "C7", text: '=SUM("4.1%")' });
801
- model.dispatch("SET_VALUE", { xc: "C8", text: '=SUM(" 4.2% ")' });
802
- model.dispatch("SET_VALUE", { xc: "C9", text: '=SUM(".1%")' });
803
- model.dispatch("SET_VALUE", { xc: "C10", text: '=SUM(" .2% ")' });
804
- model.dispatch("SET_VALUE", { xc: "C11", text: '=SUM("3.%")' });
805
- model.dispatch("SET_VALUE", { xc: "C12", text: '=SUM(" 4.% ")' });
806
-
807
- model.dispatch("SET_VALUE", { xc: "D1", text: '=COUNT("%")' });
808
- model.dispatch("SET_VALUE", { xc: "D2", text: '=COUNT(" %")' });
809
- model.dispatch("SET_VALUE", { xc: "D3", text: '=COUNT("40%")' });
810
- model.dispatch("SET_VALUE", { xc: "D4", text: '=COUNT(" 41% ")' });
811
- model.dispatch("SET_VALUE", { xc: "D5", text: '=COUNT("42 %")' });
812
- model.dispatch("SET_VALUE", { xc: "D6", text: '=COUNT(" 43 % ")' });
813
- model.dispatch("SET_VALUE", { xc: "D7", text: '=COUNT("4.1%")' });
814
- model.dispatch("SET_VALUE", { xc: "D8", text: '=COUNT(" 4.2% ")' });
815
- model.dispatch("SET_VALUE", { xc: "D9", text: '=COUNT(".1%")' });
816
- model.dispatch("SET_VALUE", { xc: "D10", text: '=COUNT(" .2% ")' });
817
- model.dispatch("SET_VALUE", { xc: "D11", text: '=COUNT("3.%")' });
818
- model.dispatch("SET_VALUE", { xc: "D12", text: '=COUNT(" 4.% ")' });
819
-
820
- expect(getCell(model, "A1")!.value).toBe('"%"');
821
- expect(getCell(model, "A2")!.value).toBe('" %"');
822
- expect(getCell(model, "A3")!.value).toBe('"40%"');
823
- expect(getCell(model, "A4")!.value).toBe('" 41% "');
824
- expect(getCell(model, "A5")!.value).toBe('"42 %"');
825
- expect(getCell(model, "A6")!.value).toBe('" 43 % "');
826
- expect(getCell(model, "A7")!.value).toBe('"4.1%"');
827
- expect(getCell(model, "A8")!.value).toBe('" 4.2% "');
828
- expect(getCell(model, "A9")!.value).toBe('".1%"');
829
- expect(getCell(model, "A10")!.value).toBe('" .2% "');
830
- expect(getCell(model, "A11")!.value).toBe('"3.%"');
831
- expect(getCell(model, "A12")!.value).toBe('" 4.% "');
832
-
833
- expect(getCell(model, "B1")!.value).toBe("%");
834
- expect(getCell(model, "B2")!.value).toBe(" %");
835
- expect(getCell(model, "B3")!.value).toBe("40%");
836
- expect(getCell(model, "B4")!.value).toBe(" 41% ");
837
- expect(getCell(model, "B5")!.value).toBe("42 %");
838
- expect(getCell(model, "B6")!.value).toBe(" 43 % ");
839
- expect(getCell(model, "B7")!.value).toBe("4.1%");
840
- expect(getCell(model, "B8")!.value).toBe(" 4.2% ");
841
- expect(getCell(model, "B9")!.value).toBe(".1%");
842
- expect(getCell(model, "B10")!.value).toBe(" .2% ");
843
- expect(getCell(model, "B11")!.value).toBe("3.%");
844
- expect(getCell(model, "B12")!.value).toBe(" 4.% ");
845
-
846
- expect(getCell(model, "C1")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
847
- expect(getCell(model, "C2")!.value).toBe("#ERROR"); // @compatibility: on google sheet, return #VALUE!
848
- expect(getCell(model, "C3")!.value).toBe(0.4);
849
- expect(getCell(model, "C4")!.value).toBe(0.41);
850
- expect(getCell(model, "C5")!.value).toBe(0.42); // @compatibility: on google sheet, return #VALUE!
851
- expect(getCell(model, "C6")!.value).toBe(0.43); // @compatibility: on google sheet, return #VALUE!
852
- expect(getCell(model, "C7")!.value).toBeCloseTo(0.041, 3);
853
- expect(getCell(model, "C8")!.value).toBe(0.042); // @compatibility: on google sheet, return #VALUE!
854
- expect(getCell(model, "C9")!.value).toBe(0.001);
855
- expect(getCell(model, "C10")!.value).toBe(0.002);
856
- expect(getCell(model, "C11")!.value).toBe(0.03);
857
- expect(getCell(model, "C12")!.value).toBe(0.04);
858
-
859
- expect(getCell(model, "D1")!.value).toBe(0);
860
-
861
- expect(getCell(model, "D2")!.value).toBe(0);
862
- expect(getCell(model, "D3")!.value).toBe(1);
863
- expect(getCell(model, "D4")!.value).toBe(1);
864
- expect(getCell(model, "D5")!.value).toBe(1); // @compatibility: google sheet returns 0 and excel 1... Excel is right
865
- expect(getCell(model, "D6")!.value).toBe(1); // @compatibility: google sheet returns 0 and excel 1... Excel is right
866
- expect(getCell(model, "D7")!.value).toBe(1);
867
- expect(getCell(model, "D8")!.value).toBe(1);
868
- expect(getCell(model, "D9")!.value).toBe(1);
869
- expect(getCell(model, "D10")!.value).toBe(1);
870
- expect(getCell(model, "D11")!.value).toBe(1);
871
- expect(getCell(model, "D12")!.value).toBe(1);
872
- });
873
-
874
- test("cells in error are correctly reset", async () => {
875
- const model = new Model();
876
- let value: string | number = "LOADING...";
877
- functionRegistry.add("GETVALUE", {
878
- description: "Get value",
879
- compute: async () => value,
880
- async: true,
881
- args: args(``),
882
- returns: ["ANY"],
883
- });
884
- model.dispatch("SET_VALUE", { xc: "A1", text: "=SUM(A2)" });
885
- model.dispatch("SET_VALUE", { xc: "A2", text: "=SUM(A3)" });
886
- model.dispatch("SET_VALUE", { xc: "A3", text: "=-GETVALUE()" });
887
- await waitForRecompute();
888
- expect(getCell(model, "A1")!.error).toBeDefined();
889
- expect(getCell(model, "A2")!.error).toBeDefined();
890
- expect(getCell(model, "A3")!.error).toBeDefined();
891
- value = 2;
892
- model.dispatch("EVALUATE_CELLS", {});
893
- await waitForRecompute();
894
- expect(getCell(model, "A1")!.value).toBe(-2);
895
- expect(getCell(model, "A2")!.value).toBe(-2);
896
- expect(getCell(model, "A3")!.value).toBe(-2);
897
- });
898
-
899
- // TO DO: add tests for exp format (ex: 4E10)
900
- // RO DO: add tests for DATE string format (ex match: "28 02 2020")
901
- });