Skip to content

Commit 6d94c92

Browse files
authored
feat(rpc): support no-serialization mode, run hook tests (#2925)
Added rpc_json_linux bots to excercise serialization - these do not run hook tests.
1 parent 6674458 commit 6d94c92

File tree

13 files changed

+42
-41
lines changed

13 files changed

+42
-41
lines changed

.github/workflows/tests.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ jobs:
174174
fail-fast: false
175175
matrix:
176176
browser: [chromium, firefox, webkit]
177+
transport: [json, object]
177178
runs-on: ubuntu-18.04
178179
steps:
179180
- uses: actions/checkout@v2
@@ -194,21 +195,19 @@ jobs:
194195
BROWSER: ${{ matrix.browser }}
195196
DEBUG: "*,-pw:wrapped*"
196197
PWCHANNEL: "1"
197-
# Ensure output folder exists just in case it was not created by the test run.
198-
- run: node -e "require('fs').mkdirSync(require('path').join('test', 'output-${{ matrix.browser }}'), {recursive:true})"
199-
if: failure()
198+
PWCHANNELTRANSPORT: ${{ matrix.transport }}
200199
- uses: actions/upload-artifact@v1
201200
if: failure()
202201
with:
203-
name: rpc-${{ matrix.browser }}-linux-output
202+
name: rpc-${{ matrix.transport }}-${{ matrix.browser }}-linux-output
204203
path: test/output-${{ matrix.browser }}
205204
- uses: actions/upload-artifact@v1
206205
if: failure()
207206
with:
208-
name: rpc-${{ matrix.browser }}-linux-testrun.log
207+
name: rpc-${{ matrix.transport }}-${{ matrix.browser }}-linux-testrun.log
209208
path: testrun.log
210209
- uses: actions/upload-artifact@v1
211210
if: failure()
212211
with:
213-
name: rpc-${{ matrix.browser }}-linux-coredumps
212+
name: rpc-${{ matrix.transport }}-${{ matrix.browser }}-linux-coredumps
214213
path: coredumps

src/rpc/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import { Transport } from './transport';
2323
const spawnedProcess = childProcess.fork(path.join(__dirname, 'server'), [], { stdio: 'pipe' });
2424
const transport = new Transport(spawnedProcess.stdin, spawnedProcess.stdout);
2525
const connection = new Connection();
26-
connection.onmessage = message => transport.send(message);
27-
transport.onmessage = message => connection.dispatch(message);
26+
connection.onmessage = message => transport.send(JSON.stringify(message));
27+
transport.onmessage = message => connection.dispatch(JSON.parse(message));
2828

2929
const playwright = await connection.waitForObjectWithKnownName('playwright');
3030
const browser = await playwright.chromium.launch({ headless: false });

src/rpc/client/connection.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Root extends ChannelOwner<Channel, {}> {
4343
export class Connection {
4444
readonly _objects = new Map<string, ChannelOwner>();
4545
private _waitingForObject = new Map<string, any>();
46-
onmessage = (message: string): void => {};
46+
onmessage = (message: object): void => {};
4747
private _lastId = 0;
4848
private _callbacks = new Map<number, { resolve: (a: any) => void, reject: (a: Error) => void }>();
4949
private _rootObject: ChannelOwner;
@@ -62,19 +62,18 @@ export class Connection {
6262
const id = ++this._lastId;
6363
const converted = { id, ...message, params: this._replaceChannelsWithGuids(message.params) };
6464
debug('pw:channel:command')(converted);
65-
this.onmessage(JSON.stringify(converted));
65+
this.onmessage(converted);
6666
return new Promise((resolve, reject) => this._callbacks.set(id, { resolve, reject }));
6767
}
6868

6969
_debugScopeState(): any {
7070
return this._rootObject._debugScopeState();
7171
}
7272

73-
dispatch(message: string) {
74-
const parsedMessage = JSON.parse(message);
75-
const { id, guid, method, params, result, error } = parsedMessage;
73+
dispatch(message: object) {
74+
const { id, guid, method, params, result, error } = message as any;
7675
if (id) {
77-
debug('pw:channel:response')(parsedMessage);
76+
debug('pw:channel:response')(message);
7877
const callback = this._callbacks.get(id)!;
7978
this._callbacks.delete(id);
8079
if (error)
@@ -84,7 +83,7 @@ export class Connection {
8483
return;
8584
}
8685

87-
debug('pw:channel:event')(parsedMessage);
86+
debug('pw:channel:event')(message);
8887
if (method === '__create__') {
8988
this._createRemoteObject(guid, params.type, params.guid, params.initializer);
9089
return;

src/rpc/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import { PlaywrightDispatcher } from './server/playwrightDispatcher';
2121

2222
const dispatcherConnection = new DispatcherConnection();
2323
const transport = new Transport(process.stdout, process.stdin);
24-
transport.onmessage = message => dispatcherConnection.dispatch(message);
25-
dispatcherConnection.onmessage = message => transport.send(message);
24+
transport.onmessage = message => dispatcherConnection.dispatch(JSON.parse(message));
25+
dispatcherConnection.onmessage = message => transport.send(JSON.stringify(message));
2626

2727
const playwright = new Playwright(__dirname, require('../../browsers.json')['browsers']);
2828
new PlaywrightDispatcher(dispatcherConnection.rootDispatcher(), playwright);

src/rpc/server/dispatcher.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ class Root extends Dispatcher<{}, {}> {
113113
export class DispatcherConnection {
114114
readonly _dispatchers = new Map<string, Dispatcher<any, any>>();
115115
private _rootDispatcher: Root;
116-
onmessage = (message: string) => {};
116+
onmessage = (message: object) => {};
117117

118118
async sendMessageToClient(guid: string, method: string, params: any): Promise<any> {
119-
this.onmessage(JSON.stringify({ guid, method, params: this._replaceDispatchersWithGuids(params) }));
119+
this.onmessage({ guid, method, params: this._replaceDispatchersWithGuids(params) });
120120
}
121121

122122
constructor() {
@@ -127,23 +127,22 @@ export class DispatcherConnection {
127127
return this._rootDispatcher;
128128
}
129129

130-
async dispatch(message: string) {
131-
const parsedMessage = JSON.parse(message);
132-
const { id, guid, method, params } = parsedMessage;
130+
async dispatch(message: object) {
131+
const { id, guid, method, params } = message as any;
133132
const dispatcher = this._dispatchers.get(guid);
134133
if (!dispatcher) {
135-
this.onmessage(JSON.stringify({ id, error: serializeError(new Error('Target browser or context has been closed')) }));
134+
this.onmessage({ id, error: serializeError(new Error('Target browser or context has been closed')) });
136135
return;
137136
}
138137
if (method === 'debugScopeState') {
139-
this.onmessage(JSON.stringify({ id, result: this._rootDispatcher._debugScopeState() }));
138+
this.onmessage({ id, result: this._rootDispatcher._debugScopeState() });
140139
return;
141140
}
142141
try {
143142
const result = await (dispatcher as any)[method](this._replaceGuidsWithDispatchers(params));
144-
this.onmessage(JSON.stringify({ id, result: this._replaceDispatchersWithGuids(result) }));
143+
this.onmessage({ id, result: this._replaceDispatchersWithGuids(result) });
145144
} catch (e) {
146-
this.onmessage(JSON.stringify({ id, error: serializeError(e) }));
145+
this.onmessage({ id, error: serializeError(e) });
147146
}
148147
}
149148

src/rpc/transport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class Transport {
2323
private _closed = false;
2424
private _bytesLeft = 0;
2525

26-
onmessage?: (message: any) => void;
26+
onmessage?: (message: string) => void;
2727
onclose?: () => void;
2828

2929
constructor(pipeWrite: NodeJS.WritableStream, pipeRead: NodeJS.ReadableStream) {

test/defaultbrowsercontext.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,9 @@ describe('launchPersistentContext()', function() {
335335
expect(error.message).toContain('can not specify page');
336336
await removeUserDataDir(userDataDir);
337337
});
338-
it.skip(USES_HOOKS)('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, defaultBrowserOptions, server}) => {
338+
it('should have passed URL when launching with ignoreDefaultArgs: true', async ({playwrightPath, browserType, defaultBrowserOptions, server}) => {
339339
const userDataDir = await makeUserDataDir();
340-
const args = browserType._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
340+
const args = require(playwrightPath)[browserType.name()]._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
341341
const options = {
342342
...defaultBrowserOptions,
343343
args: [...args, server.EMPTY_PAGE],
@@ -364,7 +364,7 @@ describe('launchPersistentContext()', function() {
364364
const e = new Error('Dummy');
365365
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } };
366366
const error = await browserType.launchPersistentContext(userDataDir, options).catch(e => e);
367-
expect(error).toBe(e);
367+
expect(error.message).toContain('Dummy');
368368
await removeUserDataDir(userDataDir);
369369
});
370370
it('should fire close event for a persistent context', async(state) => {
@@ -373,5 +373,5 @@ describe('launchPersistentContext()', function() {
373373
context.on('close', () => closed = true);
374374
await close(state);
375375
expect(closed).toBe(true);
376-
});
376+
});
377377
});

test/environments.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,13 @@ class PlaywrightEnvironment {
167167
const dispatcherConnection = new DispatcherConnection();
168168
const connection = new Connection();
169169
dispatcherConnection.onmessage = async message => {
170+
if (process.env.PWCHANNELJSON)
171+
message = JSON.parse(JSON.stringify(message));
170172
setImmediate(() => connection.dispatch(message));
171173
};
172174
connection.onmessage = async message => {
175+
if (process.env.PWCHANNELJSON)
176+
message = JSON.parse(JSON.stringify(message));
173177
const result = await dispatcherConnection.dispatch(message);
174178
await new Promise(f => setImmediate(f));
175179
return result;

test/evaluation.spec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
const utils = require('./utils');
1919
const path = require('path');
20-
const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = utils.testOptions(browserType);
20+
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = utils.testOptions(browserType);
2121

2222
describe('Page.evaluate', function() {
2323
it('should work', async({page, server}) => {
@@ -574,14 +574,14 @@ describe('Frame.evaluate', function() {
574574
else
575575
expect(page._delegate._contextIdToContext.size).toBe(count);
576576
}
577-
it.skip(USES_HOOKS)('should dispose context on navigation', async({page, server}) => {
577+
it.skip(CHANNEL)('should dispose context on navigation', async({page, server}) => {
578578
await page.goto(server.PREFIX + '/frames/one-frame.html');
579579
expect(page.frames().length).toBe(2);
580580
expectContexts(page, 4);
581581
await page.goto(server.EMPTY_PAGE);
582582
expectContexts(page, 2);
583583
});
584-
it.skip(USES_HOOKS)('should dispose context on cross-origin navigation', async({page, server}) => {
584+
it.skip(CHANNEL)('should dispose context on cross-origin navigation', async({page, server}) => {
585585
await page.goto(server.PREFIX + '/frames/one-frame.html');
586586
expect(page.frames().length).toBe(2);
587587
expectContexts(page, 4);

test/launcher.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('Playwright', function() {
6767
const e = new Error('Dummy');
6868
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
6969
const error = await browserType.launch(options).catch(e => e);
70-
expect(error).toBe(e);
70+
expect(error.message).toContain('Dummy');
7171
});
7272
it.skip(USES_HOOKS)('should report launch log', async({browserType, defaultBrowserOptions}) => {
7373
const e = new Error('Dummy');

0 commit comments

Comments
 (0)