@@ -14,14 +14,22 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- import { mocked } from "jest-mock" ;
18
- import { Widget , ClientWidgetApi , MatrixWidgetType , IWidgetApiRequest } from "matrix-widget-api" ;
17
+ import { mocked , Mocked } from "jest-mock" ;
18
+ import {
19
+ Widget ,
20
+ ClientWidgetApi ,
21
+ MatrixWidgetType ,
22
+ WidgetApiAction ,
23
+ IWidgetApiRequest ,
24
+ IWidgetApiRequestData ,
25
+ } from "matrix-widget-api" ;
19
26
import { MatrixClient } from "matrix-js-sdk/src/client" ;
20
27
21
28
import { stubClient , setupAsyncStoreWithClient , mkRoom } from "../test-utils" ;
22
29
import { MatrixClientPeg } from "../../src/MatrixClientPeg" ;
23
30
import WidgetStore , { IApp } from "../../src/stores/WidgetStore" ;
24
31
import { WidgetMessagingStore } from "../../src/stores/widgets/WidgetMessagingStore" ;
32
+ import ActiveWidgetStore , { ActiveWidgetStoreEvent } from "../../src/stores/ActiveWidgetStore" ;
25
33
import { ElementWidgetActions } from "../../src/stores/widgets/ElementWidgetActions" ;
26
34
import { VIDEO_CHANNEL_MEMBER , STUCK_DEVICE_TIMEOUT_MS } from "../../src/utils/VideoChannelUtils" ;
27
35
import VideoChannelStore , { VideoChannelEvent } from "../../src/stores/VideoChannelStore" ;
@@ -43,22 +51,19 @@ describe("VideoChannelStore", () => {
43
51
} as IApp ;
44
52
45
53
// Set up mocks to simulate the remote end of the widget API
46
- let messageSent : Promise < void > ;
47
- let messageSendMock : ( ) => void ;
54
+ let sendMock : ( action : WidgetApiAction , data : IWidgetApiRequestData ) => void ;
48
55
let onMock : ( action : string , listener : ( ev : CustomEvent < IWidgetApiRequest > ) => void ) => void ;
49
56
let onceMock : ( action : string , listener : ( ev : CustomEvent < IWidgetApiRequest > ) => void ) => void ;
50
57
let messaging : ClientWidgetApi ;
51
- let cli : MatrixClient ;
58
+ let cli : Mocked < MatrixClient > ;
52
59
beforeEach ( ( ) => {
53
60
stubClient ( ) ;
54
- cli = MatrixClientPeg . get ( ) ;
61
+ cli = mocked ( MatrixClientPeg . get ( ) ) ;
55
62
setupAsyncStoreWithClient ( WidgetMessagingStore . instance , cli ) ;
56
63
setupAsyncStoreWithClient ( store , cli ) ;
57
- mocked ( cli ) . getRoom . mockReturnValue ( mkRoom ( cli , "!1:example.org" ) ) ;
64
+ cli . getRoom . mockReturnValue ( mkRoom ( cli , "!1:example.org" ) ) ;
58
65
59
- let resolveMessageSent : ( ) => void ;
60
- messageSent = new Promise ( resolve => resolveMessageSent = resolve ) ;
61
- messageSendMock = jest . fn ( ) . mockImplementation ( ( ) => resolveMessageSent ( ) ) ;
66
+ sendMock = jest . fn ( ) ;
62
67
onMock = jest . fn ( ) ;
63
68
onceMock = jest . fn ( ) ;
64
69
@@ -69,14 +74,19 @@ describe("VideoChannelStore", () => {
69
74
stop : ( ) => { } ,
70
75
once : onceMock ,
71
76
transport : {
72
- send : messageSendMock ,
77
+ send : sendMock ,
73
78
reply : ( ) => { } ,
74
79
} ,
75
80
} as unknown as ClientWidgetApi ;
76
81
} ) ;
77
82
78
83
afterEach ( ( ) => jest . useRealTimers ( ) ) ;
79
84
85
+ const getRequest = < T extends IWidgetApiRequestData > ( ) : Promise < [ WidgetApiAction , T ] > =>
86
+ new Promise < [ WidgetApiAction , T ] > ( resolve => {
87
+ mocked ( sendMock ) . mockImplementationOnce ( ( action , data ) => resolve ( [ action , data as T ] ) ) ;
88
+ } ) ;
89
+
80
90
const widgetReady = ( ) => {
81
91
// Tell the WidgetStore that the widget is ready
82
92
const [ , ready ] = mocked ( onceMock ) . mock . calls . find ( ( [ action ] ) =>
@@ -87,7 +97,7 @@ describe("VideoChannelStore", () => {
87
97
88
98
const confirmConnect = async ( ) => {
89
99
// Wait for the store to contact the widget API
90
- await messageSent ;
100
+ await getRequest ( ) ;
91
101
// Then, locate the callback that will confirm the join
92
102
const [ , join ] = mocked ( onMock ) . mock . calls . find ( ( [ action ] ) =>
93
103
action === `action:${ ElementWidgetActions . JoinCall } ` ,
@@ -122,8 +132,9 @@ describe("VideoChannelStore", () => {
122
132
expect ( store . roomId ) . toBeFalsy ( ) ;
123
133
expect ( store . connected ) . toEqual ( false ) ;
124
134
135
+ const connectConfirmed = confirmConnect ( ) ;
125
136
const connectPromise = store . connect ( "!1:example.org" , null , null ) ;
126
- await confirmConnect ( ) ;
137
+ await connectConfirmed ;
127
138
await expect ( connectPromise ) . resolves . toBeUndefined ( ) ;
128
139
expect ( store . roomId ) . toEqual ( "!1:example.org" ) ;
129
140
expect ( store . connected ) . toEqual ( true ) ;
@@ -135,7 +146,7 @@ describe("VideoChannelStore", () => {
135
146
{ devices : [ cli . getDeviceId ( ) ] , expires_ts : expect . any ( Number ) } ,
136
147
cli . getUserId ( ) ,
137
148
) ;
138
- mocked ( cli ) . sendStateEvent . mockClear ( ) ;
149
+ cli . sendStateEvent . mockClear ( ) ;
139
150
140
151
// Our devices should be resent within the timeout period to prevent
141
152
// the data from becoming stale
@@ -146,7 +157,7 @@ describe("VideoChannelStore", () => {
146
157
{ devices : [ cli . getDeviceId ( ) ] , expires_ts : expect . any ( Number ) } ,
147
158
cli . getUserId ( ) ,
148
159
) ;
149
- mocked ( cli ) . sendStateEvent . mockClear ( ) ;
160
+ cli . sendStateEvent . mockClear ( ) ;
150
161
151
162
const disconnectPromise = store . disconnect ( ) ;
152
163
await confirmDisconnect ( ) ;
@@ -165,10 +176,11 @@ describe("VideoChannelStore", () => {
165
176
} ) ;
166
177
167
178
it ( "waits for messaging when connecting" , async ( ) => {
179
+ const connectConfirmed = confirmConnect ( ) ;
168
180
const connectPromise = store . connect ( "!1:example.org" , null , null ) ;
169
181
WidgetMessagingStore . instance . storeMessaging ( widget , "!1:example.org" , messaging ) ;
170
182
widgetReady ( ) ;
171
- await confirmConnect ( ) ;
183
+ await connectConfirmed ;
172
184
await expect ( connectPromise ) . resolves . toBeUndefined ( ) ;
173
185
expect ( store . roomId ) . toEqual ( "!1:example.org" ) ;
174
186
expect ( store . connected ) . toEqual ( true ) ;
@@ -184,12 +196,30 @@ describe("VideoChannelStore", () => {
184
196
expect ( store . roomId ) . toBeFalsy ( ) ;
185
197
expect ( store . connected ) . toEqual ( false ) ;
186
198
199
+ const requestPromise = getRequest ( ) ;
187
200
const connectPromise = store . connect ( "!1:example.org" , null , null ) ;
188
201
// Wait for the store to contact the widget API, then stop the messaging
189
- await messageSent ;
202
+ await requestPromise ;
190
203
WidgetMessagingStore . instance . stopMessaging ( widget , "!1:example.org" ) ;
191
204
await expect ( connectPromise ) . rejects . toBeDefined ( ) ;
192
205
expect ( store . roomId ) . toBeFalsy ( ) ;
193
206
expect ( store . connected ) . toEqual ( false ) ;
194
207
} ) ;
208
+
209
+ it ( "switches to spotlight mode when the widget becomes a PiP" , async ( ) => {
210
+ WidgetMessagingStore . instance . storeMessaging ( widget , "!1:example.org" , messaging ) ;
211
+ widgetReady ( ) ;
212
+ confirmConnect ( ) ;
213
+ await store . connect ( "!1:example.org" , null , null ) ;
214
+
215
+ const request = getRequest < IWidgetApiRequestData > ( ) ;
216
+ ActiveWidgetStore . instance . emit ( ActiveWidgetStoreEvent . Undock ) ;
217
+ const [ action , data ] = await request ;
218
+ expect ( action ) . toEqual ( ElementWidgetActions . SpotlightLayout ) ;
219
+ expect ( data ) . toEqual ( { } ) ;
220
+
221
+ store . disconnect ( ) ;
222
+ await confirmDisconnect ( ) ;
223
+ WidgetMessagingStore . instance . stopMessaging ( widget , "!1:example.org" ) ;
224
+ } ) ;
195
225
} ) ;
0 commit comments