mtrl-addons 0.2.1 → 0.2.3

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 (128) hide show
  1. package/{src/components/index.ts → dist/components/index.d.ts} +0 -2
  2. package/dist/components/vlist/config.d.ts +86 -0
  3. package/{src/components/vlist/constants.ts → dist/components/vlist/constants.d.ts} +10 -11
  4. package/dist/components/vlist/features/api.d.ts +7 -0
  5. package/{src/components/vlist/features/index.ts → dist/components/vlist/features/index.d.ts} +0 -2
  6. package/dist/components/vlist/features/selection.d.ts +6 -0
  7. package/dist/components/vlist/features/viewport.d.ts +9 -0
  8. package/dist/components/vlist/features.d.ts +31 -0
  9. package/{src/components/vlist/index.ts → dist/components/vlist/index.d.ts} +1 -9
  10. package/dist/components/vlist/types.d.ts +596 -0
  11. package/dist/components/vlist/vlist.d.ts +29 -0
  12. package/dist/core/compose/features/gestures/index.d.ts +86 -0
  13. package/dist/core/compose/features/gestures/longpress.d.ts +85 -0
  14. package/dist/core/compose/features/gestures/pan.d.ts +108 -0
  15. package/dist/core/compose/features/gestures/pinch.d.ts +111 -0
  16. package/dist/core/compose/features/gestures/rotate.d.ts +111 -0
  17. package/dist/core/compose/features/gestures/swipe.d.ts +149 -0
  18. package/dist/core/compose/features/gestures/tap.d.ts +79 -0
  19. package/{src/core/compose/features/index.ts → dist/core/compose/features/index.d.ts} +1 -2
  20. package/{src/core/compose/index.ts → dist/core/compose/index.d.ts} +2 -11
  21. package/{src/core/gestures/index.ts → dist/core/gestures/index.d.ts} +1 -20
  22. package/dist/core/gestures/longpress.d.ts +23 -0
  23. package/dist/core/gestures/manager.d.ts +14 -0
  24. package/dist/core/gestures/pan.d.ts +12 -0
  25. package/dist/core/gestures/pinch.d.ts +14 -0
  26. package/dist/core/gestures/rotate.d.ts +14 -0
  27. package/dist/core/gestures/swipe.d.ts +20 -0
  28. package/dist/core/gestures/tap.d.ts +12 -0
  29. package/dist/core/gestures/types.d.ts +320 -0
  30. package/dist/core/gestures/utils.d.ts +57 -0
  31. package/dist/core/index.d.ts +13 -0
  32. package/dist/core/layout/config.d.ts +33 -0
  33. package/dist/core/layout/index.d.ts +51 -0
  34. package/dist/core/layout/jsx.d.ts +65 -0
  35. package/dist/core/layout/schema.d.ts +112 -0
  36. package/dist/core/layout/types.d.ts +69 -0
  37. package/dist/core/viewport/constants.d.ts +105 -0
  38. package/dist/core/viewport/features/base.d.ts +14 -0
  39. package/dist/core/viewport/features/collection.d.ts +41 -0
  40. package/dist/core/viewport/features/events.d.ts +13 -0
  41. package/{src/core/viewport/features/index.ts → dist/core/viewport/features/index.d.ts} +0 -7
  42. package/dist/core/viewport/features/item-size.d.ts +30 -0
  43. package/dist/core/viewport/features/loading.d.ts +34 -0
  44. package/dist/core/viewport/features/momentum.d.ts +17 -0
  45. package/dist/core/viewport/features/performance.d.ts +53 -0
  46. package/dist/core/viewport/features/placeholders.d.ts +38 -0
  47. package/dist/core/viewport/features/rendering.d.ts +16 -0
  48. package/dist/core/viewport/features/scrollbar.d.ts +26 -0
  49. package/dist/core/viewport/features/scrolling.d.ts +16 -0
  50. package/dist/core/viewport/features/utils.d.ts +43 -0
  51. package/dist/core/viewport/features/virtual.d.ts +18 -0
  52. package/{src/core/viewport/index.ts → dist/core/viewport/index.d.ts} +1 -17
  53. package/dist/core/viewport/types.d.ts +96 -0
  54. package/dist/core/viewport/utils/speed-tracker.d.ts +22 -0
  55. package/dist/core/viewport/viewport.d.ts +11 -0
  56. package/{src/index.ts → dist/index.d.ts} +0 -4
  57. package/dist/index.js +5143 -0
  58. package/dist/index.mjs +5111 -0
  59. package/dist/styles.css +254 -0
  60. package/dist/styles.css.map +1 -0
  61. package/package.json +6 -1
  62. package/src/styles/components/_vlist.scss +234 -213
  63. package/.cursorrules +0 -117
  64. package/AI.md +0 -241
  65. package/build.js +0 -201
  66. package/scripts/analyze-orphaned-functions.ts +0 -387
  67. package/scripts/debug/vlist-selection.ts +0 -121
  68. package/src/components/vlist/config.ts +0 -323
  69. package/src/components/vlist/features/api.ts +0 -322
  70. package/src/components/vlist/features/selection.ts +0 -444
  71. package/src/components/vlist/features/viewport.ts +0 -65
  72. package/src/components/vlist/features.ts +0 -112
  73. package/src/components/vlist/types.ts +0 -591
  74. package/src/components/vlist/vlist.ts +0 -92
  75. package/src/core/compose/features/gestures/index.ts +0 -227
  76. package/src/core/compose/features/gestures/longpress.ts +0 -383
  77. package/src/core/compose/features/gestures/pan.ts +0 -424
  78. package/src/core/compose/features/gestures/pinch.ts +0 -475
  79. package/src/core/compose/features/gestures/rotate.ts +0 -485
  80. package/src/core/compose/features/gestures/swipe.ts +0 -492
  81. package/src/core/compose/features/gestures/tap.ts +0 -334
  82. package/src/core/gestures/longpress.ts +0 -68
  83. package/src/core/gestures/manager.ts +0 -418
  84. package/src/core/gestures/pan.ts +0 -48
  85. package/src/core/gestures/pinch.ts +0 -58
  86. package/src/core/gestures/rotate.ts +0 -58
  87. package/src/core/gestures/swipe.ts +0 -66
  88. package/src/core/gestures/tap.ts +0 -45
  89. package/src/core/gestures/types.ts +0 -387
  90. package/src/core/gestures/utils.ts +0 -128
  91. package/src/core/index.ts +0 -43
  92. package/src/core/layout/config.ts +0 -102
  93. package/src/core/layout/index.ts +0 -168
  94. package/src/core/layout/jsx.ts +0 -174
  95. package/src/core/layout/schema.ts +0 -1001
  96. package/src/core/layout/types.ts +0 -95
  97. package/src/core/viewport/constants.ts +0 -140
  98. package/src/core/viewport/features/base.ts +0 -73
  99. package/src/core/viewport/features/collection.ts +0 -882
  100. package/src/core/viewport/features/events.ts +0 -130
  101. package/src/core/viewport/features/item-size.ts +0 -271
  102. package/src/core/viewport/features/loading.ts +0 -263
  103. package/src/core/viewport/features/momentum.ts +0 -260
  104. package/src/core/viewport/features/performance.ts +0 -161
  105. package/src/core/viewport/features/placeholders.ts +0 -335
  106. package/src/core/viewport/features/rendering.ts +0 -568
  107. package/src/core/viewport/features/scrollbar.ts +0 -434
  108. package/src/core/viewport/features/scrolling.ts +0 -618
  109. package/src/core/viewport/features/utils.ts +0 -88
  110. package/src/core/viewport/features/virtual.ts +0 -384
  111. package/src/core/viewport/types.ts +0 -133
  112. package/src/core/viewport/utils/speed-tracker.ts +0 -79
  113. package/src/core/viewport/viewport.ts +0 -246
  114. package/test/benchmarks/layout/advanced.test.ts +0 -656
  115. package/test/benchmarks/layout/comparison.test.ts +0 -519
  116. package/test/benchmarks/layout/performance-comparison.test.ts +0 -274
  117. package/test/benchmarks/layout/real-components.test.ts +0 -733
  118. package/test/benchmarks/layout/simple.test.ts +0 -321
  119. package/test/benchmarks/layout/stress.test.ts +0 -990
  120. package/test/collection/basic.test.ts +0 -304
  121. package/test/components/vlist-selection.test.ts +0 -240
  122. package/test/components/vlist.test.ts +0 -63
  123. package/test/core/collection/adapter.test.ts +0 -161
  124. package/test/core/collection/collection.test.ts +0 -394
  125. package/test/core/layout/layout.test.ts +0 -201
  126. package/test/utils/dom-helpers.ts +0 -275
  127. package/test/utils/performance-helpers.ts +0 -392
  128. package/tsconfig.json +0 -20
