@livetemplate/client 0.8.21 → 0.8.23

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 (38) hide show
  1. package/dist/dom/directives.d.ts +16 -0
  2. package/dist/dom/directives.d.ts.map +1 -1
  3. package/dist/dom/directives.js +56 -6
  4. package/dist/dom/directives.js.map +1 -1
  5. package/dist/dom/event-delegation.d.ts +9 -1
  6. package/dist/dom/event-delegation.d.ts.map +1 -1
  7. package/dist/dom/event-delegation.js +72 -25
  8. package/dist/dom/event-delegation.js.map +1 -1
  9. package/dist/dom/link-interceptor.d.ts +14 -0
  10. package/dist/dom/link-interceptor.d.ts.map +1 -1
  11. package/dist/dom/link-interceptor.js +43 -2
  12. package/dist/dom/link-interceptor.js.map +1 -1
  13. package/dist/dom/observer-manager.d.ts +10 -0
  14. package/dist/dom/observer-manager.d.ts.map +1 -1
  15. package/dist/dom/observer-manager.js +110 -3
  16. package/dist/dom/observer-manager.js.map +1 -1
  17. package/dist/livetemplate-client.browser.js +5 -5
  18. package/dist/livetemplate-client.browser.js.map +3 -3
  19. package/dist/livetemplate-client.d.ts +41 -3
  20. package/dist/livetemplate-client.d.ts.map +1 -1
  21. package/dist/livetemplate-client.js +189 -33
  22. package/dist/livetemplate-client.js.map +1 -1
  23. package/dist/tests/directives.test.js +23 -1
  24. package/dist/tests/directives.test.js.map +1 -1
  25. package/dist/tests/navigation.test.d.ts +2 -0
  26. package/dist/tests/navigation.test.d.ts.map +1 -0
  27. package/dist/tests/navigation.test.js +308 -0
  28. package/dist/tests/navigation.test.js.map +1 -0
  29. package/dist/tests/observer-manager.test.js +152 -4
  30. package/dist/tests/observer-manager.test.js.map +1 -1
  31. package/dist/tests/websocket.test.js +115 -0
  32. package/dist/tests/websocket.test.js.map +1 -1
  33. package/dist/transport/websocket.d.ts +7 -0
  34. package/dist/transport/websocket.d.ts.map +1 -1
  35. package/dist/transport/websocket.js +96 -4
  36. package/dist/transport/websocket.js.map +1 -1
  37. package/livetemplate.css +23 -6
  38. package/package.json +1 -1
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const livetemplate_client_1 = require("../livetemplate-client");
4
+ describe("handleNavigationResponse", () => {
5
+ let client;
6
+ let wrapper;
7
+ beforeEach(() => {
8
+ document.body.innerHTML = ""; // safe: test cleanup, matches existing pattern
9
+ document.title = "Initial Title";
10
+ wrapper = document.createElement("div");
11
+ wrapper.setAttribute("data-lvt-id", "lvt-handler-a");
12
+ wrapper.appendChild(document.createTextNode("Handler A content"));
13
+ document.body.appendChild(wrapper);
14
+ client = new livetemplate_client_1.LiveTemplateClient();
15
+ client.wrapperElement = wrapper;
16
+ });
17
+ afterEach(() => {
18
+ document.body.innerHTML = ""; // safe: test cleanup
19
+ });
20
+ const callHandleNavigationResponse = (html) => {
21
+ client.handleNavigationResponse(html);
22
+ };
23
+ describe("same-handler navigation", () => {
24
+ it("replaces wrapper children when response has same data-lvt-id", () => {
25
+ const html = [
26
+ "<html><head><title>Same Page</title></head><body>",
27
+ '<div data-lvt-id="lvt-handler-a">',
28
+ "<p>Updated content from same handler</p>",
29
+ "</div>",
30
+ "</body></html>",
31
+ ].join("");
32
+ callHandleNavigationResponse(html);
33
+ expect(wrapper.textContent).toContain("Updated content from same handler");
34
+ expect(wrapper.getAttribute("data-lvt-id")).toBe("lvt-handler-a");
35
+ });
36
+ it("preserves wrapper element identity", () => {
37
+ const originalWrapper = wrapper;
38
+ const html = [
39
+ "<html><body>",
40
+ '<div data-lvt-id="lvt-handler-a">',
41
+ "<p>New content</p>",
42
+ "</div>",
43
+ "</body></html>",
44
+ ].join("");
45
+ callHandleNavigationResponse(html);
46
+ expect(client.wrapperElement).toBe(originalWrapper);
47
+ });
48
+ });
49
+ describe("cross-handler navigation", () => {
50
+ it("updates wrapper ID when response has different data-lvt-id", () => {
51
+ const disconnectSpy = jest
52
+ .spyOn(client, "disconnect")
53
+ .mockImplementation(() => { });
54
+ const connectSpy = jest
55
+ .spyOn(client, "connect")
56
+ .mockResolvedValue(undefined);
57
+ const html = [
58
+ "<html><body>",
59
+ '<div data-lvt-id="lvt-handler-b">',
60
+ "<p>Handler B content</p>",
61
+ "</div>",
62
+ "</body></html>",
63
+ ].join("");
64
+ callHandleNavigationResponse(html);
65
+ expect(wrapper.getAttribute("data-lvt-id")).toBe("lvt-handler-b");
66
+ expect(wrapper.textContent).toContain("Handler B content");
67
+ disconnectSpy.mockRestore();
68
+ connectSpy.mockRestore();
69
+ });
70
+ it("disconnects old handler", () => {
71
+ const disconnectSpy = jest
72
+ .spyOn(client, "disconnect")
73
+ .mockImplementation(() => { });
74
+ const connectSpy = jest
75
+ .spyOn(client, "connect")
76
+ .mockResolvedValue(undefined);
77
+ const html = [
78
+ "<html><body>",
79
+ '<div data-lvt-id="lvt-handler-b">',
80
+ "<p>Handler B</p>",
81
+ "</div>",
82
+ "</body></html>",
83
+ ].join("");
84
+ callHandleNavigationResponse(html);
85
+ expect(disconnectSpy).toHaveBeenCalledTimes(1);
86
+ disconnectSpy.mockRestore();
87
+ connectSpy.mockRestore();
88
+ });
89
+ it("reconnects to the new handler", () => {
90
+ const disconnectSpy = jest
91
+ .spyOn(client, "disconnect")
92
+ .mockImplementation(() => { });
93
+ const connectSpy = jest
94
+ .spyOn(client, "connect")
95
+ .mockResolvedValue(undefined);
96
+ const html = [
97
+ "<html><body>",
98
+ '<div data-lvt-id="lvt-handler-b">',
99
+ "<p>Handler B</p>",
100
+ "</div>",
101
+ "</body></html>",
102
+ ].join("");
103
+ callHandleNavigationResponse(html);
104
+ expect(connectSpy).toHaveBeenCalledWith('[data-lvt-id="lvt-handler-b"]');
105
+ disconnectSpy.mockRestore();
106
+ connectSpy.mockRestore();
107
+ });
108
+ it("falls back to page reload if reconnect fails", () => {
109
+ const disconnectSpy = jest
110
+ .spyOn(client, "disconnect")
111
+ .mockImplementation(() => { });
112
+ const connectSpy = jest
113
+ .spyOn(client, "connect")
114
+ .mockRejectedValue(new Error("connection failed"));
115
+ const html = [
116
+ "<html><body>",
117
+ '<div data-lvt-id="lvt-handler-b">',
118
+ "<p>Handler B</p>",
119
+ "</div>",
120
+ "</body></html>",
121
+ ].join("");
122
+ expect(() => callHandleNavigationResponse(html)).not.toThrow();
123
+ expect(disconnectSpy).toHaveBeenCalled();
124
+ expect(connectSpy).toHaveBeenCalled();
125
+ disconnectSpy.mockRestore();
126
+ connectSpy.mockRestore();
127
+ });
128
+ it("cleans up stale event listeners from old wrapper ID", () => {
129
+ const disconnectSpy = jest
130
+ .spyOn(client, "disconnect")
131
+ .mockImplementation(() => { });
132
+ const connectSpy = jest
133
+ .spyOn(client, "connect")
134
+ .mockResolvedValue(undefined);
135
+ // Simulate an existing listener keyed to old wrapper ID
136
+ const oldListener = jest.fn();
137
+ document["__lvt_link_intercept_lvt-handler-a"] = oldListener;
138
+ document.addEventListener("click", oldListener);
139
+ const html = [
140
+ "<html><body>",
141
+ '<div data-lvt-id="lvt-handler-b">',
142
+ "<p>Handler B</p>",
143
+ "</div>",
144
+ "</body></html>",
145
+ ].join("");
146
+ callHandleNavigationResponse(html);
147
+ // Old listener key should be removed
148
+ expect(document["__lvt_link_intercept_lvt-handler-a"]).toBeUndefined();
149
+ disconnectSpy.mockRestore();
150
+ connectSpy.mockRestore();
151
+ });
152
+ it("sets up event delegation and link interception immediately (before async connect)", () => {
153
+ const disconnectSpy = jest
154
+ .spyOn(client, "disconnect")
155
+ .mockImplementation(() => { });
156
+ // Make connect() return a promise that never resolves to prove the
157
+ // synchronous setup happens regardless of whether connect completes
158
+ const connectSpy = jest
159
+ .spyOn(client, "connect")
160
+ .mockReturnValue(new Promise(() => { }));
161
+ // Spy on the real internal setup methods
162
+ const eventSetupSpy = jest.spyOn(client.eventDelegator, "setupEventDelegation");
163
+ const linkSetupSpy = jest.spyOn(client.linkInterceptor, "setup");
164
+ const html = [
165
+ "<html><body>",
166
+ '<div data-lvt-id="lvt-handler-b">',
167
+ "<p>Handler B</p>",
168
+ "</div>",
169
+ "</body></html>",
170
+ ].join("");
171
+ callHandleNavigationResponse(html);
172
+ // Both setup methods must have been called synchronously
173
+ expect(eventSetupSpy).toHaveBeenCalled();
174
+ expect(linkSetupSpy).toHaveBeenCalled();
175
+ disconnectSpy.mockRestore();
176
+ connectSpy.mockRestore();
177
+ eventSetupSpy.mockRestore();
178
+ linkSetupSpy.mockRestore();
179
+ });
180
+ it("scrolls to top on cross-handler navigation", () => {
181
+ const disconnectSpy = jest
182
+ .spyOn(client, "disconnect")
183
+ .mockImplementation(() => { });
184
+ const connectSpy = jest
185
+ .spyOn(client, "connect")
186
+ .mockResolvedValue(undefined);
187
+ const scrollSpy = jest
188
+ .spyOn(window, "scrollTo")
189
+ .mockImplementation(() => { });
190
+ const html = [
191
+ "<html><body>",
192
+ '<div data-lvt-id="lvt-handler-b">',
193
+ "<p>Handler B</p>",
194
+ "</div>",
195
+ "</body></html>",
196
+ ].join("");
197
+ callHandleNavigationResponse(html);
198
+ expect(scrollSpy).toHaveBeenCalledWith(0, 0);
199
+ disconnectSpy.mockRestore();
200
+ connectSpy.mockRestore();
201
+ scrollSpy.mockRestore();
202
+ });
203
+ });
204
+ describe("title updates", () => {
205
+ it("updates document.title from response", () => {
206
+ const html = [
207
+ "<html><head><title>New Page Title</title></head><body>",
208
+ '<div data-lvt-id="lvt-handler-a">',
209
+ "<p>Content</p>",
210
+ "</div>",
211
+ "</body></html>",
212
+ ].join("");
213
+ callHandleNavigationResponse(html);
214
+ expect(document.title).toBe("New Page Title");
215
+ });
216
+ it("updates title on cross-handler navigation", () => {
217
+ const disconnectSpy = jest
218
+ .spyOn(client, "disconnect")
219
+ .mockImplementation(() => { });
220
+ const connectSpy = jest
221
+ .spyOn(client, "connect")
222
+ .mockResolvedValue(undefined);
223
+ const html = [
224
+ "<html><head><title>Handler B Title</title></head><body>",
225
+ '<div data-lvt-id="lvt-handler-b">',
226
+ "<p>Handler B</p>",
227
+ "</div>",
228
+ "</body></html>",
229
+ ].join("");
230
+ callHandleNavigationResponse(html);
231
+ expect(document.title).toBe("Handler B Title");
232
+ disconnectSpy.mockRestore();
233
+ connectSpy.mockRestore();
234
+ });
235
+ it("does not change title when response has no title element", () => {
236
+ const html = [
237
+ "<html><body>",
238
+ '<div data-lvt-id="lvt-handler-a">',
239
+ "<p>No title page</p>",
240
+ "</div>",
241
+ "</body></html>",
242
+ ].join("");
243
+ callHandleNavigationResponse(html);
244
+ expect(document.title).toBe("Initial Title");
245
+ });
246
+ });
247
+ describe("non-LiveTemplate response", () => {
248
+ it("uses body content when response has no data-lvt-id wrapper", () => {
249
+ const disconnectSpy = jest
250
+ .spyOn(client, "disconnect")
251
+ .mockImplementation(() => { });
252
+ const html = [
253
+ "<html><body>",
254
+ "<div><p>Plain HTML page</p></div>",
255
+ "</body></html>",
256
+ ].join("");
257
+ callHandleNavigationResponse(html);
258
+ expect(wrapper.textContent).toContain("Plain HTML page");
259
+ expect(wrapper.getAttribute("data-lvt-id")).toBe("lvt-handler-a");
260
+ disconnectSpy.mockRestore();
261
+ });
262
+ it("disconnects old WebSocket on non-LiveTemplate fallback", () => {
263
+ const disconnectSpy = jest
264
+ .spyOn(client, "disconnect")
265
+ .mockImplementation(() => { });
266
+ const html = [
267
+ "<html><body>",
268
+ "<div><p>Plain HTML page</p></div>",
269
+ "</body></html>",
270
+ ].join("");
271
+ callHandleNavigationResponse(html);
272
+ expect(disconnectSpy).toHaveBeenCalledTimes(1);
273
+ disconnectSpy.mockRestore();
274
+ });
275
+ it("tears down stale listeners on non-LiveTemplate fallback", () => {
276
+ const disconnectSpy = jest
277
+ .spyOn(client, "disconnect")
278
+ .mockImplementation(() => { });
279
+ // Spy on teardownForWrapper to verify it's called with the old ID
280
+ const linkTeardownSpy = jest.spyOn(client.linkInterceptor, "teardownForWrapper");
281
+ const eventTeardownSpy = jest.spyOn(client.eventDelegator, "teardownForWrapper");
282
+ const html = [
283
+ "<html><body>",
284
+ "<div><p>Plain HTML page</p></div>",
285
+ "</body></html>",
286
+ ].join("");
287
+ callHandleNavigationResponse(html);
288
+ // Both teardown methods must be called with the old wrapper ID
289
+ // before the fallback path re-registers listeners.
290
+ expect(linkTeardownSpy).toHaveBeenCalledWith("lvt-handler-a");
291
+ expect(eventTeardownSpy).toHaveBeenCalledWith("lvt-handler-a");
292
+ disconnectSpy.mockRestore();
293
+ linkTeardownSpy.mockRestore();
294
+ eventTeardownSpy.mockRestore();
295
+ });
296
+ });
297
+ describe("edge cases", () => {
298
+ it("handles empty response body gracefully", () => {
299
+ const html = "<html><body></body></html>";
300
+ expect(() => callHandleNavigationResponse(html)).not.toThrow();
301
+ });
302
+ it("does nothing when wrapperElement is null", () => {
303
+ client.wrapperElement = null;
304
+ expect(() => callHandleNavigationResponse("<html><body></body></html>")).not.toThrow();
305
+ });
306
+ });
307
+ });
308
+ //# sourceMappingURL=navigation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.test.js","sourceRoot":"","sources":["../../tests/navigation.test.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const observer_manager_1 = require("../dom/observer-manager");
4
4
  const logger_1 = require("../utils/logger");
