11/**
22 * Unit tests for injection-bridge.js
3- * Focused on the context invalidation fix and core message forwarding
3+ * Validates bridge message handling, input validation, and context lifecycle
44 */
55
66import {
@@ -39,34 +39,105 @@ describe('InjectionBridge', () => {
3939 window . dispatchEvent ( event ) ;
4040 }
4141
42- // --- Core forwarding ---
42+ // --- set-speed verb ---
4343
44- it ( 'storage-update forwards to chrome.storage.sync.set ' , ( ) => {
44+ it ( 'set-speed writes clamped lastSpeed to chrome.storage' , ( ) => {
4545 let setData = null ;
4646 chrome . storage . sync . set = ( data ) => {
4747 setData = data ;
4848 } ;
4949
5050 bridge = setupMessageBridge ( ) ;
51- postPageMessage ( 'storage-update ' , { lastSpeed : 2.5 } ) ;
51+ postPageMessage ( 'set-speed ' , { speed : 2.5 } ) ;
5252
53- expect ( setData ) . toBeDefined ( ) ;
54- expect ( setData . lastSpeed ) . toBe ( 2.5 ) ;
53+ expect ( setData ) . toEqual ( { lastSpeed : 2.5 } ) ;
5554 } ) ;
5655
57- it ( 'runtime-message filters out VSC_STATE_UPDATE' , ( ) => {
58- let sendCalled = false ;
59- chrome . runtime . sendMessage = ( ) => {
60- sendCalled = true ;
56+ it ( 'set-speed clamps speed to minimum (0.07)' , ( ) => {
57+ let setData = null ;
58+ chrome . storage . sync . set = ( data ) => {
59+ setData = data ;
60+ } ;
61+
62+ bridge = setupMessageBridge ( ) ;
63+ postPageMessage ( 'set-speed' , { speed : 0.01 } ) ;
64+
65+ expect ( setData ) . toEqual ( { lastSpeed : 0.07 } ) ;
66+ } ) ;
67+
68+ it ( 'set-speed clamps speed to maximum (16)' , ( ) => {
69+ let setData = null ;
70+ chrome . storage . sync . set = ( data ) => {
71+ setData = data ;
72+ } ;
73+
74+ bridge = setupMessageBridge ( ) ;
75+ postPageMessage ( 'set-speed' , { speed : 100 } ) ;
76+
77+ expect ( setData ) . toEqual ( { lastSpeed : 16 } ) ;
78+ } ) ;
79+
80+ it ( 'set-speed requires a numeric value' , ( ) => {
81+ let setCalled = false ;
82+ chrome . storage . sync . set = ( ) => {
83+ setCalled = true ;
84+ } ;
85+
86+ bridge = setupMessageBridge ( ) ;
87+ postPageMessage ( 'set-speed' , { speed : 'fast' } ) ;
88+
89+ expect ( setCalled ) . toBe ( false ) ;
90+ } ) ;
91+
92+ it ( 'set-speed requires a finite value' , ( ) => {
93+ let setCalled = false ;
94+ chrome . storage . sync . set = ( ) => {
95+ setCalled = true ;
96+ } ;
97+
98+ bridge = setupMessageBridge ( ) ;
99+ postPageMessage ( 'set-speed' , { speed : NaN } ) ;
100+ expect ( setCalled ) . toBe ( false ) ;
101+
102+ postPageMessage ( 'set-speed' , { speed : Infinity } ) ;
103+ expect ( setCalled ) . toBe ( false ) ;
104+ } ) ;
105+
106+ it ( 'set-speed requires data to be present' , ( ) => {
107+ let setCalled = false ;
108+ chrome . storage . sync . set = ( ) => {
109+ setCalled = true ;
61110 } ;
62111
63112 bridge = setupMessageBridge ( ) ;
64- postPageMessage ( 'runtime-message ' , { type : 'VSC_STATE_UPDATE' } ) ;
113+ postPageMessage ( 'set-speed ' , null ) ;
65114
115+ expect ( setCalled ) . toBe ( false ) ;
116+ } ) ;
117+
118+ // --- Only set-speed is accepted from page context ---
119+
120+ it ( 'only accepts the set-speed action' , ( ) => {
121+ let setCalled = false ;
122+ let sendCalled = false ;
123+ let getCalled = false ;
124+ chrome . storage . sync . set = ( ) => { setCalled = true ; } ;
125+ chrome . storage . sync . get = ( ) => { getCalled = true ; } ;
126+ chrome . runtime . sendMessage = ( ) => { sendCalled = true ; } ;
127+
128+ bridge = setupMessageBridge ( ) ;
129+
130+ postPageMessage ( 'storage-update' , { lastSpeed : 2.5 } ) ;
131+ postPageMessage ( 'runtime-message' , { type : 'EXTENSION_TOGGLE' , enabled : false } ) ;
132+ postPageMessage ( 'get-storage' , { } ) ;
133+ postPageMessage ( 'something-else' , { payload : 'data' } ) ;
134+
135+ expect ( setCalled ) . toBe ( false ) ;
66136 expect ( sendCalled ) . toBe ( false ) ;
137+ expect ( getCalled ) . toBe ( false ) ;
67138 } ) ;
68139
69- // --- Context invalidation (the actual fix) ---
140+ // --- Context invalidation ---
70141
71142 it ( 'Extension context invalidated removes the message listener' , ( ) => {
72143 chrome . storage . sync . set = ( ) => {
@@ -76,15 +147,15 @@ describe('InjectionBridge', () => {
76147 bridge = setupMessageBridge ( ) ;
77148
78149 // First message triggers invalidation — listener should self-remove
79- postPageMessage ( 'storage-update ' , { lastSpeed : 2.0 } ) ;
150+ postPageMessage ( 'set-speed ' , { speed : 2.0 } ) ;
80151
81152 // Replace with a tracking mock — if listener was removed, this won't fire
82153 let calledAfter = false ;
83154 chrome . storage . sync . set = ( ) => {
84155 calledAfter = true ;
85156 } ;
86157
87- postPageMessage ( 'storage-update ' , { lastSpeed : 3.0 } ) ;
158+ postPageMessage ( 'set-speed ' , { speed : 3.0 } ) ;
88159
89160 expect ( calledAfter ) . toBe ( false ) ;
90161 } ) ;
@@ -100,12 +171,48 @@ describe('InjectionBridge', () => {
100171
101172 bridge = setupMessageBridge ( ) ;
102173
103- postPageMessage ( 'storage-update ' , { lastSpeed : 2.0 } ) ;
104- postPageMessage ( 'storage-update ' , { lastSpeed : 3.0 } ) ;
174+ postPageMessage ( 'set-speed ' , { speed : 2.0 } ) ;
175+ postPageMessage ( 'set-speed ' , { speed : 3.0 } ) ;
105176
106177 expect ( callCount ) . toBe ( 2 ) ;
107178 } ) ;
108179
180+ // --- Message source filtering ---
181+
182+ it ( 'requires vsc-page source prefix' , ( ) => {
183+ let setCalled = false ;
184+ chrome . storage . sync . set = ( ) => {
185+ setCalled = true ;
186+ } ;
187+
188+ bridge = setupMessageBridge ( ) ;
189+
190+ const event = new MessageEvent ( 'message' , {
191+ data : { source : 'other' , action : 'set-speed' , data : { speed : 2.0 } } ,
192+ } ) ;
193+ Object . defineProperty ( event , 'source' , { value : window } ) ;
194+ window . dispatchEvent ( event ) ;
195+
196+ expect ( setCalled ) . toBe ( false ) ;
197+ } ) ;
198+
199+ it ( 'only processes messages from vsc-page, not vsc-content' , ( ) => {
200+ let setCalled = false ;
201+ chrome . storage . sync . set = ( ) => {
202+ setCalled = true ;
203+ } ;
204+
205+ bridge = setupMessageBridge ( ) ;
206+
207+ const event = new MessageEvent ( 'message' , {
208+ data : { source : 'vsc-content' , action : 'set-speed' , data : { speed : 2.0 } } ,
209+ } ) ;
210+ Object . defineProperty ( event , 'source' , { value : window } ) ;
211+ window . dispatchEvent ( event ) ;
212+
213+ expect ( setCalled ) . toBe ( false ) ;
214+ } ) ;
215+
109216 // --- sendCommand API ---
110217
111218 it ( 'sendCommand dispatches VSC_MESSAGE CustomEvent to page context' , ( ) => {
0 commit comments