@@ -1,161 +0,0 @@
1
- // test/core/collection/adapter.test.ts
2
-
3
- import { describe, test, expect, beforeEach } from "bun:test";
4
- import {
5
- createRouteAdapter,
6
- withRouteAdapter,
7
- } from "../../../src/core/collection/features/adapter";
8
- import { createCollection } from "../../../src/core/collection";
9
-
10
- describe("Route Adapter", () => {
11
- let fetchMock: any;
12
-
13
- beforeEach(() => {
14
- // Mock fetch
15
- fetchMock = {
16
- calls: [] as any[],
17
- response: {
18
- items: [
19
- { id: "1", name: "Item 1" },
20
- { id: "2", name: "Item 2" },
21
- ],
22
- meta: {
23
- total: 100,
24
- hasNext: true,
25
- cursor: "next-cursor",
26
- },
27
- },
28
- };
29
-
30
- global.fetch = async (url: any, options: any) => {
31
- fetchMock.calls.push({ url, options });
32
- return {
33
- ok: true,
34
- headers: {
35
- get: () => "application/json",
36
- },
37
- json: async () => fetchMock.response,
38
- } as any;
39
- };
40
- });
41
-
42
- describe("createRouteAdapter", () => {
43
- test("creates adapter with default config", () => {
44
- const adapter = createRouteAdapter();
45
- expect(adapter).toBeDefined();
46
- expect(adapter.read).toBeDefined();
47
- expect(adapter.disconnect).toBeDefined();
48
- });
49
-
50
- test("makes API request with correct parameters", async () => {
51
- const adapter = createRouteAdapter({
52
- base: "/api",
53
- endpoints: { list: "/users" },
54
- headers: { Authorization: "Bearer token" },
55
- pagination: { strategy: "offset" }, // Use offset strategy for this test
56
- });
57
-
58
- const result = await adapter.read({
59
- offset: 0,
60
- limit: 20,
61
- search: "john",
62
- sort: "name",
63
- });
64
-
65
- expect(fetchMock.calls).toHaveLength(1);
66
- const [call] = fetchMock.calls;
67
- expect(call.url).toContain("/api/users");
68
- expect(call.url).toContain("offset=0");
69
- expect(call.url).toContain("limit=20");
70
- expect(call.url).toContain("search=john");
71
- expect(call.url).toContain("sort=name");
72
- expect(call.options.headers["Authorization"]).toBe("Bearer token");
73
- });
74
-
75
- test("handles different pagination strategies", async () => {
76
- // Cursor pagination
77
- const cursorAdapter = createRouteAdapter({
78
- base: "/api",
79
- endpoints: { list: "/items" },
80
- pagination: { strategy: "cursor" },
81
- });
82
-
83
- await cursorAdapter.read({ cursor: "abc123", limit: 10 });
84
- expect(fetchMock.calls[0].url).toContain("cursor=abc123");
85
-
86
- // Page pagination
87
- const pageAdapter = createRouteAdapter({
88
- base: "/api",
89
- endpoints: { list: "/items" },
90
- pagination: { strategy: "page" },
91
- });
92
-
93
- await pageAdapter.read({ page: 3, limit: 10 });
94
- expect(fetchMock.calls[1].url).toContain("page=3");
95
- });
96
-
97
- test("transforms query operators", async () => {
98
- const adapter = createRouteAdapter({
99
- base: "/api",
100
- endpoints: { list: "/items" },
101
- });
102
-
103
- await adapter.read({
104
- filters: {
105
- age: { GT: 18, LTE: 65 },
106
- status: { EQ: "active" },
107
- tags: { IN: ["premium", "verified"] },
108
- },
109
- });
110
-
111
- const url = fetchMock.calls[0].url;
112
- expect(url).toContain("age_gt=18");
113
- expect(url).toContain("age_lte=65");
114
- expect(url).toContain("status_eq=active");
115
- expect(url).toContain("tags_in=premium");
116
- expect(url).toContain("tags_in=verified");
117
- });
118
-
119
- test("handles caching", async () => {
120
- const adapter = createRouteAdapter({
121
- base: "/api",
122
- endpoints: { list: "/items" },
123
- cache: true,
124
- pagination: { strategy: "offset" }, // Use offset strategy to test offset params
125
- });
126
-
127
- // First call
128
- await adapter.read({ offset: 0, limit: 10 });
129
- expect(fetchMock.calls).toHaveLength(1);
130
-
131
- // Second call with same params - should use cache
132
- await adapter.read({ offset: 0, limit: 10 });
133
- expect(fetchMock.calls).toHaveLength(1);
134
-
135
- // Different params - should make new request
136
- await adapter.read({ offset: 10, limit: 10 });
137
- expect(fetchMock.calls).toHaveLength(2);
138
- });
139
- });
140
-
141
- describe("withRouteAdapter", () => {
142
- test("adds route adapter to collection", async () => {
143
- const collection = createCollection({
144
- pageSize: 20,
145
- });
146
-
147
- const enhancedCollection = withRouteAdapter({
148
- base: "/api",
149
- endpoints: { list: "/users" },
150
- })(collection);
151
-
152
- expect(enhancedCollection.disconnect).toBeDefined();
153
-
154
- // Load data
155
- await enhancedCollection.loadPage(1);
156
-
157
- expect(fetchMock.calls).toHaveLength(1);
158
- expect(fetchMock.calls[0].url).toContain("/api/users");
159
- });
160
- });
161
- });
@@ -1,394 +0,0 @@
1
- // test/core/collection/collection.test.ts - Core Collection Tests
2
- import {
3
- describe,
4
- test,
5
- expect,
6
- mock,
7
- beforeAll,
8
- afterAll,
9
- beforeEach,
10
- afterEach,
11
- } from "bun:test";
12
- import { JSDOM } from "jsdom";
13
-
14
- // Setup for DOM testing environment
15
- let dom: JSDOM;
16
- let window: Window;
17
- let document: Document;
18
- let originalGlobalDocument: any;
19
- let originalGlobalWindow: any;
20
-
21
- // Setup DOM environment before importing modules
22
- beforeAll(() => {
23
- // Create a new JSDOM instance
24
- dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
25
- url: "http://localhost/",
26
- pretendToBeVisual: true,
27
- resources: "usable",
28
- });
29
-
30
- // Get window and document from jsdom
31
- window = dom.window as any;
32
- document = window.document;
33
-
34
- // Store original globals
35
- originalGlobalDocument = global.document;
36
- originalGlobalWindow = global.window;
37
-
38
- // Set globals to use jsdom
39
- global.document = document;
40
- global.window = window as any;
41
- global.Element = (window as any).Element;
42
- global.HTMLElement = (window as any).HTMLElement;
43
- global.DocumentFragment = (window as any).DocumentFragment;
44
- global.requestAnimationFrame = (window as any).requestAnimationFrame;
45
- global.cancelAnimationFrame = (window as any).cancelAnimationFrame;
46
-
47
- // Add missing DOM APIs
48
- global.getComputedStyle =
49
- (window as any).getComputedStyle ||
50
- (() => ({
51
- position: "static",
52
- getPropertyValue: () => "",
53
- }));
54
-
55
- // Add IntersectionObserver mock
56
- if (!(window as any).IntersectionObserver) {
57
- const IntersectionObserverMock = class {
58
- constructor() {}
59
- observe() {}
60
- disconnect() {}
61
- unobserve() {}
62
- };
63
- (window as any).IntersectionObserver = IntersectionObserverMock as any;
64
- (global as any).IntersectionObserver = IntersectionObserverMock as any;
65
- }
66
-
67
- // Add ResizeObserver mock
68
- if (!(window as any).ResizeObserver) {
69
- const ResizeObserverMock = class {
70
- constructor() {}
71
- observe() {}
72
- disconnect() {}
73
- unobserve() {}
74
- };
75
- (window as any).ResizeObserver = ResizeObserverMock as any;
76
- (global as any).ResizeObserver = ResizeObserverMock as any;
77
- }
78
- });
79
-
80
- afterAll(() => {
81
- // Restore original globals
82
- global.document = originalGlobalDocument;
83
- global.window = originalGlobalWindow;
84
-
85
- // Clean up jsdom
86
- window.close();
87
- });
88
-
89
- // Import the collection after DOM setup
90
- // TODO: Implement these imports as we build the system
91
- // import { createCollection, pipe, withEvents, withLifecycle } from "../../../src/core/collection";
92
-
93
- // Test data interfaces
94
- interface TestItem {
95
- id: string;
96
- name: string;
97
- email: string;
98
- age: number;
99
- active: boolean;
100
- }
101
-
102
- interface TestProduct {
103
- id: string;
104
- title: string;
105
- price: number;
106
- category: string;
107
- }
108
-
109
- // Helper functions for creating test data
110
- function createTestItem(
111
- id: string,
112
- overrides: Partial<TestItem> = {}
113
- ): TestItem {
114
- return {
115
- id,
116
- name: `User ${id}`,
117
- email: `user${id}@example.com`,
118
- age: 20 + parseInt(id),
119
- active: true,
120
- ...overrides,
121
- };
122
- }
123
-
124
- function createTestProduct(
125
- id: string,
126
- overrides: Partial<TestProduct> = {}
127
- ): TestProduct {
128
- return {
129
- id,
130
- title: `Product ${id}`,
131
- price: parseFloat(id) * 10,
132
- category: "electronics",
133
- ...overrides,
134
- };
135
- }
136
-
137
- // Mock template engine
138
- const mockTemplateEngine = {
139
- render: mock((template: any, data: any) => {
140
- const element = document.createElement("div");
141
- element.className = "test-item";
142
- element.setAttribute("data-id", data.id);
143
- element.innerHTML = `
144
- <div class="item-name">${data.name}</div>
145
- <div class="item-email">${data.email}</div>
146
- `;
147
- return element;
148
- }),
149
-
150
- compile: mock((template: any) => {
151
- return (data: any) => mockTemplateEngine.render(template, data);
152
- }),
153
- };
154
-
155
- // Mock adapter for data loading
156
- const mockAdapter = {
157
- read: mock(async (params: any) => {
158
- const page = params.page || 1;
159
- const limit = params.limit || params.per_page || 20;
160
- const startId = (page - 1) * limit + 1;
161
-
162
- const items: TestItem[] = [];
163
- for (let i = 0; i < limit; i++) {
164
- const id = startId + i;
165
- if (id <= 100) {
166
- items.push(createTestItem(id.toString()));
167
- }
168
- }
169
-
170
- return {
171
- items,
172
- meta: {
173
- total: 100,
174
- page,
175
- hasNext: page * limit < 100,
176
- nextCursor: items.length > 0 ? items[items.length - 1].id : null,
177
- },
178
- };
179
- }),
180
- };
181
-
182
- describe("Collection System", () => {
183
- let container: HTMLElement;
184
-
185
- beforeEach(() => {
186
- // Create fresh container for each test
187
- container = document.createElement("div");
188
- container.style.height = "400px";
189
- container.style.overflow = "auto";
190
- document.body.appendChild(container);
191
-
192
- // Reset mocks
193
- mockTemplateEngine.render.mockClear();
194
- mockTemplateEngine.compile.mockClear();
195
- mockAdapter.read.mockClear();
196
- });
197
-
198
- afterEach(() => {
199
- // Cleanup container
200
- if (container && container.parentNode) {
201
- container.parentNode.removeChild(container);
202
- }
203
- });
204
-
205
- describe("Basic Infrastructure", () => {
206
- test("DOM environment is properly set up", () => {
207
- expect(document).toBeDefined();
208
- expect(document.createElement).toBeDefined();
209
- expect(global.IntersectionObserver).toBeDefined();
210
- expect(global.ResizeObserver).toBeDefined();
211
- });
212
-
213
- test("test container is created correctly", () => {
214
- expect(container).toBeDefined();
215
- expect(container.style.height).toBe("400px");
216
- expect(container.style.overflow).toBe("auto");
217
- expect(container.parentNode).toBe(document.body);
218
- });
219
-
220
- test("test data helpers work correctly", () => {
221
- const item = createTestItem("123");
222
- expect(item.id).toBe("123");
223
- expect(item.name).toBe("User 123");
224
- expect(item.email).toBe("user123@example.com");
225
- expect(item.age).toBe(143);
226
- expect(item.active).toBe(true);
227
-
228
- const customItem = createTestItem("456", { name: "Custom User" });
229
- expect(customItem.name).toBe("Custom User");
230
- expect(customItem.id).toBe("456");
231
- });
232
-
233
- test("mock template engine renders correctly", () => {
234
- const template = { tag: "div", text: "{{name}}" };
235
- const data = { id: "1", name: "John Doe", email: "john@example.com" };
236
-
237
- const element = mockTemplateEngine.render(template, data);
238
-
239
- expect(element.tagName).toBe("DIV");
240
- expect(element.className).toBe("test-item");
241
- expect(element.getAttribute("data-id")).toBe("1");
242
- expect(element.querySelector(".item-name")?.textContent).toBe("John Doe");
243
- });
244
-
245
- test("mock adapter generates test data correctly", async () => {
246
- const result = await mockAdapter.read({ page: 1, per_page: 5 });
247
-
248
- expect(result.items).toHaveLength(5);
249
- expect(result.meta.total).toBe(100);
250
- expect(result.meta.page).toBe(1);
251
- expect(result.meta.hasNext).toBe(true);
252
-
253
- // Check first item
254
- expect(result.items[0].id).toBe("1");
255
- expect(result.items[0].name).toBe("User 1");
256
- });
257
- });
258
-
259
- describe("Collection Core (Placeholder)", () => {
260
- test("placeholder for collection creation", () => {
261
- // TODO: Implement when createCollection is available
262
- // const collection = createCollection({ items: [] });
263
- // expect(collection).toBeDefined();
264
-
265
- // Placeholder assertion
266
- expect(true).toBe(true);
267
- });
268
-
269
- test("placeholder for functional composition", () => {
270
- // TODO: Implement when pipe and features are available
271
- // const collection = pipe(
272
- // createCollection(config),
273
- // withEvents(),
274
- // withLifecycle()
275
- // );
276
- // expect(collection).toBeDefined();
277
-
278
- // Placeholder assertion
279
- expect(true).toBe(true);
280
- });
281
- });
282
-
283
- describe("Template Engine Integration (Placeholder)", () => {
284
- test("placeholder for template compilation", () => {
285
- // TODO: Implement when template engine is available
286
- // const engine = createTemplateEngine('object');
287
- // const template = { tag: 'div', text: '{{name}}' };
288
- // const compiled = engine.compile(template);
289
- // expect(compiled).toBeDefined();
290
-
291
- // Test mock for now
292
- const compiled = mockTemplateEngine.compile({
293
- tag: "div",
294
- text: "{{name}}",
295
- });
296
- expect(compiled).toBeDefined();
297
- expect(mockTemplateEngine.compile).toHaveBeenCalled();
298
- });
299
-
300
- test("placeholder for element recycling", () => {
301
- // TODO: Implement when recycling pool is available
302
- // const pool = createRecyclingPool({ maxSize: 10 });
303
- // const element = pool.getElement();
304
- // expect(element).toBeDefined();
305
-
306
- // Placeholder assertion
307
- expect(true).toBe(true);
308
- });
309
- });
310
-
311
- describe("Performance Testing Framework", () => {
312
- test("measures render time accurately", async () => {
313
- const start = performance.now();
314
-
315
- // Simulate some work
316
- await new Promise((resolve) => setTimeout(resolve, 10));
317
-
318
- const end = performance.now();
319
- const duration = end - start;
320
-
321
- expect(duration).toBeGreaterThan(5);
322
- expect(duration).toBeLessThan(50);
323
- });
324
-
325
- test("creates large datasets for performance testing", () => {
326
- const items = Array.from({ length: 1000 }, (_, i) =>
327
- createTestItem(i.toString())
328
- );
329
-
330
- expect(items).toHaveLength(1000);
331
- expect(items[0].id).toBe("0");
332
- expect(items[999].id).toBe("999");
333
- });
334
-
335
- test("simulates scroll events correctly", () => {
336
- let scrollEventFired = false;
337
-
338
- container.addEventListener("scroll", () => {
339
- scrollEventFired = true;
340
- });
341
-
342
- container.scrollTop = 100;
343
- const scrollEvent = new (window as any).Event("scroll", {
344
- bubbles: true,
345
- });
346
- container.dispatchEvent(scrollEvent);
347
-
348
- expect(scrollEventFired).toBe(true);
349
- expect(container.scrollTop).toBe(100);
350
- });
351
- });
352
-
353
- describe("Memory Management Testing", () => {
354
- test("cleans up event listeners", () => {
355
- const listener = mock(() => {});
356
-
357
- container.addEventListener("scroll", listener);
358
-
359
- // Simulate cleanup
360
- container.removeEventListener("scroll", listener);
361
-
362
- // Fire event - should not call listener
363
- const scrollEvent = new (window as any).Event("scroll", {
364
- bubbles: true,
365
- });
366
- container.dispatchEvent(scrollEvent);
367
-
368
- expect(listener).not.toHaveBeenCalled();
369
- });
370
-
371
- test("handles rapid element creation/destruction", () => {
372
- const elements: HTMLElement[] = [];
373
-
374
- // Create many elements
375
- for (let i = 0; i < 100; i++) {
376
- const element = document.createElement("div");
377
- element.textContent = `Item ${i}`;
378
- elements.push(element);
379
- }
380
-
381
- expect(elements).toHaveLength(100);
382
-
383
- // Clean up
384
- elements.forEach((element) => {
385
- element.remove();
386
- });
387
-
388
- expect(elements[0].isConnected).toBe(false);
389
- });
390
- });
391
- });
392
-
393
- // Export test utilities for use in other test files
394
- export { createTestItem, createTestProduct, mockTemplateEngine, mockAdapter };