@livetemplate/client 0.3.0 → 0.4.1

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 (48) hide show
  1. package/dist/dom/event-delegation.d.ts +1 -0
  2. package/dist/dom/event-delegation.d.ts.map +1 -1
  3. package/dist/dom/event-delegation.js +9 -0
  4. package/dist/dom/event-delegation.js.map +1 -1
  5. package/dist/livetemplate-client.browser.js +4 -4
  6. package/dist/livetemplate-client.browser.js.map +3 -3
  7. package/dist/livetemplate-client.d.ts.map +1 -1
  8. package/dist/livetemplate-client.js +3 -2
  9. package/dist/livetemplate-client.js.map +1 -1
  10. package/dist/tests/directives.test.d.ts +2 -0
  11. package/dist/tests/directives.test.d.ts.map +1 -0
  12. package/dist/tests/directives.test.js +208 -0
  13. package/dist/tests/directives.test.js.map +1 -0
  14. package/dist/tests/event-delegation.test.js +1 -0
  15. package/dist/tests/event-delegation.test.js.map +1 -1
  16. package/dist/tests/loading-indicator.test.d.ts +2 -0
  17. package/dist/tests/loading-indicator.test.d.ts.map +1 -0
  18. package/dist/tests/loading-indicator.test.js +60 -0
  19. package/dist/tests/loading-indicator.test.js.map +1 -0
  20. package/dist/tests/logger.test.d.ts +2 -0
  21. package/dist/tests/logger.test.d.ts.map +1 -0
  22. package/dist/tests/logger.test.js +201 -0
  23. package/dist/tests/logger.test.js.map +1 -0
  24. package/dist/tests/observer-manager.test.d.ts +2 -0
  25. package/dist/tests/observer-manager.test.d.ts.map +1 -0
  26. package/dist/tests/observer-manager.test.js +192 -0
  27. package/dist/tests/observer-manager.test.js.map +1 -0
  28. package/dist/tests/s3-uploader.test.d.ts +2 -0
  29. package/dist/tests/s3-uploader.test.d.ts.map +1 -0
  30. package/dist/tests/s3-uploader.test.js +141 -0
  31. package/dist/tests/s3-uploader.test.js.map +1 -0
  32. package/dist/tests/upload-handler.test.d.ts +2 -0
  33. package/dist/tests/upload-handler.test.d.ts.map +1 -0
  34. package/dist/tests/upload-handler.test.js +365 -0
  35. package/dist/tests/upload-handler.test.js.map +1 -0
  36. package/dist/tests/websocket.test.d.ts +2 -0
  37. package/dist/tests/websocket.test.d.ts.map +1 -0
  38. package/dist/tests/websocket.test.js +379 -0
  39. package/dist/tests/websocket.test.js.map +1 -0
  40. package/dist/transport/websocket.js +1 -1
  41. package/dist/transport/websocket.js.map +1 -1
  42. package/dist/upload/types.d.ts +1 -0
  43. package/dist/upload/types.d.ts.map +1 -1
  44. package/dist/upload/upload-handler.d.ts +11 -0
  45. package/dist/upload/upload-handler.d.ts.map +1 -1
  46. package/dist/upload/upload-handler.js +58 -6
  47. package/dist/upload/upload-handler.js.map +1 -1
  48. package/package.json +2 -1
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const logger_1 = require("../utils/logger");
4
+ describe("Logger", () => {
5
+ let mockConsole;
6
+ beforeEach(() => {
7
+ mockConsole = {
8
+ error: jest.fn(),
9
+ warn: jest.fn(),
10
+ info: jest.fn(),
11
+ debug: jest.fn(),
12
+ log: jest.fn(),
13
+ };
14
+ });
15
+ describe("createLogger", () => {
16
+ it("creates logger with default options", () => {
17
+ const logger = (0, logger_1.createLogger)({ sink: mockConsole });
18
+ expect(logger.getLevel()).toBe("info");
19
+ });
20
+ it("respects custom log level", () => {
21
+ const logger = (0, logger_1.createLogger)({
22
+ level: "debug",
23
+ sink: mockConsole,
24
+ });
25
+ expect(logger.getLevel()).toBe("debug");
26
+ });
27
+ it("accepts scope as string", () => {
28
+ const logger = (0, logger_1.createLogger)({
29
+ scope: "TestScope",
30
+ sink: mockConsole,
31
+ });
32
+ logger.info("test message");
33
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate:TestScope]", "test message");
34
+ });
35
+ it("accepts scope as array", () => {
36
+ const logger = (0, logger_1.createLogger)({
37
+ scope: ["Parent", "Child"],
38
+ sink: mockConsole,
39
+ });
40
+ logger.info("test message");
41
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate:Parent:Child]", "test message");
42
+ });
43
+ });
44
+ describe("log level filtering", () => {
45
+ it("silent level suppresses all logs", () => {
46
+ const logger = (0, logger_1.createLogger)({
47
+ level: "silent",
48
+ sink: mockConsole,
49
+ });
50
+ logger.error("error");
51
+ logger.warn("warn");
52
+ logger.info("info");
53
+ logger.debug("debug");
54
+ expect(mockConsole.error).not.toHaveBeenCalled();
55
+ expect(mockConsole.warn).not.toHaveBeenCalled();
56
+ expect(mockConsole.info).not.toHaveBeenCalled();
57
+ expect(mockConsole.debug).not.toHaveBeenCalled();
58
+ });
59
+ it("error level only shows errors", () => {
60
+ const logger = (0, logger_1.createLogger)({
61
+ level: "error",
62
+ sink: mockConsole,
63
+ });
64
+ logger.error("error");
65
+ logger.warn("warn");
66
+ logger.info("info");
67
+ logger.debug("debug");
68
+ expect(mockConsole.error).toHaveBeenCalledTimes(1);
69
+ expect(mockConsole.warn).not.toHaveBeenCalled();
70
+ expect(mockConsole.info).not.toHaveBeenCalled();
71
+ expect(mockConsole.debug).not.toHaveBeenCalled();
72
+ });
73
+ it("warn level shows errors and warnings", () => {
74
+ const logger = (0, logger_1.createLogger)({
75
+ level: "warn",
76
+ sink: mockConsole,
77
+ });
78
+ logger.error("error");
79
+ logger.warn("warn");
80
+ logger.info("info");
81
+ logger.debug("debug");
82
+ expect(mockConsole.error).toHaveBeenCalledTimes(1);
83
+ expect(mockConsole.warn).toHaveBeenCalledTimes(1);
84
+ expect(mockConsole.info).not.toHaveBeenCalled();
85
+ expect(mockConsole.debug).not.toHaveBeenCalled();
86
+ });
87
+ it("info level shows errors, warnings, and info", () => {
88
+ const logger = (0, logger_1.createLogger)({
89
+ level: "info",
90
+ sink: mockConsole,
91
+ });
92
+ logger.error("error");
93
+ logger.warn("warn");
94
+ logger.info("info");
95
+ logger.debug("debug");
96
+ expect(mockConsole.error).toHaveBeenCalledTimes(1);
97
+ expect(mockConsole.warn).toHaveBeenCalledTimes(1);
98
+ expect(mockConsole.info).toHaveBeenCalledTimes(1);
99
+ expect(mockConsole.debug).not.toHaveBeenCalled();
100
+ });
101
+ it("debug level shows all logs", () => {
102
+ const logger = (0, logger_1.createLogger)({
103
+ level: "debug",
104
+ sink: mockConsole,
105
+ });
106
+ logger.error("error");
107
+ logger.warn("warn");
108
+ logger.info("info");
109
+ logger.debug("debug");
110
+ expect(mockConsole.error).toHaveBeenCalledTimes(1);
111
+ expect(mockConsole.warn).toHaveBeenCalledTimes(1);
112
+ expect(mockConsole.info).toHaveBeenCalledTimes(1);
113
+ expect(mockConsole.debug).toHaveBeenCalledTimes(1);
114
+ });
115
+ });
116
+ describe("setLevel", () => {
117
+ it("changes log level dynamically", () => {
118
+ const logger = (0, logger_1.createLogger)({
119
+ level: "silent",
120
+ sink: mockConsole,
121
+ });
122
+ logger.info("should not appear");
123
+ expect(mockConsole.info).not.toHaveBeenCalled();
124
+ logger.setLevel("info");
125
+ logger.info("should appear");
126
+ expect(mockConsole.info).toHaveBeenCalledTimes(1);
127
+ });
128
+ });
129
+ describe("child", () => {
130
+ it("creates scoped logger that shares state", () => {
131
+ const parent = (0, logger_1.createLogger)({
132
+ level: "info",
133
+ sink: mockConsole,
134
+ });
135
+ const child = parent.child("ChildScope");
136
+ child.info("child message");
137
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate:ChildScope]", "child message");
138
+ });
139
+ it("child logger inherits level changes from parent", () => {
140
+ const parent = (0, logger_1.createLogger)({
141
+ level: "silent",
142
+ sink: mockConsole,
143
+ });
144
+ const child = parent.child("Child");
145
+ child.info("should not appear");
146
+ expect(mockConsole.info).not.toHaveBeenCalled();
147
+ parent.setLevel("info");
148
+ child.info("should appear");
149
+ expect(mockConsole.info).toHaveBeenCalledTimes(1);
150
+ });
151
+ it("supports multiple levels of nesting", () => {
152
+ const root = (0, logger_1.createLogger)({
153
+ scope: "Root",
154
+ sink: mockConsole,
155
+ });
156
+ const level1 = root.child("Level1");
157
+ const level2 = level1.child("Level2");
158
+ level2.info("deep message");
159
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate:Root:Level1:Level2]", "deep message");
160
+ });
161
+ });
162
+ describe("isDebugEnabled", () => {
163
+ it("returns true when level is debug", () => {
164
+ const logger = (0, logger_1.createLogger)({
165
+ level: "debug",
166
+ sink: mockConsole,
167
+ });
168
+ expect(logger.isDebugEnabled()).toBe(true);
169
+ });
170
+ it("returns false when level is info or lower", () => {
171
+ const logger = (0, logger_1.createLogger)({
172
+ level: "info",
173
+ sink: mockConsole,
174
+ });
175
+ expect(logger.isDebugEnabled()).toBe(false);
176
+ });
177
+ });
178
+ describe("prefix formatting", () => {
179
+ it("uses default prefix when no scope provided", () => {
180
+ const logger = (0, logger_1.createLogger)({ sink: mockConsole });
181
+ logger.info("test");
182
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate]", "test");
183
+ });
184
+ it("includes scope in prefix", () => {
185
+ const logger = (0, logger_1.createLogger)({
186
+ scope: "MyScope",
187
+ sink: mockConsole,
188
+ });
189
+ logger.info("test");
190
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate:MyScope]", "test");
191
+ });
192
+ });
193
+ describe("multiple arguments", () => {
194
+ it("passes all arguments to console method", () => {
195
+ const logger = (0, logger_1.createLogger)({ sink: mockConsole });
196
+ logger.info("message", { data: 123 }, [1, 2, 3]);
197
+ expect(mockConsole.info).toHaveBeenCalledWith("[LiveTemplate]", "message", { data: 123 }, [1, 2, 3]);
198
+ });
199
+ });
200
+ });
201
+ //# sourceMappingURL=logger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../tests/logger.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=observer-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-manager.test.d.ts","sourceRoot":"","sources":["../../tests/observer-manager.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const observer_manager_1 = require("../dom/observer-manager");
4
+ const logger_1 = require("../utils/logger");
5
+ // Mock IntersectionObserver
6
+ class MockIntersectionObserver {
7
+ constructor(callback, options) {
8
+ this.elements = [];
9
+ this.callback = callback;
10
+ this.options = options;
11
+ }
12
+ observe(element) {
13
+ this.elements.push(element);
14
+ }
15
+ unobserve(element) {
16
+ this.elements = this.elements.filter((e) => e !== element);
17
+ }
18
+ disconnect() {
19
+ this.elements = [];
20
+ }
21
+ // Helper to trigger intersection
22
+ triggerIntersection(isIntersecting) {
23
+ const entries = this.elements.map((target) => ({
24
+ target,
25
+ isIntersecting,
26
+ boundingClientRect: {},
27
+ intersectionRatio: isIntersecting ? 1 : 0,
28
+ intersectionRect: {},
29
+ rootBounds: null,
30
+ time: Date.now(),
31
+ }));
32
+ this.callback(entries, this);
33
+ }
34
+ }
35
+ global.IntersectionObserver = MockIntersectionObserver;
36
+ describe("ObserverManager", () => {
37
+ let mockContext;
38
+ let mockSend;
39
+ let manager;
40
+ let mockLogger;
41
+ let mockConsole;
42
+ beforeEach(() => {
43
+ document.body.innerHTML = "";
44
+ mockSend = jest.fn();
45
+ mockConsole = {
46
+ debug: jest.fn(),
47
+ info: jest.fn(),
48
+ warn: jest.fn(),
49
+ error: jest.fn(),
50
+ };
51
+ mockLogger = (0, logger_1.createLogger)({
52
+ level: "debug",
53
+ sink: mockConsole,
54
+ });
55
+ });
56
+ afterEach(() => {
57
+ if (manager) {
58
+ manager.teardown();
59
+ }
60
+ });
61
+ describe("setupInfiniteScrollObserver", () => {
62
+ it("does nothing if wrapper element is null", () => {
63
+ mockContext = {
64
+ getWrapperElement: () => null,
65
+ send: mockSend,
66
+ };
67
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
68
+ manager.setupInfiniteScrollObserver();
69
+ // Should not throw and should not call send
70
+ expect(mockSend).not.toHaveBeenCalled();
71
+ });
72
+ it("does nothing if scroll-sentinel element is not found", () => {
73
+ document.body.innerHTML = "<div id='wrapper'></div>";
74
+ mockContext = {
75
+ getWrapperElement: () => document.getElementById("wrapper"),
76
+ send: mockSend,
77
+ };
78
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
79
+ manager.setupInfiniteScrollObserver();
80
+ expect(mockSend).not.toHaveBeenCalled();
81
+ });
82
+ it("sets up IntersectionObserver when sentinel exists", () => {
83
+ document.body.innerHTML = `
84
+ <div id="wrapper">
85
+ <div id="scroll-sentinel"></div>
86
+ </div>
87
+ `;
88
+ mockContext = {
89
+ getWrapperElement: () => document.getElementById("wrapper"),
90
+ send: mockSend,
91
+ };
92
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
93
+ manager.setupInfiniteScrollObserver();
94
+ expect(mockConsole.debug).toHaveBeenCalledWith(expect.any(String), "Observer set up successfully");
95
+ });
96
+ it("disconnects previous observer before setting up new one", () => {
97
+ document.body.innerHTML = `
98
+ <div id="wrapper">
99
+ <div id="scroll-sentinel"></div>
100
+ </div>
101
+ `;
102
+ mockContext = {
103
+ getWrapperElement: () => document.getElementById("wrapper"),
104
+ send: mockSend,
105
+ };
106
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
107
+ manager.setupInfiniteScrollObserver();
108
+ manager.setupInfiniteScrollObserver();
109
+ // Should have logged setup twice (once per call)
110
+ const setupCalls = mockConsole.debug.mock.calls.filter((call) => call[1] === "Observer set up successfully");
111
+ expect(setupCalls.length).toBe(2);
112
+ });
113
+ });
114
+ describe("setupInfiniteScrollMutationObserver", () => {
115
+ it("does nothing if wrapper element is null", () => {
116
+ mockContext = {
117
+ getWrapperElement: () => null,
118
+ send: mockSend,
119
+ };
120
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
121
+ manager.setupInfiniteScrollMutationObserver();
122
+ // Should not log setup message since wrapper is null
123
+ const mutationSetupCalls = mockConsole.debug.mock.calls.filter((call) => call[1] === "MutationObserver set up successfully");
124
+ expect(mutationSetupCalls.length).toBe(0);
125
+ });
126
+ it("sets up MutationObserver when wrapper exists", () => {
127
+ document.body.innerHTML = "<div id='wrapper'></div>";
128
+ mockContext = {
129
+ getWrapperElement: () => document.getElementById("wrapper"),
130
+ send: mockSend,
131
+ };
132
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
133
+ manager.setupInfiniteScrollMutationObserver();
134
+ expect(mockConsole.debug).toHaveBeenCalledWith(expect.any(String), "MutationObserver set up successfully");
135
+ });
136
+ it("disconnects previous mutation observer before setting up new one", () => {
137
+ document.body.innerHTML = "<div id='wrapper'></div>";
138
+ mockContext = {
139
+ getWrapperElement: () => document.getElementById("wrapper"),
140
+ send: mockSend,
141
+ };
142
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
143
+ manager.setupInfiniteScrollMutationObserver();
144
+ manager.setupInfiniteScrollMutationObserver();
145
+ const mutationSetupCalls = mockConsole.debug.mock.calls.filter((call) => call[1] === "MutationObserver set up successfully");
146
+ expect(mutationSetupCalls.length).toBe(2);
147
+ });
148
+ });
149
+ describe("teardown", () => {
150
+ it("disconnects all observers", () => {
151
+ document.body.innerHTML = `
152
+ <div id="wrapper">
153
+ <div id="scroll-sentinel"></div>
154
+ </div>
155
+ `;
156
+ mockContext = {
157
+ getWrapperElement: () => document.getElementById("wrapper"),
158
+ send: mockSend,
159
+ };
160
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
161
+ manager.setupInfiniteScrollObserver();
162
+ manager.setupInfiniteScrollMutationObserver();
163
+ // Should not throw
164
+ expect(() => manager.teardown()).not.toThrow();
165
+ });
166
+ it("is safe to call when no observers are set up", () => {
167
+ mockContext = {
168
+ getWrapperElement: () => null,
169
+ send: mockSend,
170
+ };
171
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
172
+ expect(() => manager.teardown()).not.toThrow();
173
+ });
174
+ it("is safe to call multiple times", () => {
175
+ document.body.innerHTML = `
176
+ <div id="wrapper">
177
+ <div id="scroll-sentinel"></div>
178
+ </div>
179
+ `;
180
+ mockContext = {
181
+ getWrapperElement: () => document.getElementById("wrapper"),
182
+ send: mockSend,
183
+ };
184
+ manager = new observer_manager_1.ObserverManager(mockContext, mockLogger);
185
+ manager.setupInfiniteScrollObserver();
186
+ manager.teardown();
187
+ manager.teardown();
188
+ expect(() => manager.teardown()).not.toThrow();
189
+ });
190
+ });
191
+ });
192
+ //# sourceMappingURL=observer-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-manager.test.js","sourceRoot":"","sources":["../../tests/observer-manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=s3-uploader.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-uploader.test.d.ts","sourceRoot":"","sources":["../../tests/s3-uploader.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const s3_uploader_1 = require("../upload/s3-uploader");
4
+ describe("S3Uploader", () => {
5
+ let uploader;
6
+ let mockXHR;
7
+ let xhrEventHandlers;
8
+ let uploadEventHandlers;
9
+ beforeEach(() => {
10
+ xhrEventHandlers = new Map();
11
+ uploadEventHandlers = new Map();
12
+ mockXHR = {
13
+ open: jest.fn(),
14
+ send: jest.fn(),
15
+ setRequestHeader: jest.fn(),
16
+ abort: jest.fn(),
17
+ upload: {
18
+ addEventListener: jest.fn((event, handler) => {
19
+ uploadEventHandlers.set(event, handler);
20
+ }),
21
+ },
22
+ addEventListener: jest.fn((event, handler) => {
23
+ xhrEventHandlers.set(event, handler);
24
+ }),
25
+ status: 200,
26
+ statusText: "OK",
27
+ };
28
+ global.XMLHttpRequest = jest.fn(() => mockXHR);
29
+ uploader = new s3_uploader_1.S3Uploader();
30
+ });
31
+ const createMockEntry = (overrides = {}) => ({
32
+ id: "test-entry-1",
33
+ file: new File(["test content"], "test.txt", { type: "text/plain" }),
34
+ uploadName: "test-upload",
35
+ progress: 0,
36
+ bytesUploaded: 0,
37
+ valid: true,
38
+ done: false,
39
+ ...overrides,
40
+ });
41
+ const createMockMeta = (overrides = {}) => ({
42
+ uploader: "s3",
43
+ url: "https://s3.example.com/bucket/key?presigned=signature",
44
+ ...overrides,
45
+ });
46
+ describe("upload", () => {
47
+ it("uploads file to presigned URL", async () => {
48
+ const entry = createMockEntry();
49
+ const meta = createMockMeta();
50
+ const uploadPromise = uploader.upload(entry, meta);
51
+ expect(mockXHR.open).toHaveBeenCalledWith("PUT", meta.url);
52
+ expect(mockXHR.send).toHaveBeenCalledWith(entry.file);
53
+ // Simulate successful upload
54
+ mockXHR.status = 200;
55
+ xhrEventHandlers.get("load")();
56
+ await uploadPromise;
57
+ expect(entry.done).toBe(true);
58
+ expect(entry.progress).toBe(100);
59
+ });
60
+ it("sets custom headers", async () => {
61
+ const entry = createMockEntry();
62
+ const meta = createMockMeta({
63
+ headers: {
64
+ "Content-Type": "text/plain",
65
+ "x-amz-acl": "public-read",
66
+ },
67
+ });
68
+ const uploadPromise = uploader.upload(entry, meta);
69
+ expect(mockXHR.setRequestHeader).toHaveBeenCalledWith("Content-Type", "text/plain");
70
+ expect(mockXHR.setRequestHeader).toHaveBeenCalledWith("x-amz-acl", "public-read");
71
+ mockXHR.status = 200;
72
+ xhrEventHandlers.get("load")();
73
+ await uploadPromise;
74
+ });
75
+ it("tracks upload progress", async () => {
76
+ const entry = createMockEntry();
77
+ const meta = createMockMeta();
78
+ const onProgress = jest.fn();
79
+ const uploadPromise = uploader.upload(entry, meta, onProgress);
80
+ // Simulate progress event
81
+ uploadEventHandlers.get("progress")({
82
+ lengthComputable: true,
83
+ loaded: 50,
84
+ total: 100,
85
+ });
86
+ expect(entry.bytesUploaded).toBe(50);
87
+ expect(entry.progress).toBe(50);
88
+ expect(onProgress).toHaveBeenCalledWith(entry);
89
+ // Complete upload
90
+ mockXHR.status = 200;
91
+ xhrEventHandlers.get("load")();
92
+ await uploadPromise;
93
+ });
94
+ it("handles upload failure with status code", async () => {
95
+ const entry = createMockEntry();
96
+ const meta = createMockMeta();
97
+ const uploadPromise = uploader.upload(entry, meta);
98
+ mockXHR.status = 403;
99
+ mockXHR.statusText = "Forbidden";
100
+ xhrEventHandlers.get("load")();
101
+ await expect(uploadPromise).rejects.toThrow("S3 upload failed with status 403: Forbidden");
102
+ expect(entry.error).toBe("S3 upload failed with status 403: Forbidden");
103
+ });
104
+ it("handles network error", async () => {
105
+ const entry = createMockEntry();
106
+ const meta = createMockMeta();
107
+ const uploadPromise = uploader.upload(entry, meta);
108
+ xhrEventHandlers.get("error")();
109
+ await expect(uploadPromise).rejects.toThrow("S3 upload failed: Network error");
110
+ expect(entry.error).toBe("S3 upload failed: Network error");
111
+ });
112
+ it("supports abort/cancellation", async () => {
113
+ const entry = createMockEntry();
114
+ const meta = createMockMeta();
115
+ const uploadPromise = uploader.upload(entry, meta);
116
+ // Abort the upload
117
+ entry.abortController.abort();
118
+ // The abort event should be triggered
119
+ xhrEventHandlers.get("abort")();
120
+ await expect(uploadPromise).rejects.toThrow("S3 upload cancelled");
121
+ expect(mockXHR.abort).toHaveBeenCalled();
122
+ });
123
+ it("does not call progress callback for non-computable progress", async () => {
124
+ const entry = createMockEntry();
125
+ const meta = createMockMeta();
126
+ const onProgress = jest.fn();
127
+ const uploadPromise = uploader.upload(entry, meta, onProgress);
128
+ // Simulate progress event without length
129
+ uploadEventHandlers.get("progress")({
130
+ lengthComputable: false,
131
+ loaded: 50,
132
+ total: 0,
133
+ });
134
+ expect(onProgress).not.toHaveBeenCalled();
135
+ mockXHR.status = 200;
136
+ xhrEventHandlers.get("load")();
137
+ await uploadPromise;
138
+ });
139
+ });
140
+ });
141
+ //# sourceMappingURL=s3-uploader.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-uploader.test.js","sourceRoot":"","sources":["../../tests/s3-uploader.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=upload-handler.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-handler.test.d.ts","sourceRoot":"","sources":["../../tests/upload-handler.test.ts"],"names":[],"mappings":""}