Skip to content

Commit 3a45e92

Browse files
author
Shane Osbourne
committed
updating specs
1 parent 66d8fe2 commit 3a45e92

File tree

8 files changed

+256
-123
lines changed

8 files changed

+256
-123
lines changed

packages/messaging/lib/messaging.types.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ interface UnstableWebkit {
1010
interface Window {
1111
webkit: UnstableWebkit
1212
__playwright_01: {
13+
mockResponses: Record<string, import("../index.js").MessageResponse>,
14+
subscriptionEvents: import("../index.js").SubscriptionEvent[],
1315
mocks: {
1416
outgoing: UnstableMockCall[],
15-
incoming: any,
1617
}
1718
}
1819
}

packages/messaging/lib/test-utils.mjs

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
*/
55
export function mockWebkit(params) {
66
window.__playwright_01 = {
7+
mockResponses: {},
8+
subscriptionEvents: [],
79
mocks: {
8-
outgoing: [],
9-
incoming: []
10+
outgoing: []
1011
}
1112
}
1213

@@ -15,16 +16,27 @@ export function mockWebkit(params) {
1516
const call = {
1617
payload: payload
1718
}
18-
console.log(JSON.stringify(call));
1919
window.__playwright_01.mocks.outgoing.push(JSON.parse(JSON.stringify(call)))
2020
}
2121

2222
window.webkit = {
2323
messageHandlers: {
2424
[params.messagingContext.context]: {
25-
26-
postMessage: (payload) => {
27-
recordOutgoing(payload)
25+
/**
26+
* @param {import("../../messaging/index.js").RequestMessage} msg
27+
* @return {Promise<string>}
28+
*/
29+
postMessage: async (msg) => {
30+
recordOutgoing(msg)
31+
if ('id' in msg) {
32+
if (msg.method in window.__playwright_01.mockResponses) {
33+
return JSON.stringify(window.__playwright_01.mockResponses[msg.method])
34+
} else {
35+
console.warn('response not found for ' + msg.method)
36+
throw new Error('response not found for ' + msg.method);
37+
}
38+
}
39+
return undefined;
2840
}
2941
}
3042
}
@@ -37,9 +49,10 @@ export function mockWebkit(params) {
3749
*/
3850
export function mockWindows(params) {
3951
window.__playwright_01 = {
52+
mockResponses: {},
53+
subscriptionEvents: [],
4054
mocks: {
41-
outgoing: [],
42-
incoming: []
55+
outgoing: []
4356
}
4457
}
4558
const listeners = []
@@ -51,24 +64,25 @@ export function mockWindows(params) {
5164
}
5265
window.__playwright_01.mocks.outgoing.push(JSON.parse(JSON.stringify(call)))
5366
}
54-
55-
// function respond (name, request, response) {
56-
// const call = [name, request, response]
57-
// // @ts-expect-error
58-
// window.__playwright_01.mocks.incoming.push(JSON.parse(JSON.stringify(call)))
59-
// setTimeout(() => {
60-
// for (const listener of listeners) {
61-
// listener({
62-
// origin: window.origin,
63-
// data: {
64-
// Feature: params.feature,
65-
// Name: name + 'Response',
66-
// Data: response
67-
// }
68-
// })
69-
// }
70-
// }, 0)
71-
// }
67+
/**
68+
* @param {import("../../messaging/index.js").RequestMessage} msg
69+
* @param response
70+
*/
71+
function respond (msg, response) {
72+
setTimeout(() => {
73+
for (const listener of listeners) {
74+
listener({
75+
origin: window.origin,
76+
data: {
77+
result: response,
78+
context: msg.context,
79+
featureName: msg.featureName,
80+
id: msg.id,
81+
},
82+
})
83+
}
84+
}, 0)
85+
}
7286

7387
function isOutgoing (message) {
7488
if (typeof message.method === 'string' &&
@@ -93,13 +107,40 @@ export function mockWindows(params) {
93107
window.chrome = {
94108
// @ts-ignore
95109
webview: {
110+
/**
111+
* @param {import("../../messaging/lib/windows.js").WindowsNotification | import("../../messaging/lib/windows.js").WindowsRequestMessage} input
112+
*/
96113
postMessage (input) {
97-
if (isOutgoing(input)) {
98-
recordOutgoing(input, undefined)
114+
/** @type {import("../../messaging/index.js").NotificationMessage | import("../../messaging/index.js").RequestMessage} */
115+
let msg;
116+
if ('Id' in input) {
117+
msg = {
118+
id: input.Id,
119+
context: input.Feature,
120+
featureName: input.SubFeatureName,
121+
params: input.Data,
122+
method: input.Name
123+
}
124+
} else {
125+
msg = {
126+
context: input.Feature,
127+
featureName: input.SubFeatureName,
128+
params: input.Data,
129+
method: input.Name
130+
}
131+
}
132+
if (isOutgoing(msg)) {
133+
recordOutgoing(msg, undefined)
134+
if ('id' in msg) {
135+
if (msg.method in window.__playwright_01.mockResponses) {
136+
respond(msg, window.__playwright_01.mockResponses[msg.method]);
137+
} else {
138+
throw new Error('response not found for ' + msg.method);
139+
}
140+
}
99141
} else if (isSubscriptionEvent(input)) {
100142
setTimeout(() => {
101143
for (const listener of listeners) {
102-
console.log('listener');
103144
listener({
104145
origin: window.origin,
105146
data: input
@@ -130,16 +171,15 @@ export function mockWindows(params) {
130171
*/
131172
export function waitForCallCount(params) {
132173
const outgoing = window.__playwright_01.mocks.outgoing
133-
// console.log(JSON.stringify(outgoing, null, 2));
134174
const filtered = outgoing.filter(({ payload }) => params.method === payload.method)
135175
return filtered.length === params.count
136176
}
137177

138178
/**
139-
* Just access to outgoing
179+
* Just access to readOutgoingMessages
140180
* @return {any}
141181
*/
142-
export function outgoing() {
182+
export function readOutgoingMessages() {
143183
return window.__playwright_01.mocks.outgoing
144184
}
145185

@@ -182,6 +222,6 @@ export class TestPlatform {
182222
* @param {"apple" | "windows"} params.name
183223
*/
184224
constructor (params) {
185-
this.name = params.name
225+
this.name = params.name;
186226
}
187227
}

packages/messaging/lib/webkit.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export class WebkitMessagingTransport {
8585
* @internal
8686
*/
8787
wkSend(handler, data = {}) {
88+
// console.log('WU?', handler in this.globals.window.webkit.messageHandlers);
8889
if (!(handler in this.globals.window.webkit.messageHandlers)) {
8990
throw new MissingHandler(`Missing webkit handler: '${handler}'`, handler)
9091
}
@@ -155,7 +156,7 @@ export class WebkitMessagingTransport {
155156
* @param {import("../index.js").RequestMessage} msg
156157
*/
157158
// eslint-disable-next-line @typescript-eslint/no-unused-vars
158-
request(msg, _opts) {
159+
async request(msg, _opts) {
159160
return this.wkSendAndWait(msg.context, msg)
160161
}
161162
/**
@@ -358,15 +359,15 @@ export class WebkitMessagingConfig {
358359
*/
359360
this.webkitMessageHandlerNames = params.webkitMessageHandlerNames
360361
/**
361-
* A string provided by native platforms to be sent with future outgoing
362+
* A string provided by native platforms to be sent with future readOutgoingMessages
362363
* messages
363364
*/
364365
this.secret = params.secret
365366
}
366367
}
367368

368369
/**
369-
* This is the additional payload that gets appended to outgoing messages.
370+
* This is the additional payload that gets appended to readOutgoingMessages messages.
370371
* It's used in the Swift side to encrypt the response that comes back
371372
*/
372373
export class SecureMessagingParams {

packages/messaging/lib/windows.js

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
* [[include:packages/messaging/lib/examples/windows.example.js]]```
1212
*
1313
*/
14-
15-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1614
import { MessagingTransport, NotificationMessage, RequestMessage } from '../index.js'
1715

1816
/**
@@ -39,15 +37,9 @@ export class WindowsMessagingTransport {
3937
// @ts-ignore
4038
// eslint-disable-next-line @typescript-eslint/no-unused-vars
4139
notify(msg) {
42-
43-
console.log('🙏 windows transport, sending a notification', JSON.stringify(msg, null, 2))
44-
const raw = {};
45-
raw.Name = msg.method;
46-
raw.Feature = msg.context;
47-
raw.SubFeatureName = msg.featureName;
48-
raw.Data = JSON.parse(JSON.stringify(raw.params || {}));
49-
50-
this.config.methods.postMessage(raw)
40+
// console.log('🙏 windows transport, sending a notification', JSON.stringify(msg, null, 2))
41+
const notification = WindowsNotification.fromNotification(msg);
42+
this.config.methods.postMessage(notification)
5143
}
5244
/**
5345
* @param {import("../index.js").RequestMessage} msg
@@ -57,13 +49,8 @@ export class WindowsMessagingTransport {
5749
// @ts-ignore
5850
// eslint-disable-next-line @typescript-eslint/no-unused-vars
5951
request(msg, opts = {}) {
60-
const raw = {};
61-
raw.Name = msg.method;
62-
raw.Feature = msg.context;
63-
raw.SubFeatureName = msg.featureName;
64-
raw.Data = JSON.parse(JSON.stringify(msg.params || {}))
65-
raw.Id = msg.id;
66-
this.config.methods.postMessage(raw)
52+
const outgoing = WindowsRequestMessage.fromRequest(msg);
53+
this.config.methods.postMessage(outgoing)
6754
const comparator = (eventData) => {
6855
return eventData.featureName === msg.featureName
6956
&& eventData.context === msg.context
@@ -76,13 +63,12 @@ export class WindowsMessagingTransport {
7663
unsubscribe();
7764
if ('result' in value) {
7865
resolve(value['result']);
66+
} else if ('error' in value) {
67+
// @ts-expect-error
68+
reject(new Error(value.error.message || 'unknown error'))
7969
} else {
80-
if ('error' in value) {
81-
reject(new Error(value.error.message || 'unknown error'))
82-
} else {
83-
console.warn('unknown response', value);
84-
reject(new Error('unknown response'))
85-
}
70+
console.warn('unknown response', value);
71+
reject(new Error('unknown response'))
8672
}
8773
})
8874
} catch (e) {
@@ -161,10 +147,85 @@ export class WindowsInteropMethods {
161147
}
162148

163149
/**
150+
* This data type represents a message sent to the Windows
151+
* platform via `window.chrome.webview.postMessage`
152+
*/
153+
export class WindowsNotification {
154+
/**
155+
* @param {object} params
156+
* @param {string} params.Feature
157+
* @param {string} params.SubFeatureName
158+
* @param {string} params.Name
159+
* @param {Record<string, any>} [params.Data]
160+
*/
161+
constructor (params) {
162+
this.Feature = params.Feature
163+
this.SubFeatureName = params.SubFeatureName
164+
this.Name = params.Name
165+
this.Data = params.Data
166+
}
167+
168+
/**
169+
* @param {NotificationMessage} notification
170+
* @returns {WindowsNotification}
171+
*/
172+
static fromNotification(notification) {
173+
/** @type {WindowsNotification} */
174+
const output = {
175+
Data: JSON.parse(JSON.stringify(notification.params || {})),
176+
Feature: notification.context,
177+
SubFeatureName: notification.featureName,
178+
Name: notification.method,
179+
}
180+
return output;
181+
}
182+
}
183+
184+
/**
185+
* This data type represents a message sent to the Windows
186+
* platform via `window.chrome.webview.postMessage` when it
187+
* expects a response
188+
*/
189+
export class WindowsRequestMessage {
190+
/**
191+
* @param {object} params
192+
* @param {string} params.Feature
193+
* @param {string} params.SubFeatureName
194+
* @param {string} params.Name
195+
* @param {Record<string, any>} [params.Data]
196+
* @param {string} [params.Id]
197+
*/
198+
constructor (params) {
199+
this.Feature = params.Feature
200+
this.SubFeatureName = params.SubFeatureName
201+
this.Name = params.Name
202+
this.Data = params.Data
203+
this.Id = params.Id
204+
}
205+
206+
/**
207+
* @param {RequestMessage} msg
208+
* @returns {WindowsRequestMessage}
209+
*/
210+
static fromRequest(msg) {
211+
/** @type {WindowsRequestMessage} */
212+
const output = {
213+
Data: JSON.parse(JSON.stringify(msg.params || {})),
214+
Feature: msg.context,
215+
SubFeatureName: msg.featureName,
216+
Name: msg.method,
217+
Id: msg.id,
218+
}
219+
return output;
220+
}
221+
}
222+
223+
/**
224+
* @typedef {import("../index.js").MessageResponse | import("../index.js").SubscriptionEvent} Incoming
164225
* @param {WindowsMessagingConfig} config
165226
* @param {(eventData: any) => boolean} comparator
166227
* @param {{signal?: AbortSignal}} options
167-
* @param {(value: unknown, unsubscribe: (()=>void)) => void} callback
228+
* @param {(value: Incoming, unsubscribe: (()=>void)) => void} callback
168229
*/
169230
function subscribe(config, comparator, options, callback) {
170231
// if already aborted, reject immediately
@@ -179,8 +240,8 @@ function subscribe(config, comparator, options, callback) {
179240
* @param {MessageEvent} event
180241
*/
181242
const idHandler = (event) => {
182-
console.log(`📩 windows, ${window.location.href}`)
183-
console.log("\t", {origin: event.origin, json: JSON.stringify(event.data, null, 2)});
243+
// console.log(`📩 windows, ${window.location.href}`)
244+
// console.log("\t", {origin: event.origin, json: JSON.stringify(event.data, null, 2)});
184245
if (!event.data) {
185246
console.warn('data absent from message')
186247
return
@@ -197,13 +258,13 @@ function subscribe(config, comparator, options, callback) {
197258
throw new DOMException('Aborted', 'AbortError')
198259
}
199260

200-
console.log('DEBUG: handler setup', { config, comparator })
261+
// console.log('DEBUG: handler setup', { config, comparator })
201262
// eslint-disable-next-line no-undef
202263
config.methods.addEventListener('message', idHandler)
203264
options?.signal?.addEventListener('abort', abortHandler)
204265

205266
teardown = () => {
206-
console.log('DEBUG: handler teardown', { config, comparator })
267+
// console.log('DEBUG: handler teardown', { config, comparator })
207268
// eslint-disable-next-line no-undef
208269
config.methods.removeEventListener('message', idHandler)
209270
options?.signal?.removeEventListener('abort', abortHandler)

0 commit comments

Comments
 (0)