aboutsummaryrefslogtreecommitdiffstats
path: root/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts')
-rw-r--r--packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts51
1 files changed, 36 insertions, 15 deletions
diff --git a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts b/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts
index 2f295e6..71ac2a1 100644
--- a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts
+++ b/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts
@@ -60,7 +60,7 @@ const invalidAction = {
60 60
61describe('createSophieRenderer', () => { 61describe('createSophieRenderer', () => {
62 it('registers a shared store patch listener', () => { 62 it('registers a shared store patch listener', () => {
63 createSophieRenderer(); 63 createSophieRenderer(false);
64 expect(ipcRenderer.on).toHaveBeenCalledWith( 64 expect(ipcRenderer.on).toHaveBeenCalledWith(
65 MainToRendererIpcMessage.SharedStorePatch, 65 MainToRendererIpcMessage.SharedStorePatch,
66 expect.anything(), 66 expect.anything(),
@@ -77,26 +77,21 @@ describe('SophieRendererImpl', () => {
77 }; 77 };
78 78
79 beforeEach(() => { 79 beforeEach(() => {
80 sut = createSophieRenderer(); 80 sut = createSophieRenderer(false);
81 onSharedStorePatch = mocked(ipcRenderer.on).mock.calls.find(([channel]) => { 81 onSharedStorePatch = mocked(ipcRenderer.on).mock.calls.find(([channel]) => {
82 return channel === MainToRendererIpcMessage.SharedStorePatch; 82 return channel === MainToRendererIpcMessage.SharedStorePatch;
83 })?.[1]!; 83 })?.[1]!;
84 }); 84 });
85 85
86 describe('onSharedStoreChange', () => { 86 describe('onSharedStoreChange', () => {
87 it('requests a snapshot from the service', async () => { 87 it('requests a snapshot from the main process', async () => {
88 mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); 88 mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot);
89 await sut.onSharedStoreChange(listener); 89 await sut.onSharedStoreChange(listener);
90 expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot); 90 expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot);
91 });
92
93 it('passes the snapshot to the listener', async () => {
94 mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot);
95 await sut.onSharedStoreChange(listener);
96 expect(listener.onSnapshot).toBeCalledWith(snapshot); 91 expect(listener.onSnapshot).toBeCalledWith(snapshot);
97 }); 92 });
98 93
99 it('catches service errors without exposing them', async () => { 94 it('catches IPC errors without exposing them', async () => {
100 mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t')); 95 mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t'));
101 await expect(sut.onSharedStoreChange(listener)).rejects.not.toHaveProperty( 96 await expect(sut.onSharedStoreChange(listener)).rejects.not.toHaveProperty(
102 'message', 97 'message',
@@ -125,7 +120,7 @@ describe('SophieRendererImpl', () => {
125 }); 120 });
126 121
127 describe('when no listener is registered', () => { 122 describe('when no listener is registered', () => {
128 it('discards the received patch', () => { 123 it('discards the received patch without any error', () => {
129 onSharedStorePatch(event, patch); 124 onSharedStorePatch(event, patch);
130 }); 125 });
131 }); 126 });
@@ -136,8 +131,10 @@ describe('SophieRendererImpl', () => {
136 }); 131 });
137 } 132 }
138 133
139 function itDoesNotPassPatchesToTheListener() { 134 function itDoesNotPassPatchesToTheListener(
140 it('does not pass patches to the listener', () => { 135 name: string = 'does not pass patches to the listener',
136 ) {
137 it(name, () => {
141 onSharedStorePatch(event, patch); 138 onSharedStorePatch(event, patch);
142 expect(listener.onPatch).toBeCalledTimes(0); 139 expect(listener.onPatch).toBeCalledTimes(0);
143 }); 140 });
@@ -161,18 +158,18 @@ describe('SophieRendererImpl', () => {
161 158
162 itRefusesToRegisterAnotherListener(); 159 itRefusesToRegisterAnotherListener();
163 160
164 describe('that later threw an error', () => { 161 describe('after the listener threw in onPatch', () => {
165 beforeEach(() => { 162 beforeEach(() => {
166 mocked(listener.onPatch).mockImplementation(() => { throw new Error(); }); 163 mocked(listener.onPatch).mockImplementation(() => { throw new Error(); });
167 onSharedStorePatch(event, patch); 164 onSharedStorePatch(event, patch);
168 listener.onPatch.mockRestore(); 165 listener.onPatch.mockRestore();
169 }); 166 });
170 167
171 itDoesNotPassPatchesToTheListener(); 168 itDoesNotPassPatchesToTheListener('does not pass on patches any more');
172 }); 169 });
173 }); 170 });
174 171
175 describe('when a listener failed to register due to service error', () => { 172 describe('when a listener failed to register due to IPC error', () => {
176 beforeEach(async () => { 173 beforeEach(async () => {
177 mocked(ipcRenderer.invoke).mockRejectedValue(new Error()); 174 mocked(ipcRenderer.invoke).mockRejectedValue(new Error());
178 try { 175 try {
@@ -217,4 +214,28 @@ describe('SophieRendererImpl', () => {
217 214
218 itDoesNotPassPatchesToTheListener(); 215 itDoesNotPassPatchesToTheListener();
219 }); 216 });
217
218 describe('when it is allowed to replace listeners', () => {
219 const snapshot2 = {
220 shouldUseDarkColors: false,
221 }
222 const listener2 = {
223 onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => { }),
224 onPatch: jest.fn((_patch: IJsonPatch) => { }),
225 };
226
227 it('should fetch a second snapshot', async () => {
228 mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot2);
229 await sut.onSharedStoreChange(listener2);
230 expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot);
231 expect(listener2.onSnapshot).toBeCalledWith(snapshot2);
232 });
233
234 it('should pass the second snapshot to the new listener', async () => {
235 mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot2);
236 await sut.onSharedStoreChange(listener2);
237 onSharedStorePatch(event, patch);
238 expect(listener2.onPatch).toBeCalledWith(patch);
239 });
240 });
220}); 241});