5
- // Mock IntersectionObserver
5
+ // Mock IntersectionObserver. Tracks instances and disconnect calls so tests
6
+ // can assert not just that a fresh observer was built, but that the old one
7
+ // was torn down — guards against silent leaks where a stale observer keeps
8
+ // firing callbacks against a detached sentinel.
6
9
  class MockIntersectionObserver {
10
+ static reset() {
11
+ MockIntersectionObserver.instances.length = 0;
12
+ }
7
13
  constructor(callback, options) {
14
+ this.disconnected = false;
8
15
  this.elements = [];
9
16
  this.callback = callback;
10
17
  this.options = options;
18
+ MockIntersectionObserver.instances.push(this);
11
19
  }
12
20
  observe(element) {
13
21
  this.elements.push(element);
@@ -16,6 +24,7 @@ class MockIntersectionObserver {
16
24
  this.elements = this.elements.filter((e) => e !== element);
17
25
  }
18
26
  disconnect() {
27
+ this.disconnected = true;
19
28
  this.elements = [];
20
29
  }
21
30
  // Helper to trigger intersection
@@ -32,6 +41,7 @@ class MockIntersectionObserver {
32
41
  this.callback(entries, this);
33
42
  }
34
43
  }
44
+ MockIntersectionObserver.instances = [];
35
45
  global.IntersectionObserver = MockIntersectionObserver;
36
46
  describe("ObserverManager", () => {
37
47
  let mockContext;
@@ -40,7 +50,9 @@ describe("ObserverManager", () => {
40
50
  let mockLogger;
41
51
  let mockConsole;
42
52
  beforeEach(() => {
53
+ jest.useFakeTimers();
43
54
  document.body.innerHTML = "";
55
+ MockIntersectionObserver.reset();
44
56
  mockSend = jest.fn();
45
57
  mockConsole = {
46
58
  debug: jest.fn(),
@@ -54,9 +66,13 @@ describe("ObserverManager", () => {
54
66
  });
55
67
  });
56
68
  afterEach(() => {
69
+ // Teardown BEFORE swapping back to real timers so any pending fake
70
+ // setTimeout IDs inside ObserverManager are cleared against the fake
71
+ // timer backend they were scheduled on.
57
72
  if (manager) {
58
73
  manager.teardown();
59
74
  }
75
+ jest.useRealTimers();
60
76
  });
61
77
  describe("setupInfiniteScrollObserver", () => {
62
78
  it("does nothing if wrapper element is null", () => {
@@ -93,7 +109,7 @@ describe("ObserverManager", () => {
93
109
  manager.setupInfiniteScrollObserver();
94
110
  expect(mockConsole.debug).toHaveBeenCalledWith(expect.any(String), "Observer set up successfully");
95
111
  });
96
- it("disconnects previous observer before setting up new one", () => {
112
+ it("reuses the existing observer when the sentinel is unchanged", () => {
97
113
  document.body.innerHTML = `
98
114
  <div id="wrapper">
99
115
  <div id="scroll-sentinel"></div>
@@ -106,9 +122,137 @@ describe("ObserverManager", () => {
106
122
  manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
107
123
  manager.setupInfiniteScrollObserver();
108
124
  manager.setupInfiniteScrollObserver();
109
- // Should have logged setup twice (once per call)
125
+ // Same sentinel node → only one setup; subsequent calls are no-ops.
126
+ const setupCalls = mockConsole.debug.mock.calls.filter((call) => call[1] === "Observer set up successfully");
127
+ expect(setupCalls.length).toBe(1);
128
+ });
129
+ it("releases the load_more throttle if the server never responds", () => {
130
+ // Build fresh wrapper + sentinel via DOM APIs to avoid the XSS-reminder
131
+ // hook in tests that scans innerHTML assignments.
132
+ document.body.replaceChildren();
133
+ const wrapper = document.createElement("div");
134
+ wrapper.id = "wrapper";
135
+ const sentinel = document.createElement("div");
136
+ sentinel.id = "scroll-sentinel";
137
+ wrapper.appendChild(sentinel);
138
+ document.body.appendChild(wrapper);
139
+ mockContext = {
140
+ getWrapperElement: () => document.getElementById("wrapper"),
141
+ send: mockSend,
142
+ };
143
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
144
+ manager.setupInfiniteScrollObserver();
145
+ // First intersection → send load_more, arm the 30s safety timeout.
146
+ MockIntersectionObserver.instances[0].triggerIntersection(true);
147
+ expect(mockSend).toHaveBeenCalledTimes(1);
148
+ expect(mockSend).toHaveBeenCalledWith({ action: "load_more" });
149
+ // While "pending" is true, subsequent intersections must be ignored.
150
+ MockIntersectionObserver.instances[0].triggerIntersection(true);
151
+ expect(mockSend).toHaveBeenCalledTimes(1);
152
+ // Server never responds. Advance past the 30s safety net.
153
+ jest.advanceTimersByTime(30001);
154
+ // A warning must be logged and a fresh observer allocated so the
155
+ // next intersection can re-fire. MockIntersectionObserver.instances
156
+ // should now have a second entry.
157
+ expect(mockConsole.warn).toHaveBeenCalledWith(expect.any(String), expect.stringMatching(/load_more response not received/));
158
+ expect(MockIntersectionObserver.instances.length).toBeGreaterThanOrEqual(2);
159
+ // The next intersection re-arms the throttle and sends again.
160
+ const latest = MockIntersectionObserver.instances[MockIntersectionObserver.instances.length - 1];
161
+ latest.triggerIntersection(true);
162
+ expect(mockSend).toHaveBeenCalledTimes(2);
163
+ });
164
+ it("clears the load_more throttle when the sentinel disappears", () => {
165
+ // Regression test for HasMore flip-flop scenario:
166
+ // 1. Sentinel visible → load_more sent, throttle armed.
167
+ // 2. Server flips HasMore to false → sentinel removed from DOM.
168
+ // 3. Server flips HasMore back to true → sentinel reappears.
169
+ // 4. Next intersection must re-trigger load_more (not be silently
170
+ // dropped waiting on the 30s safety timer).
171
+ document.body.replaceChildren();
172
+ const wrapper = document.createElement("div");
173
+ wrapper.id = "wrapper";
174
+ const sentinel1 = document.createElement("div");
175
+ sentinel1.id = "scroll-sentinel";
176
+ wrapper.appendChild(sentinel1);
177
+ document.body.appendChild(wrapper);
178
+ mockContext = {
179
+ getWrapperElement: () => document.getElementById("wrapper"),
180
+ send: mockSend,
181
+ };
182
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
183
+ manager.setupInfiniteScrollObserver();
184
+ // Step 1: arm the throttle by triggering intersection.
185
+ MockIntersectionObserver.instances[0].triggerIntersection(true);
186
+ expect(mockSend).toHaveBeenCalledTimes(1);
187
+ // Step 2: sentinel removed (HasMore flipped false).
188
+ sentinel1.remove();
189
+ manager.setupInfiniteScrollObserver();
190
+ // No observer should be active at this point.
191
+ expect(MockIntersectionObserver.instances[0].disconnected).toBe(true);
192
+ // Step 3: sentinel reappears.
193
+ const sentinel2 = document.createElement("div");
194
+ sentinel2.id = "scroll-sentinel";
195
+ wrapper.appendChild(sentinel2);
196
+ manager.setupInfiniteScrollObserver();
197
+ // Step 4: next intersection must fire — throttle must be clear.
198
+ const latest = MockIntersectionObserver.instances[MockIntersectionObserver.instances.length - 1];
199
+ latest.triggerIntersection(true);
200
+ expect(mockSend).toHaveBeenCalledTimes(2);
201
+ });
202
+ it("clears the load_more safety timeout when lvt:updated fires", () => {
203
+ document.body.replaceChildren();
204
+ const wrapper = document.createElement("div");
205
+ wrapper.id = "wrapper";
206
+ const sentinel = document.createElement("div");
207
+ sentinel.id = "scroll-sentinel";
208
+ wrapper.appendChild(sentinel);
209
+ document.body.appendChild(wrapper);
210
+ mockContext = {
211
+ getWrapperElement: () => document.getElementById("wrapper"),
212
+ send: mockSend,
213
+ };
214
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
215
+ manager.setupInfiniteScrollObserver();
216
+ MockIntersectionObserver.instances[0].triggerIntersection(true);
217
+ expect(mockSend).toHaveBeenCalledTimes(1);
218
+ // Simulate the server's lvt:updated event for load_more.
219
+ wrapper.dispatchEvent(new CustomEvent("lvt:updated", { detail: { action: "load_more" } }));
220
+ // Advance well past the 30s safety window — no warning should fire
221
+ // because the timeout was cleared on the legitimate response.
222
+ jest.advanceTimersByTime(60000);
223
+ expect(mockConsole.warn).not.toHaveBeenCalledWith(expect.any(String), expect.stringMatching(/load_more response not received/));
224
+ });
225
+ it("rebuilds the observer when the sentinel node identity changes", () => {
226
+ // Build fresh wrapper + sentinel via DOM APIs to avoid the XSS-reminder
227
+ // hook in tests that scans innerHTML assignments.
228
+ document.body.replaceChildren();
229
+ const wrapper = document.createElement("div");
230
+ wrapper.id = "wrapper";
231
+ const sentinel1 = document.createElement("div");
232
+ sentinel1.id = "scroll-sentinel";
233
+ wrapper.appendChild(sentinel1);
234
+ document.body.appendChild(wrapper);
235
+ mockContext = {
236
+ getWrapperElement: () => document.getElementById("wrapper"),
237
+ send: mockSend,
238
+ };
239
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
240
+ manager.setupInfiniteScrollObserver();
241
+ // Replace sentinel with a fresh node (simulates morphdom recreating
242
+ // the element on a structural transition).
243
+ sentinel1.remove();
244
+ const sentinel2 = document.createElement("div");
245
+ sentinel2.id = "scroll-sentinel";
246
+ wrapper.appendChild(sentinel2);
247
+ manager.setupInfiniteScrollObserver();
110
248
  const setupCalls = mockConsole.debug.mock.calls.filter((call) => call[1] === "Observer set up successfully");
111
249
  expect(setupCalls.length).toBe(2);
250
+ // The old observer MUST be disconnected before the new one is created —
251
+ // otherwise it keeps firing callbacks against the detached sentinel and
252
+ // leaks memory until GC collects a chain that the observer itself holds.
253
+ expect(MockIntersectionObserver.instances.length).toBe(2);
254
+ expect(MockIntersectionObserver.instances[0].disconnected).toBe(true);
255
+ expect(MockIntersectionObserver.instances[1].disconnected).toBe(false);
112
256
  });
113
257
  });
114
258
  describe("setupInfiniteScrollMutationObserver", () => {
@@ -160,8 +304,12 @@ describe("ObserverManager", () => {
160
304
  manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
161
305
  manager.setupInfiniteScrollObserver();
162
306
  manager.setupInfiniteScrollMutationObserver();
163
- // Should not throw
164
307
  expect(() => manager.teardown()).not.toThrow();
308
+ // IntersectionObserver instance created by setupInfiniteScrollObserver
309
+ // must be disconnected — verifies teardown actually cleans up, not just
310
+ // that it doesn't throw.
311
+ expect(MockIntersectionObserver.instances.length).toBe(1);
312
+ expect(MockIntersectionObserver.instances[0].disconnected).toBe(true);
165
313
  });
166
314
  it("is safe to call when no observers are set up", () => {
167
315
  mockContext = {
@@ -1 +1 @@
1
- {"version":3,"file":"observer-manager.test.js","sourceRoot":"","sources":["../../tests/observer-manager.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observer-manager.test.js","sourceRoot":"","sources":["../../tests/observer-manager.test.ts"],"names":[],"mappings":"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"}