@antelopejs/dms 0.7.6 → 0.7.8
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.
- package/CHANGELOG.md +35 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js +15 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/page-live.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/page-live.test.js +66 -0
- package/dist/test/unit/interfaces/dms-base/page-live.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js +16 -0
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js.map +1 -1
- package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +23 -3
- package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +2 -1
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +2 -1
- package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +134 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/rowSidePanel.ts +129 -0
- package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +6 -0
- package/frontend-vue/layers/dms-layout/app/types/page.ts +3 -0
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +5 -1
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +5 -1
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +30 -15
- package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +44 -8
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +35 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +17 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +107 -12
- package/frontend-vue/layers/dms-ui/app/build/composables/blocks/useRefreshTriggers.ts +26 -11
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +24 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +58 -16
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +30 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +107 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/formatElapsed.ts +25 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/pageLiveController.ts +229 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +8 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/useLiveToggleShortcut.ts +25 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +46 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/periodQuery.ts +330 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodLocation.ts +189 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableListData.ts +15 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +77 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +53 -18
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +1 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +61 -2
- package/frontend-vue/layers/dms-ui/app/build/utils/rowClickTrigger.ts +73 -0
- package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +92 -0
- package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +10 -4
- package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +19 -0
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +90 -12
- package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +1 -1
- package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +52 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/shortcuts/index.ts +8 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/shortcuts/tableViewRowPanel.ts +30 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +15 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
- package/frontend-vue/layers/dms-ui/app/config/shortcuts-registry.ts +5 -0
- package/frontend-vue/layers/dms-ui/app/types/live.ts +8 -0
- package/frontend-vue/layers/dms-ui/app/types/row-action.ts +5 -2
- package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +44 -6
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +28 -0
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +28 -0
- package/frontend-vue/tests/chart-live-pause.test.ts +74 -0
- package/frontend-vue/tests/field-row.test.ts +14 -0
- package/frontend-vue/tests/form-section-nav-groups.test.ts +75 -14
- package/frontend-vue/tests/live-hold-banner.test.ts +37 -0
- package/frontend-vue/tests/live-toggle.test.ts +162 -0
- package/frontend-vue/tests/page-live-gate.test.ts +241 -0
- package/frontend-vue/tests/period-live-pause.test.ts +120 -0
- package/frontend-vue/tests/period-selector-url.test.ts +268 -0
- package/frontend-vue/tests/period-url-query.test.ts +351 -0
- package/frontend-vue/tests/row-side-panel.test.ts +653 -0
- package/frontend-vue/tests/table-cell-tones.test.ts +176 -0
- package/frontend-vue/tests/table-live-hold.test.ts +204 -0
- package/frontend-vue/tests/table-source-period-scope.test.ts +144 -0
- package/frontend-vue/tests/table-view-refresh.test.ts +2 -2
- package/frontend-vue/tests/table-view-sources.test.ts +40 -0
- package/frontend-vue/tests/vue-inventory.test.ts +1 -1
- package/package.json +2 -2
- package/skills/dms/SKILL.md +11 -3
- package/skills/dms-pages/REFERENCE.md +5 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A PeriodSelector keeps its period in the page URL under keys prefixed with
|
|
3
|
+
* its id. These cover what the URL holds: how a selection is written and read
|
|
4
|
+
* back, which source wins (the URL, then the user's last choice, then the
|
|
5
|
+
* default), that two selectors never read each other's keys, and that a value
|
|
6
|
+
* the selector cannot honour falls back silently.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import {
|
|
10
|
+
formatPeriodDate,
|
|
11
|
+
isPeriodQueryCurrent,
|
|
12
|
+
mergePeriodSearch,
|
|
13
|
+
parsePeriodDate,
|
|
14
|
+
periodQueryKeys,
|
|
15
|
+
type PeriodChoices,
|
|
16
|
+
type PeriodSelection,
|
|
17
|
+
readComparisonChoice,
|
|
18
|
+
readRangeChoice,
|
|
19
|
+
rememberPeriod,
|
|
20
|
+
resolvePeriodSelection,
|
|
21
|
+
writePeriodQuery,
|
|
22
|
+
} from "../layers/dms-ui/app/build/composables/period/periodQuery";
|
|
23
|
+
|
|
24
|
+
const CHOICES: PeriodChoices = {
|
|
25
|
+
presets: ["last-7-days", "last-30-days", "this-month", "custom"],
|
|
26
|
+
comparisons: ["none", "previous-period", "previous-year", "custom"],
|
|
27
|
+
};
|
|
28
|
+
const DEFAULT: PeriodSelection = {
|
|
29
|
+
preset: "this-month",
|
|
30
|
+
comparison: "none",
|
|
31
|
+
customRange: null,
|
|
32
|
+
customCompareRange: null,
|
|
33
|
+
};
|
|
34
|
+
const PAGE = periodQueryKeys("page");
|
|
35
|
+
const STORED = periodQueryKeys();
|
|
36
|
+
|
|
37
|
+
const day = (year: number, month: number, date: number) =>
|
|
38
|
+
new Date(year, month - 1, date);
|
|
39
|
+
const endOfDay = (year: number, month: number, date: number) =>
|
|
40
|
+
new Date(year, month - 1, date, 23, 59, 59, 999);
|
|
41
|
+
|
|
42
|
+
describe("the keys of a selector", () => {
|
|
43
|
+
it("prefixes every key with the selector id", () => {
|
|
44
|
+
expect(PAGE).toEqual({
|
|
45
|
+
period: "page.period",
|
|
46
|
+
compare: "page.compare",
|
|
47
|
+
from: "page.from",
|
|
48
|
+
to: "page.to",
|
|
49
|
+
compareFrom: "page.compareFrom",
|
|
50
|
+
compareTo: "page.compareTo",
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("keeps the bare keys without an id", () => {
|
|
55
|
+
expect(STORED.period).toBe("period");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("serializing a selection", () => {
|
|
60
|
+
it("writes a preset and its comparison", () => {
|
|
61
|
+
expect(
|
|
62
|
+
writePeriodQuery(
|
|
63
|
+
{ ...DEFAULT, preset: "last-7-days", comparison: "previous-period" },
|
|
64
|
+
PAGE,
|
|
65
|
+
),
|
|
66
|
+
).toEqual({
|
|
67
|
+
"page.period": "last-7-days",
|
|
68
|
+
"page.compare": "previous-period",
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("writes a custom range of whole days as bare dates", () => {
|
|
73
|
+
expect(
|
|
74
|
+
writePeriodQuery(
|
|
75
|
+
{
|
|
76
|
+
...DEFAULT,
|
|
77
|
+
preset: "custom",
|
|
78
|
+
customRange: { from: day(2026, 10, 1), to: endOfDay(2026, 10, 31) },
|
|
79
|
+
},
|
|
80
|
+
PAGE,
|
|
81
|
+
),
|
|
82
|
+
).toEqual({
|
|
83
|
+
"page.from": "2026-10-01",
|
|
84
|
+
"page.to": "2026-10-31",
|
|
85
|
+
"page.compare": "none",
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("writes an instant that is not a day boundary as an ISO date-time", () => {
|
|
90
|
+
const from = new Date(2026, 9, 1, 10, 30);
|
|
91
|
+
expect(formatPeriodDate(from, "start")).toBe(from.toISOString());
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("writes a custom comparison with its own range", () => {
|
|
95
|
+
expect(
|
|
96
|
+
writePeriodQuery(
|
|
97
|
+
{
|
|
98
|
+
...DEFAULT,
|
|
99
|
+
comparison: "custom",
|
|
100
|
+
customCompareRange: {
|
|
101
|
+
from: day(2025, 10, 1),
|
|
102
|
+
to: endOfDay(2025, 10, 31),
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
PAGE,
|
|
106
|
+
),
|
|
107
|
+
).toEqual({
|
|
108
|
+
"page.period": "this-month",
|
|
109
|
+
"page.compare": "custom",
|
|
110
|
+
"page.compareFrom": "2025-10-01",
|
|
111
|
+
"page.compareTo": "2025-10-31",
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("reads back what it wrote", () => {
|
|
116
|
+
const selection: PeriodSelection = {
|
|
117
|
+
preset: "custom",
|
|
118
|
+
comparison: "custom",
|
|
119
|
+
customRange: {
|
|
120
|
+
from: new Date(2026, 9, 1, 8),
|
|
121
|
+
to: new Date(2026, 9, 2, 18),
|
|
122
|
+
},
|
|
123
|
+
customCompareRange: { from: day(2026, 9, 1), to: endOfDay(2026, 9, 2) },
|
|
124
|
+
};
|
|
125
|
+
const query = writePeriodQuery(selection, PAGE);
|
|
126
|
+
expect(
|
|
127
|
+
resolvePeriodSelection([{ query, keys: PAGE }], CHOICES, DEFAULT),
|
|
128
|
+
).toEqual(selection);
|
|
129
|
+
expect(isPeriodQueryCurrent(query, PAGE, selection)).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("parsing the URL", () => {
|
|
134
|
+
it("reads an ISO date as the start or the end of that local day", () => {
|
|
135
|
+
expect(parsePeriodDate("2026-10-01", "start")).toEqual(day(2026, 10, 1));
|
|
136
|
+
expect(parsePeriodDate("2026-10-01", "end")).toEqual(endOfDay(2026, 10, 1));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("reads an ISO date-time as that instant", () => {
|
|
140
|
+
expect(parsePeriodDate("2026-10-01T08:00:00.000Z", "start")).toEqual(
|
|
141
|
+
new Date("2026-10-01T08:00:00.000Z"),
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it.each(["2026-02-30", "yesterday", "1700000000", "2026-13-01", ""])(
|
|
146
|
+
"refuses %j",
|
|
147
|
+
(text) => {
|
|
148
|
+
expect(parsePeriodDate(text, "start")).toBeNull();
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
it("reads a preset the selector offers", () => {
|
|
153
|
+
const query = { "page.period": "last-30-days" };
|
|
154
|
+
expect(readRangeChoice({ query, keys: PAGE }, CHOICES)).toEqual({
|
|
155
|
+
preset: "last-30-days",
|
|
156
|
+
customRange: null,
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("prefers a custom range to a preset", () => {
|
|
161
|
+
const query = {
|
|
162
|
+
"page.period": "last-30-days",
|
|
163
|
+
"page.from": "2026-10-01",
|
|
164
|
+
"page.to": "2026-10-15",
|
|
165
|
+
};
|
|
166
|
+
expect(readRangeChoice({ query, keys: PAGE }, CHOICES)).toEqual({
|
|
167
|
+
preset: "custom",
|
|
168
|
+
customRange: { from: day(2026, 10, 1), to: endOfDay(2026, 10, 15) },
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("takes the first value of a repeated key", () => {
|
|
173
|
+
const query = { "page.period": ["last-7-days", "last-30-days"] };
|
|
174
|
+
expect(readRangeChoice({ query, keys: PAGE }, CHOICES)?.preset).toBe(
|
|
175
|
+
"last-7-days",
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it.each([
|
|
180
|
+
["an unknown preset", { "page.period": "last-decade" }],
|
|
181
|
+
["a preset the selector does not offer", { "page.period": "ytd" }],
|
|
182
|
+
["custom with no range", { "page.period": "custom" }],
|
|
183
|
+
[
|
|
184
|
+
"a range ending before it starts",
|
|
185
|
+
{ "page.from": "2026-10-15", "page.to": "2026-10-01" },
|
|
186
|
+
],
|
|
187
|
+
["half a range", { "page.from": "2026-10-01" }],
|
|
188
|
+
])("ignores %s", (_, query) => {
|
|
189
|
+
expect(readRangeChoice({ query, keys: PAGE }, CHOICES)).toBeNull();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("ignores a custom range the selector does not offer", () => {
|
|
193
|
+
const query = { "page.from": "2026-10-01", "page.to": "2026-10-15" };
|
|
194
|
+
const presets = CHOICES.presets.filter((preset) => preset !== "custom");
|
|
195
|
+
expect(
|
|
196
|
+
readRangeChoice({ query, keys: PAGE }, { ...CHOICES, presets }),
|
|
197
|
+
).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it.each([
|
|
201
|
+
["an unknown comparison", { "page.compare": "previous-decade" }],
|
|
202
|
+
["a custom comparison with no range", { "page.compare": "custom" }],
|
|
203
|
+
])("ignores %s", (_, query) => {
|
|
204
|
+
expect(readComparisonChoice({ query, keys: PAGE }, CHOICES)).toBeNull();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe("the order of the sources", () => {
|
|
209
|
+
const stored = {
|
|
210
|
+
query: { period: "last-30-days", compare: "previous-year" },
|
|
211
|
+
keys: STORED,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
it("reads the URL first", () => {
|
|
215
|
+
const url = {
|
|
216
|
+
query: { "page.period": "last-7-days", "page.compare": "none" },
|
|
217
|
+
keys: PAGE,
|
|
218
|
+
};
|
|
219
|
+
expect(
|
|
220
|
+
resolvePeriodSelection([url, stored], CHOICES, DEFAULT),
|
|
221
|
+
).toMatchObject({ preset: "last-7-days", comparison: "none" });
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("reads the user's last choice when the URL names nothing", () => {
|
|
225
|
+
expect(
|
|
226
|
+
resolvePeriodSelection(
|
|
227
|
+
[{ query: {}, keys: PAGE }, stored],
|
|
228
|
+
CHOICES,
|
|
229
|
+
DEFAULT,
|
|
230
|
+
),
|
|
231
|
+
).toMatchObject({ preset: "last-30-days", comparison: "previous-year" });
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("falls back to the default when no source names a period", () => {
|
|
235
|
+
expect(
|
|
236
|
+
resolvePeriodSelection(
|
|
237
|
+
[
|
|
238
|
+
{ query: {}, keys: PAGE },
|
|
239
|
+
{ query: {}, keys: STORED },
|
|
240
|
+
],
|
|
241
|
+
CHOICES,
|
|
242
|
+
DEFAULT,
|
|
243
|
+
),
|
|
244
|
+
).toEqual(DEFAULT);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("skips an invalid URL value for the next source, half by half", () => {
|
|
248
|
+
const url = {
|
|
249
|
+
query: {
|
|
250
|
+
"page.period": "last-decade",
|
|
251
|
+
"page.compare": "previous-period",
|
|
252
|
+
},
|
|
253
|
+
keys: PAGE,
|
|
254
|
+
};
|
|
255
|
+
expect(
|
|
256
|
+
resolvePeriodSelection([url, stored], CHOICES, DEFAULT),
|
|
257
|
+
).toMatchObject({
|
|
258
|
+
preset: "last-30-days",
|
|
259
|
+
comparison: "previous-period",
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("skips an invalid stored value for the default", () => {
|
|
264
|
+
const broken = { query: { period: 42, compare: "?" }, keys: STORED };
|
|
265
|
+
expect(
|
|
266
|
+
resolvePeriodSelection(
|
|
267
|
+
[{ query: {}, keys: PAGE }, broken],
|
|
268
|
+
CHOICES,
|
|
269
|
+
DEFAULT,
|
|
270
|
+
),
|
|
271
|
+
).toEqual(DEFAULT);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe("several selectors on one page", () => {
|
|
276
|
+
const query = {
|
|
277
|
+
"sales.period": "last-7-days",
|
|
278
|
+
"sales.compare": "previous-year",
|
|
279
|
+
"traffic.period": "last-30-days",
|
|
280
|
+
"traffic.compare": "none",
|
|
281
|
+
period: "this-month",
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
it("reads each selector's own keys only", () => {
|
|
285
|
+
const read = (id: string) =>
|
|
286
|
+
resolvePeriodSelection(
|
|
287
|
+
[{ query, keys: periodQueryKeys(id) }],
|
|
288
|
+
CHOICES,
|
|
289
|
+
DEFAULT,
|
|
290
|
+
);
|
|
291
|
+
expect(read("sales")).toMatchObject({
|
|
292
|
+
preset: "last-7-days",
|
|
293
|
+
comparison: "previous-year",
|
|
294
|
+
});
|
|
295
|
+
expect(read("traffic")).toMatchObject({
|
|
296
|
+
preset: "last-30-days",
|
|
297
|
+
comparison: "none",
|
|
298
|
+
});
|
|
299
|
+
expect(read("other")).toEqual(DEFAULT);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("rewrites one selector's keys and keeps every other parameter", () => {
|
|
303
|
+
const search =
|
|
304
|
+
"?requests.tab=get&sales.period=last-7-days&sales.compare=none&traffic.period=last-30-days";
|
|
305
|
+
const next = mergePeriodSearch(search, periodQueryKeys("sales"), {
|
|
306
|
+
...DEFAULT,
|
|
307
|
+
preset: "custom",
|
|
308
|
+
customRange: { from: day(2026, 10, 1), to: endOfDay(2026, 10, 2) },
|
|
309
|
+
});
|
|
310
|
+
expect(Object.fromEntries(new URLSearchParams(next))).toEqual({
|
|
311
|
+
"requests.tab": "get",
|
|
312
|
+
"sales.compare": "none",
|
|
313
|
+
"sales.from": "2026-10-01",
|
|
314
|
+
"sales.to": "2026-10-02",
|
|
315
|
+
"traffic.period": "last-30-days",
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe("the last choices kept in the browser", () => {
|
|
321
|
+
it("keeps only the most recent ones", () => {
|
|
322
|
+
let store = {};
|
|
323
|
+
for (let index = 0; index < 25; index++) {
|
|
324
|
+
store = rememberPeriod(store, `page-${index}#page`, { period: "ytd" });
|
|
325
|
+
}
|
|
326
|
+
const keys = Object.keys(store);
|
|
327
|
+
expect(keys).toHaveLength(20);
|
|
328
|
+
expect(keys[0]).toBe("page-5#page");
|
|
329
|
+
expect(keys.at(-1)).toBe("page-24#page");
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it("moves a selector chosen again to the most recent place", () => {
|
|
333
|
+
const store = rememberPeriod(
|
|
334
|
+
{ "a#page": { period: "ytd" }, "b#page": { period: "ytd" } },
|
|
335
|
+
"a#page",
|
|
336
|
+
{ period: "last-7-days" },
|
|
337
|
+
2,
|
|
338
|
+
);
|
|
339
|
+
expect(Object.keys(store)).toEqual(["b#page", "a#page"]);
|
|
340
|
+
expect(store["a#page"]).toEqual({ period: "last-7-days" });
|
|
341
|
+
expect(
|
|
342
|
+
Object.keys(rememberPeriod(store, "c#page", { period: "ytd" }, 2)),
|
|
343
|
+
).toEqual(["a#page", "c#page"]);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it("starts over from a store that is not an object", () => {
|
|
347
|
+
expect(rememberPeriod("broken", "a#page", { period: "ytd" })).toEqual({
|
|
348
|
+
"a#page": { period: "ytd" },
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
});
|