@vatvaghool/create-ipl-dashboard 0.1.20 → 0.1.24

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.
@@ -1,290 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { afterEach, describe, it, mock } from "node:test";
3
-
4
- import type { DashboardData, RawApiUser } from "../app/types.ts";
5
- import {
6
- addLeaderboardMetrics,
7
- buildManualDashboard,
8
- normalizePayload,
9
- normalizeRawApiUsers,
10
- syncRawUsersWithSnapshot,
11
- } from "../app/api/ipl/transform.ts";
12
- import { createDashboardPoller } from "../app/hooks/dashboardPolling.ts";
13
-
14
- const flushPromises = () => new Promise<void>((resolve) => queueMicrotask(resolve));
15
-
16
- describe("coverage gap guards", () => {
17
- afterEach(() => {
18
- mock.timers.reset();
19
- });
20
-
21
- it("normalizes date instances and filters malformed squad/player records", () => {
22
- const updatedAt = new Date("2026-04-28T09:15:00.000Z");
23
- const payload = normalizePayload({
24
- updatedAt,
25
- leaders: [
26
- {
27
- rank: 1,
28
- name: "Alpha",
29
- points: 110,
30
- captain: { playerName: "Captain A", id: 7, playerPoints: 44 },
31
- viceCaptain: { fullName: "Vice A", playerId: "11", pts: 22 },
32
- players: [
33
- { name: "Valid Player", number: "08", points: 20 },
34
- { playerName: "Bench Player", id: 19, playerPoints: 5 },
35
- { number: "99", points: 3 },
36
- "",
37
- null,
38
- ],
39
- },
40
- ],
41
- });
42
-
43
- assert.ok(payload);
44
- assert.equal(payload.updatedAt, updatedAt.toISOString());
45
- assert.equal(payload.leaders[0].captain?.name, "Captain A");
46
- assert.equal(payload.leaders[0].captain?.number, "7");
47
- assert.equal(payload.leaders[0].captain?.points, 44);
48
- assert.equal(payload.leaders[0].viceCaptain?.name, "Vice A");
49
- assert.equal(payload.leaders[0].viceCaptain?.number, "11");
50
- assert.deepEqual(payload.leaders[0].players, [
51
- { name: "Valid Player", number: "08", points: 20 },
52
- { name: "Bench Player", number: "19", points: 5 },
53
- ]);
54
- });
55
-
56
- it("keeps completed match count undefined when a valid payload reports zero", () => {
57
- const payload = normalizePayload({
58
- completedMatches: 0,
59
- Meta: {
60
- Timestamp: {
61
- ISTTime: "2026-04-28T09:15:00.000Z",
62
- },
63
- },
64
- leaders: [{ rank: 1, name: "Alpha", points: 110 }],
65
- });
66
-
67
- assert.ok(payload);
68
- assert.equal(payload.completedMatches, undefined);
69
- assert.equal(payload.updatedAt, "2026-04-28T09:15:00.000Z");
70
- });
71
-
72
- it("parses completed matches from feed text and handles single-row leaderboard metrics", () => {
73
- const payload = normalizePayload({
74
- Data: {
75
- Value: [{ rank: 1, usrname: "Solo", points: 77 }],
76
- FeedTime: {
77
- UTCTime: "Match 12",
78
- },
79
- },
80
- });
81
-
82
- assert.ok(payload);
83
- assert.equal(payload.completedMatches, 12);
84
-
85
- const rows = addLeaderboardMetrics([
86
- { rank: 1, name: "Solo", points: 77, transfersLeft: 210 },
87
- ]);
88
-
89
- assert.deepEqual(rows, [
90
- {
91
- name: "Solo",
92
- points: 77,
93
- rank: 1,
94
- previousRank: 1,
95
- previousPoints: 77,
96
- lastMatchPoints: undefined,
97
- gapToNext: 0,
98
- gapPercent: 0,
99
- movement: "same",
100
- transfersLeft: 210,
101
- transfersUsed: undefined,
102
- totalTransfers: undefined,
103
- boostersUsed: undefined,
104
- efficiency: undefined,
105
- isLastMatchLeader: false,
106
- captain: undefined,
107
- viceCaptain: undefined,
108
- players: undefined,
109
- },
110
- ]);
111
- });
112
-
113
- it("rejects invalid raw user payload shapes and invalid match rows", () => {
114
- assert.equal(normalizeRawApiUsers({ nope: true }), null);
115
-
116
- const normalized = normalizeRawApiUsers([
117
- null,
118
- {
119
- rno: 1,
120
- temname: "Alpha",
121
- matches: [
122
- null,
123
- { matchId: "bad", points: 10 },
124
- { matchId: 1, points: "bad" },
125
- { matchId: 2, points: 25 },
126
- ],
127
- },
128
- {
129
- rno: 2,
130
- temname: "No Matches Array",
131
- },
132
- ]);
133
-
134
- assert.deepEqual(normalized, [
135
- {
136
- rno: 1,
137
- temname: "Alpha",
138
- points: 25,
139
- matches: [{ matchId: 2, points: 25 }],
140
- },
141
- ]);
142
- });
143
-
144
- it("builds an empty manual dashboard and appends future matches without live points", () => {
145
- assert.deepEqual(buildManualDashboard([]), {
146
- overall: [],
147
- daily: [],
148
- completedMatches: undefined,
149
- source: "database",
150
- });
151
-
152
- const users: RawApiUser[] = [
153
- {
154
- rno: 1,
155
- temname: "Alpha",
156
- points: 30,
157
- matches: [{ matchId: 1, points: 30 }],
158
- },
159
- ];
160
-
161
- const result = syncRawUsersWithSnapshot(users, {
162
- updatedAt: "2026-04-28T09:15:00.000Z",
163
- completedMatches: 3,
164
- leaders: [{ rank: 1, name: "Alpha", points: 45 }],
165
- });
166
-
167
- assert.equal(result.status, "updated");
168
- assert.equal(result.mode, "append");
169
- assert.deepEqual(result.users[0].matches, [
170
- { matchId: 1, points: 30 },
171
- { matchId: 2, points: 15 },
172
- ]);
173
- });
174
-
175
- it("returns skipped when snapshot leaders do not match raw users", () => {
176
- const users: RawApiUser[] = [
177
- {
178
- rno: 1,
179
- temname: "Alpha",
180
- points: 100,
181
- matches: [{ matchId: 1, points: 100 }],
182
- },
183
- ];
184
-
185
- const result = syncRawUsersWithSnapshot(users, {
186
- updatedAt: "2026-04-28T09:15:00.000Z",
187
- completedMatches: 2,
188
- leaders: [{ rank: 1, name: "Ghost Team", points: 150 }],
189
- });
190
-
191
- assert.deepEqual(result, {
192
- status: "skipped",
193
- users,
194
- unmatchedNames: ["Ghost Team"],
195
- });
196
- });
197
-
198
- it("creates a latest match row when forcing update-latest without an existing match entry", () => {
199
- const users: RawApiUser[] = [
200
- {
201
- rno: 1,
202
- temname: "Alpha",
203
- points: 10,
204
- matches: [{ matchId: 1, points: 10 }],
205
- },
206
- {
207
- rno: 2,
208
- temname: "Beta",
209
- points: 15,
210
- matches: [{ matchId: 1, points: 15 }],
211
- },
212
- ];
213
-
214
- const result = syncRawUsersWithSnapshot(users, {
215
- updatedAt: "2026-04-28T09:15:00.000Z",
216
- completedMatches: 2,
217
- leaders: [
218
- { rank: 1, name: "Beta", points: 15, lastMatchPoints: 0 },
219
- { rank: 2, name: "Alpha", points: 18, lastMatchPoints: 8 },
220
- ],
221
- });
222
-
223
- assert.equal(result.status, "updated");
224
- assert.equal(result.mode, "append");
225
- assert.equal(result.matchId, 2);
226
- assert.deepEqual(result.users[0].matches, [
227
- { matchId: 1, points: 10 },
228
- { matchId: 2, points: 8 },
229
- ]);
230
- });
231
-
232
- it("reports polling fetch failures and does not emit stale data after stop", async () => {
233
- mock.timers.enable({ apis: ["Date", "setInterval"], now: 0 });
234
-
235
- const errors: unknown[] = [];
236
- const received: DashboardData[] = [];
237
- let resolveFetch: ((value: Response) => void) | undefined;
238
-
239
- const fetcher = (async (url: string) => {
240
- if (url.includes("first")) {
241
- return {
242
- ok: false,
243
- status: 503,
244
- json: async () => ({}),
245
- } as Response;
246
- }
247
-
248
- return await new Promise<Response>((resolve) => {
249
- resolveFetch = resolve;
250
- });
251
- }) as typeof fetch;
252
-
253
- let firstCall = true;
254
- const wrappedFetcher = (async (url: string, options?: RequestInit) => {
255
- const actualUrl = firstCall ? "/api/ipl?first=true" : url;
256
- firstCall = false;
257
- return fetcher(actualUrl, options);
258
- }) as typeof fetch;
259
-
260
- const stop = createDashboardPoller({
261
- fetcher: wrappedFetcher,
262
- onData: (data) => received.push(data),
263
- onError: (error) => errors.push(error),
264
- intervalMs: 50,
265
- });
266
-
267
- await flushPromises();
268
- await flushPromises();
269
- assert.equal(errors.length, 1);
270
- assert.match(String(errors[0]), /503/);
271
-
272
- mock.timers.tick(50);
273
- stop();
274
-
275
- resolveFetch?.({
276
- ok: true,
277
- status: 200,
278
- json: async () =>
279
- ({
280
- source: "database",
281
- updatedAt: "2026-04-28T09:20:00.000Z",
282
- overall: [{ rank: 1, name: "Alpha", points: 120 }],
283
- daily: [{ day: "Match 1", Alpha: 120 }],
284
- }) as DashboardData,
285
- } as Response);
286
-
287
- await flushPromises();
288
- assert.equal(received.length, 0);
289
- });
290
- });
@@ -1,96 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { afterEach, describe, it, mock } from "node:test";
3
- import type { DashboardData } from "../app/types.ts";
4
- import {
5
- createDashboardPoller,
6
- DASHBOARD_POLL_INTERVAL_MS,
7
- } from "../app/hooks/dashboardPolling.ts";
8
-
9
- const flushPromises = () => new Promise<void>((resolve) => queueMicrotask(resolve));
10
-
11
- const createResponse = (data: DashboardData) =>
12
- ({
13
- ok: true,
14
- status: 200,
15
- json: async () => data,
16
- }) as Response;
17
-
18
- describe("dashboard polling", () => {
19
- afterEach(() => {
20
- mock.timers.reset();
21
- });
22
-
23
- it("fetches fresh dashboard data again after every polling interval", async () => {
24
- mock.timers.enable({ apis: ["Date", "setInterval"], now: 0 });
25
-
26
- const first: DashboardData = {
27
- source: "database",
28
- updatedAt: "2026-04-26T10:00:00.000Z",
29
- overall: [{ rank: 1, name: "Alpha", points: 100 }],
30
- daily: [{ day: "Match 1", Alpha: 100 }],
31
- };
32
- const second: DashboardData = {
33
- source: "database",
34
- updatedAt: "2026-04-26T10:02:00.000Z",
35
- overall: [{ rank: 1, name: "Alpha", points: 125 }],
36
- daily: [{ day: "Match 1", Alpha: 125 }],
37
- };
38
- const responses = [first, second];
39
- const received: DashboardData[] = [];
40
- const fetchCalls: Array<{ url: string; options?: RequestInit }> = [];
41
- const fetcher = (async (url: string, options?: RequestInit) => {
42
- fetchCalls.push({ url, options });
43
- return createResponse(responses.shift() ?? second);
44
- }) as typeof fetch;
45
-
46
- const stop = createDashboardPoller({
47
- fetcher,
48
- onData: (data) => received.push(data),
49
- onError: (error) => assert.fail(String(error)),
50
- });
51
-
52
- await flushPromises();
53
-
54
- assert.equal(fetchCalls.length, 1);
55
- assert.equal(received.length, 1);
56
- assert.equal(received[0].overall[0].points, 100);
57
-
58
- mock.timers.tick(DASHBOARD_POLL_INTERVAL_MS);
59
- await flushPromises();
60
-
61
- assert.equal(fetchCalls.length, 2);
62
- assert.equal(received.length, 2);
63
- assert.equal(received[1].overall[0].points, 125);
64
- assert.equal(fetchCalls[1].url, `/api/ipl?t=${DASHBOARD_POLL_INTERVAL_MS}`);
65
- assert.deepEqual(fetchCalls[1].options, { cache: "no-store" });
66
-
67
- stop();
68
- });
69
-
70
- it("does not emit unchanged data on the next interval", async () => {
71
- mock.timers.enable({ apis: ["Date", "setInterval"], now: 0 });
72
-
73
- const dashboard: DashboardData = {
74
- source: "database",
75
- updatedAt: "2026-04-26T10:00:00.000Z",
76
- overall: [{ rank: 1, name: "Alpha", points: 100 }],
77
- daily: [{ day: "Match 1", Alpha: 100 }],
78
- };
79
- const received: DashboardData[] = [];
80
- const fetcher = (async () => createResponse(dashboard)) as typeof fetch;
81
-
82
- const stop = createDashboardPoller({
83
- fetcher,
84
- onData: (data) => received.push(data),
85
- onError: (error) => assert.fail(String(error)),
86
- });
87
-
88
- await flushPromises();
89
- mock.timers.tick(DASHBOARD_POLL_INTERVAL_MS);
90
- await flushPromises();
91
-
92
- assert.equal(received.length, 1);
93
-
94
- stop();
95
- });
96
- });
@@ -1,267 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { afterEach, describe, it, mock } from "node:test";
3
-
4
- import { readDashboardCache, writeDashboardCache } from "../app/hooks/dashboardCache.ts";
5
- import { readSnapshotCache, writeSnapshotCache } from "../app/hooks/snapshotCache.ts";
6
- import {
7
- getDisplayLiveMatchId,
8
- getLiveUpdateRow,
9
- getPlayedMatchRows,
10
- hasMeaningfulMatchData,
11
- parseMatchId,
12
- } from "../app/lib/dashboardData.ts";
13
- import { getMatchViewState } from "../app/lib/dashboardView.ts";
14
- import { getLatestMatchRow, hasLiveMatchRow } from "../app/lib/dashboardView.ts";
15
- import { matches } from "../app/lib/matches.ts";
16
- import { getDiff } from "../app/lib/utils/diff.ts";
17
- import { getStdDeviation } from "../app/lib/utils/getStdDeviation.ts";
18
- import { formatMatchTime, getMatchStatus, getTimeLeft } from "../app/lib/utils/time.ts";
19
- import { splitTeamName, trimTeamName } from "../app/lib/utils.ts";
20
-
21
- const createStorage = () => {
22
- const store = new Map<string, string>();
23
-
24
- return {
25
- getItem: (key: string) => store.get(key) ?? null,
26
- setItem: (key: string, value: string) => {
27
- store.set(key, value);
28
- },
29
- removeItem: (key: string) => {
30
- store.delete(key);
31
- },
32
- clear: () => {
33
- store.clear();
34
- },
35
- };
36
- };
37
-
38
- describe("utility and cache coverage", () => {
39
- afterEach(() => {
40
- delete (globalThis as { window?: unknown }).window;
41
- mock.timers.reset();
42
- });
43
-
44
- it("trims and splits team names across all branches", () => {
45
- assert.equal(trimTeamName("Short"), "Short");
46
- assert.equal(trimTeamName("VeryLongTeamName", 8), "VeryLong...");
47
- assert.deepEqual(splitTeamName("Alpha"), ["Alpha", ""]);
48
- assert.deepEqual(splitTeamName("Alpha Beta", 7), ["Alpha", "Beta"]);
49
- assert.deepEqual(splitTeamName("NoSpacesHere", 4), ["NoSp", "acesHere"]);
50
- assert.deepEqual(
51
- splitTeamName("A very very long team name", 8),
52
- ["A very", "very lon..."],
53
- );
54
- });
55
-
56
- it("computes diffs and standard deviation", () => {
57
- assert.deepEqual(
58
- getDiff(
59
- { a: 1, nested: { left: 2, same: 1 } },
60
- { a: 2, nested: { left: 3, same: 1 }, added: true },
61
- ),
62
- {
63
- a: 2,
64
- "nested.left": 3,
65
- added: true,
66
- },
67
- );
68
- assert.equal(getStdDeviation([2, 4, 4, 4, 5, 5, 7, 9]), 2);
69
- });
70
-
71
- it("formats match times and covers all time status helpers", () => {
72
- mock.timers.enable({ apis: ["Date"], now: new Date("2026-04-28T10:00:00.000Z") });
73
-
74
- assert.match(
75
- formatMatchTime("2026-04-28T14:00:00.000Z", "UTC"),
76
- /28 Apr.*02:00 pm/i,
77
- );
78
- assert.equal(getMatchStatus("2026-04-28T05:30:00.000Z"), "ENDED");
79
- assert.equal(getMatchStatus("2026-04-28T09:30:00.000Z"), "LIVE");
80
- assert.equal(getMatchStatus("2026-04-28T10:20:00.000Z"), "STARTING SOON");
81
- assert.equal(getMatchStatus("2026-04-28T12:00:00.000Z"), "UPCOMING");
82
- assert.equal(getTimeLeft("2026-04-28T09:59:00.000Z"), "Started");
83
- assert.equal(getTimeLeft("2026-04-28T10:45:00.000Z"), "45m");
84
- assert.equal(getTimeLeft("2026-04-28T12:15:00.000Z"), "2h 15m");
85
- });
86
-
87
- it("normalizes dashboard daily rows for played matches and live match labels", () => {
88
- const daily = [
89
- { day: "Match 1", Alpha: 120, Beta: 90 },
90
- { day: "Match 2", Alpha: 0, Beta: 0 },
91
- { day: "Match 3", Alpha: 65, Beta: 55 },
92
- { day: "Live Update", Alpha: 20, Beta: 18 },
93
- ];
94
-
95
- assert.equal(parseMatchId("Match 12"), 12);
96
- assert.equal(parseMatchId("Live Update"), undefined);
97
- assert.equal(hasMeaningfulMatchData(daily[0]), true);
98
- assert.equal(hasMeaningfulMatchData(daily[1]), false);
99
- assert.deepEqual(
100
- getPlayedMatchRows(daily).map((row) => row.day),
101
- ["Match 1", "Match 3"],
102
- );
103
- assert.equal(getLiveUpdateRow(daily)?.day, "Live Update");
104
- assert.equal(getDisplayLiveMatchId(daily), 4);
105
- });
106
-
107
- it("falls back to the latest played row when no live match row exists", () => {
108
- const daily = [
109
- { day: "Match 1", Alpha: 10, Beta: 20 },
110
- { day: "Match 2", Alpha: 15, Beta: 12 },
111
- ];
112
-
113
- assert.equal(hasLiveMatchRow(daily), false);
114
- assert.equal(getLatestMatchRow(daily)?.day, "Match 2");
115
- assert.equal(getMatchViewState(daily).isLive, false);
116
- assert.equal(getMatchViewState(daily).latestRow?.day, "Match 2");
117
- assert.equal(getMatchViewState(daily).hasMatches, true);
118
- });
119
-
120
- it("reads and writes dashboard cache with invalid payload safeguards", () => {
121
- assert.equal(readDashboardCache(), null);
122
- assert.doesNotThrow(() =>
123
- writeDashboardCache({
124
- source: "database",
125
- overall: [],
126
- daily: [],
127
- }),
128
- );
129
-
130
- const storage = createStorage();
131
- (globalThis as { window?: unknown }).window = {
132
- localStorage: storage,
133
- };
134
-
135
- assert.equal(readDashboardCache(), null);
136
-
137
- writeDashboardCache({
138
- source: "database",
139
- updatedAt: "2026-04-28T09:20:00.000Z",
140
- snapshot: {
141
- updatedAt: "2026-04-28T09:20:00.000Z",
142
- leaders: [{ rank: 1, name: "Alpha", points: 120 }],
143
- },
144
- overall: [{ rank: 1, name: "Alpha", points: 120 }],
145
- daily: [{ day: "Match 1", Alpha: 120 }],
146
- });
147
- const cached = readDashboardCache();
148
- assert.ok(cached);
149
- assert.equal(cached.data.overall[0].name, "Alpha");
150
- assert.ok(cached.cachedAt);
151
-
152
- storage.setItem(
153
- "ipl:dashboard-cache:v1",
154
- JSON.stringify({
155
- data: { source: "database", overall: [], daily: [] },
156
- }),
157
- );
158
- const fallbackCached = readDashboardCache();
159
- assert.ok(fallbackCached);
160
- assert.equal(typeof fallbackCached.cachedAt, "string");
161
-
162
- storage.setItem(
163
- "ipl:dashboard-cache:v1",
164
- JSON.stringify({
165
- cachedAt: "2026-04-28T09:20:00.000Z",
166
- data: {
167
- source: "database",
168
- updatedAt: "2026-04-28T09:20:00.000Z",
169
- overall: [],
170
- daily: [],
171
- },
172
- }),
173
- );
174
- assert.equal(readDashboardCache(), null);
175
-
176
- storage.setItem("ipl:dashboard-cache:v1", "{\"cachedAt\":1}");
177
- assert.equal(readDashboardCache(), null);
178
-
179
- storage.setItem("ipl:dashboard-cache:v1", "null");
180
- assert.equal(readDashboardCache(), null);
181
-
182
- storage.setItem("ipl:dashboard-cache:v1", "1");
183
- assert.equal(readDashboardCache(), null);
184
-
185
- storage.setItem("ipl:dashboard-cache:v1", JSON.stringify({ data: 1 }));
186
- assert.equal(readDashboardCache(), null);
187
-
188
- storage.setItem("ipl:dashboard-cache:v1", "not-json");
189
- assert.equal(readDashboardCache(), null);
190
- });
191
-
192
- it("reads and writes snapshot cache with fallback timestamps", () => {
193
- assert.equal(readSnapshotCache(), null);
194
- assert.doesNotThrow(() =>
195
- writeSnapshotCache({
196
- leaders: [],
197
- }),
198
- );
199
-
200
- const storage = createStorage();
201
- (globalThis as { window?: unknown }).window = {
202
- localStorage: storage,
203
- };
204
-
205
- assert.equal(readSnapshotCache(), null);
206
-
207
- writeSnapshotCache({
208
- updatedAt: "2026-04-28T09:15:00.000Z",
209
- completedMatches: 41,
210
- leaders: [{ rank: 1, name: "Alpha", points: 110 }],
211
- });
212
- const cached = readSnapshotCache();
213
- assert.ok(cached);
214
- assert.equal(cached.snapshot.leaders[0].name, "Alpha");
215
- assert.ok(cached.cachedAt);
216
-
217
- storage.setItem(
218
- "ipl:snapshot-cache:v1",
219
- JSON.stringify({
220
- snapshot: { updatedAt: "2026-04-28T09:15:00.000Z", leaders: [] },
221
- }),
222
- );
223
- const fallbackCached = readSnapshotCache();
224
- assert.ok(fallbackCached);
225
- assert.equal(typeof fallbackCached.cachedAt, "string");
226
-
227
- storage.setItem("ipl:snapshot-cache:v1", "{\"cachedAt\":1}");
228
- assert.equal(readSnapshotCache(), null);
229
-
230
- storage.setItem("ipl:snapshot-cache:v1", "1");
231
- assert.equal(readSnapshotCache(), null);
232
-
233
- storage.setItem("ipl:snapshot-cache:v1", JSON.stringify({ snapshot: 1 }));
234
- assert.equal(readSnapshotCache(), null);
235
-
236
- storage.setItem("ipl:snapshot-cache:v1", "not-json");
237
- assert.equal(readSnapshotCache(), null);
238
- });
239
-
240
- it("gracefully ignores cache write failures and exposes upcoming match data", () => {
241
- (globalThis as { window?: unknown }).window = {
242
- localStorage: {
243
- getItem: () => null,
244
- setItem: () => {
245
- throw new Error("quota");
246
- },
247
- },
248
- };
249
-
250
- assert.doesNotThrow(() =>
251
- writeDashboardCache({
252
- source: "database",
253
- overall: [],
254
- daily: [],
255
- }),
256
- );
257
- assert.doesNotThrow(() =>
258
- writeSnapshotCache({
259
- leaders: [],
260
- }),
261
- );
262
-
263
- assert.equal(matches[0].id, 51);
264
- assert.equal(matches.at(-1)?.id, 70);
265
- assert.equal(matches.every((match) => match.team1 && match.team2 && match.date), true);
266
- });
267
- });