|
19 | 19 |
|
20 | 20 | const PasteBox = require("../pastebox"); |
21 | 21 |
|
22 | | -const mockActivity = { |
23 | | - stage: { |
24 | | - addChild: jest.fn(), |
25 | | - }, |
26 | | - refreshCanvas: jest.fn(), |
27 | | -}; |
28 | | - |
29 | | -const mockDocById = jest.fn(); |
30 | | -global.docById = mockDocById; |
31 | | - |
32 | | -const mockCreatejs = { |
33 | | - Container: jest.fn(() => ({ |
34 | | - addChild: jest.fn(), |
35 | | - getBounds: jest.fn(() => ({ |
36 | | - x: 0, |
37 | | - y: 0, |
38 | | - width: 100, |
39 | | - height: 50, |
40 | | - })), |
41 | | - on: jest.fn(), |
42 | | - })), |
43 | | - Shape: jest.fn(() => ({ |
44 | | - graphics: { |
45 | | - beginFill: jest.fn().mockReturnThis(), |
46 | | - drawRect: jest.fn().mockReturnThis(), |
47 | | - }, |
48 | | - })), |
49 | | - Bitmap: jest.fn(), |
50 | | -}; |
51 | | -global.createjs = mockCreatejs; |
52 | | - |
53 | | -global.base64Encode = jest.fn((data) => data); |
54 | | - |
55 | | -describe("PasteBox Class", () => { |
56 | | - let pasteBox; |
57 | | - |
58 | | - beforeEach(() => { |
59 | | - jest.clearAllMocks(); |
60 | | - pasteBox = new PasteBox(mockActivity); |
| 22 | +describe("PasteBox", () => { |
| 23 | + |
| 24 | + const _Image = global.Image; |
| 25 | + const _window = global.window; |
| 26 | + const _createjs = global.createjs; |
| 27 | + const _docById = global.docById; |
| 28 | + const _base64Encode = global.base64Encode; |
| 29 | + |
| 30 | + afterAll(() => { |
| 31 | + global.Image = _Image; |
| 32 | + global.window = _window; |
| 33 | + global.createjs = _createjs; |
| 34 | + global.docById = _docById; |
| 35 | + global.base64Encode = _base64Encode; |
61 | 36 | }); |
62 | 37 |
|
63 | | - it("should initialize with the correct default values", () => { |
64 | | - expect(pasteBox.activity).toBe(mockActivity); |
65 | | - expect(pasteBox._container).toBe(null); |
66 | | - expect(pasteBox.save).toBe(null); |
67 | | - expect(pasteBox.close).toBe(null); |
68 | | - expect(pasteBox._scale).toBe(1); |
69 | | - }); |
| 38 | + describe("constructor / hide / show / getPos", () => { |
| 39 | + let pasteBox, mockActivity, mockDocById; |
| 40 | + |
| 41 | + beforeEach(() => { |
| 42 | + mockActivity = { |
| 43 | + stage: { addChild: jest.fn() }, |
| 44 | + refreshCanvas: jest.fn(), |
| 45 | + pasted: jest.fn(), |
| 46 | + }; |
| 47 | + mockDocById = jest.fn(); |
| 48 | + global.docById = mockDocById; |
| 49 | + global.base64Encode = jest.fn((x) => x); |
| 50 | + global.window = { btoa: jest.fn((x) => x) }; |
| 51 | + |
| 52 | + pasteBox = new PasteBox(mockActivity); |
| 53 | + }); |
70 | 54 |
|
71 | | - it("should hide the container and clear the paste element", () => { |
72 | | - pasteBox._container = { visible: true }; |
73 | | - mockDocById.mockReturnValue({ |
74 | | - value: "", |
75 | | - style: { visibility: "visible" }, |
| 55 | + it("should initialize with the correct default values", () => { |
| 56 | + expect(pasteBox.activity).toBe(mockActivity); |
| 57 | + expect(pasteBox._container).toBeNull(); |
| 58 | + expect(pasteBox.save).toBeNull(); |
| 59 | + expect(pasteBox.close).toBeNull(); |
| 60 | + expect(pasteBox._scale).toBe(1); |
76 | 61 | }); |
77 | 62 |
|
78 | | - pasteBox.hide(); |
| 63 | + it("should hide the container and clear the paste element", () => { |
| 64 | + pasteBox._container = { visible: true }; |
| 65 | + mockDocById.mockReturnValue({ |
| 66 | + value: "foo", |
| 67 | + style: { visibility: "visible" }, |
| 68 | + }); |
79 | 69 |
|
80 | | - expect(pasteBox._container.visible).toBe(false); |
81 | | - expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
82 | | - expect(mockDocById).toHaveBeenCalledWith("paste"); |
83 | | - expect(mockDocById("paste").value).toBe(""); |
84 | | - expect(mockDocById("paste").style.visibility).toBe("hidden"); |
85 | | - }); |
| 70 | + pasteBox.hide(); |
86 | 71 |
|
87 | | - it("should create a container and add it to the stage", () => { |
88 | | - pasteBox.createBox(2, 100, 200); |
| 72 | + expect(pasteBox._container.visible).toBe(false); |
| 73 | + expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
| 74 | + expect(mockDocById).toHaveBeenCalledWith("paste"); |
| 75 | + expect(mockDocById("paste").value).toBe(""); |
| 76 | + expect(mockDocById("paste").style.visibility).toBe("hidden"); |
| 77 | + }); |
89 | 78 |
|
90 | | - expect(pasteBox._scale).toBe(2); |
91 | | - expect(mockCreatejs.Container).toHaveBeenCalled(); |
92 | | - expect(mockActivity.stage.addChild).toHaveBeenCalledWith(pasteBox._container); |
93 | | - expect(pasteBox._container.x).toBe(100); |
94 | | - expect(pasteBox._container.y).toBe(200); |
95 | | - }); |
| 79 | + it("should make the container visible and show the paste element", () => { |
| 80 | + pasteBox._container = { visible: false }; |
| 81 | + mockDocById.mockReturnValue({ style: { visibility: "hidden" } }); |
96 | 82 |
|
97 | | - it("should make the container visible and show the paste element", () => { |
98 | | - pasteBox._container = { visible: false }; |
99 | | - mockDocById.mockReturnValue({ style: { visibility: "hidden" } }); |
| 83 | + pasteBox.show(); |
100 | 84 |
|
101 | | - pasteBox.show(); |
| 85 | + expect(pasteBox._container.visible).toBe(true); |
| 86 | + expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
| 87 | + expect(mockDocById).toHaveBeenCalledWith("paste"); |
| 88 | + expect(mockDocById("paste").style.visibility).toBe("visible"); |
| 89 | + }); |
102 | 90 |
|
103 | | - expect(pasteBox._container.visible).toBe(true); |
104 | | - expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
105 | | - expect(mockDocById).toHaveBeenCalledWith("paste"); |
106 | | - expect(mockDocById("paste").style.visibility).toBe("visible"); |
| 91 | + it("should return the position of the container", () => { |
| 92 | + pasteBox._container = { x: 12, y: 34 }; |
| 93 | + expect(pasteBox.getPos()).toEqual([12, 34]); |
| 94 | + }); |
107 | 95 | }); |
108 | 96 |
|
109 | | - it("should return the position of the container", () => { |
110 | | - pasteBox._container = { x: 150, y: 250 }; |
111 | | - const position = pasteBox.getPos(); |
| 97 | + describe("createBox()", () => { |
| 98 | + let pasteBox, mockActivity; |
| 99 | + |
| 100 | + beforeEach(() => { |
| 101 | + mockActivity = { |
| 102 | + stage: { addChild: jest.fn() }, |
| 103 | + refreshCanvas: jest.fn(), |
| 104 | + pasted: jest.fn(), |
| 105 | + }; |
| 106 | + global.base64Encode = jest.fn((x) => x); |
| 107 | + global.window = { btoa: jest.fn((x) => x) }; |
| 108 | + pasteBox = new PasteBox(mockActivity); |
| 109 | + }); |
| 110 | + |
| 111 | + it("should create a container and add it to the stage", () => { |
| 112 | + const mockContainer = { addChild: jest.fn(), x: 0, y: 0, visible: false }; |
| 113 | + global.createjs = { |
| 114 | + Container: jest.fn(() => mockContainer), |
| 115 | + Bitmap: jest.fn(), |
| 116 | + Shape: jest.fn(), |
| 117 | + }; |
| 118 | + |
| 119 | + jest.spyOn(pasteBox, "_makeBoxBitmap"); |
| 120 | + |
| 121 | + pasteBox.createBox(2, 10, 20); |
| 122 | + |
| 123 | + expect(pasteBox._scale).toBe(2); |
| 124 | + expect(global.createjs.Container).toHaveBeenCalled(); |
| 125 | + expect(mockActivity.stage.addChild).toHaveBeenCalledWith(mockContainer); |
| 126 | + expect(mockContainer.x).toBe(10); |
| 127 | + expect(mockContainer.y).toBe(20); |
| 128 | + expect(pasteBox._makeBoxBitmap).toHaveBeenCalledWith( |
| 129 | + expect.any(String), |
| 130 | + "box", |
| 131 | + expect.any(Function), |
| 132 | + null |
| 133 | + ); |
| 134 | + }); |
112 | 135 |
|
113 | | - expect(position).toEqual([150, 250]); |
| 136 | + it("should create a bitmap from SVG data and call the callback", () => { |
| 137 | + const mockContainer = { |
| 138 | + addChild: jest.fn(), |
| 139 | + x: 0, |
| 140 | + y: 0, |
| 141 | + visible: false, |
| 142 | + getBounds: jest.fn(() => ({ x: 0, y: 0, width: 300, height: 55 })), |
| 143 | + on: jest.fn(), |
| 144 | + hitArea: null, |
| 145 | + }; |
| 146 | + |
| 147 | + const mockBitmap = { type: "BITMAP" }; |
| 148 | + |
| 149 | + global.createjs = { |
| 150 | + Container: jest.fn(() => mockContainer), |
| 151 | + Bitmap: jest.fn(() => mockBitmap), |
| 152 | + Shape: jest.fn(() => ({ |
| 153 | + graphics: { |
| 154 | + beginFill: jest.fn().mockReturnThis(), |
| 155 | + drawRect: jest.fn().mockReturnThis(), |
| 156 | + }, |
| 157 | + })), |
| 158 | + }; |
| 159 | + |
| 160 | + const img = { onload: null, src: "" }; |
| 161 | + global.Image = jest.fn(() => img); |
| 162 | + |
| 163 | + pasteBox = new PasteBox(mockActivity); |
| 164 | + pasteBox.createBox(1, 0, 0); |
| 165 | + |
| 166 | + expect(img.onload).toBeInstanceOf(Function); |
| 167 | + img.onload(); |
| 168 | + |
| 169 | + expect(mockContainer.addChild).toHaveBeenCalledWith(mockBitmap); |
| 170 | + expect(mockContainer.visible).toBe(true); |
| 171 | + expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
| 172 | + }); |
114 | 173 | }); |
115 | 174 |
|
116 | | - it("should set up the click handler for the container", () => { |
117 | | - const mockBounds = { x: 0, y: 0, width: 100, height: 50 }; |
118 | | - pasteBox._container = { |
119 | | - getBounds: jest.fn().mockReturnValue(mockBounds), |
120 | | - hitArea: null, |
121 | | - on: jest.fn(), |
122 | | - }; |
| 175 | + describe("_loadClearContainerHandler click‐handler", () => { |
| 176 | + let pasteBox, mockActivity, handler; |
| 177 | + |
| 178 | + beforeEach(() => { |
| 179 | + mockActivity = { pasted: jest.fn(), refreshCanvas: jest.fn() }; |
| 180 | + global.docById = jest.fn().mockReturnValue({ |
| 181 | + value: "", |
| 182 | + style: { visibility: "visible" }, |
| 183 | + }); |
| 184 | + |
| 185 | + global.createjs = { |
| 186 | + Shape: jest.fn(() => ({ |
| 187 | + graphics: { |
| 188 | + beginFill: jest.fn().mockReturnThis(), |
| 189 | + drawRect: jest.fn().mockReturnThis(), |
| 190 | + }, |
| 191 | + })), |
| 192 | + }; |
| 193 | + |
| 194 | + pasteBox = new PasteBox(mockActivity); |
| 195 | + pasteBox._scale = 1; |
| 196 | + pasteBox._container = { |
| 197 | + getBounds: jest.fn(() => ({ x: 0, y: 0, width: 300, height: 55 })), |
| 198 | + on: jest.fn((evt, cb) => { handler = cb; }), |
| 199 | + hitArea: null, |
| 200 | + x: 200, |
| 201 | + y: 0, |
| 202 | + visible: true, |
| 203 | + }; |
| 204 | + |
| 205 | + pasteBox._loadClearContainerHandler(); |
| 206 | + }); |
123 | 207 |
|
124 | | - pasteBox._loadClearContainerHandler(); |
| 208 | + it("should set up the click handler for the container", () => { |
| 209 | + expect(pasteBox._container.on).toHaveBeenCalledWith("click", expect.any(Function)); |
| 210 | + }); |
125 | 211 |
|
126 | | - expect(mockCreatejs.Shape).toHaveBeenCalled(); |
127 | | - expect(pasteBox._container.getBounds).toHaveBeenCalled(); |
128 | | - expect(pasteBox._container.on).toHaveBeenCalledWith("click", expect.any(Function)); |
129 | | - }); |
| 212 | + it("calls pasted() + hide() when clicking in paste area", () => { |
| 213 | + handler({ stageX: 410, stageY: 25 }); |
| 214 | + expect(mockActivity.pasted).toHaveBeenCalled(); |
| 215 | + expect(pasteBox._container.visible).toBe(false); |
| 216 | + expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
| 217 | + expect(global.docById).toHaveBeenCalledWith("paste"); |
| 218 | + }); |
130 | 219 |
|
131 | | - it("should create a bitmap from SVG data and call the callback", () => { |
132 | | - const mockCallback = jest.fn(); |
133 | | - const mockImg = { onload: null }; |
134 | | - jest.spyOn(global, "Image").mockImplementation(() => mockImg); |
| 220 | + it("only calls hide() when clicking in close area", () => { |
| 221 | + handler({ stageX: 460, stageY: 10 }); |
| 222 | + expect(mockActivity.pasted).not.toHaveBeenCalled(); |
| 223 | + expect(pasteBox._container.visible).toBe(false); |
| 224 | + expect(mockActivity.refreshCanvas).toHaveBeenCalled(); |
| 225 | + expect(global.docById).toHaveBeenCalledWith("paste"); |
| 226 | + }); |
| 227 | + |
| 228 | + it("does nothing when clicking outside both areas", () => { |
| 229 | + handler({ stageX: 300, stageY: 60 }); |
| 230 | + expect(mockActivity.pasted).not.toHaveBeenCalled(); |
| 231 | + expect(mockActivity.refreshCanvas).not.toHaveBeenCalled(); |
| 232 | + expect(pasteBox._container.visible).toBe(true); |
| 233 | + }); |
135 | 234 |
|
136 | | - pasteBox._makeBoxBitmap("data", "box", mockCallback, null); |
| 235 | + it("debounces rapid clicks in paste area", () => { |
| 236 | + jest.useFakeTimers(); |
137 | 237 |
|
138 | | - mockImg.onload(); |
| 238 | + handler({ stageX: 410, stageY: 25 }); |
| 239 | + handler({ stageX: 410, stageY: 25 }); |
| 240 | + jest.advanceTimersByTime(500); |
| 241 | + handler({ stageX: 410, stageY: 25 }); |
139 | 242 |
|
140 | | - expect(global.base64Encode).toHaveBeenCalledWith("data"); |
141 | | - expect(mockCreatejs.Bitmap).toHaveBeenCalled(); |
142 | | - expect(mockCallback).toHaveBeenCalled(); |
| 243 | + expect(mockActivity.pasted).toHaveBeenCalledTimes(2); |
| 244 | + jest.useRealTimers(); |
| 245 | + }); |
143 | 246 | }); |
144 | 247 | }); |
0 commit comments