Skip to content

Commit

Permalink
addInitScript in qawolf.register since it happens before pages load, …
Browse files Browse the repository at this point in the history
…so it should not throw any errors with the addInitScript

- Remove the ability to independently call indexPages. Just call qawolf.register and indexPages and ContextEventCollector work. One way to do things
  • Loading branch information
jperl committed Jul 13, 2020
1 parent 5490e85 commit 3e8eae2
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 218 deletions.
46 changes: 6 additions & 40 deletions src/create-code/ContextEventCollector.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import Debug from 'debug';
import { EventEmitter } from 'events';
import { BrowserContext } from 'playwright-core';
import { webScript } from '../web/addScript';
import { loadConfig } from '../config';
import { IndexedPage, isRegistered } from '../utils/context/register';
import { ElementEvent } from '../types';
import { indexPages, IndexedPage } from '../utils';

const debug = Debug('qawolf:ContextEventCollector');

const ignoreError = (error: Error) => {
// when an iframe closes it will throw an error we can ignore
return !!['Session closed', 'Target closed'].find((ignore) =>
error.message.includes(ignore),
);
};

export class ContextEventCollector extends EventEmitter {
readonly _attribute: string;
readonly _context: BrowserContext;
Expand All @@ -23,18 +14,19 @@ export class ContextEventCollector extends EventEmitter {
context: BrowserContext,
): Promise<ContextEventCollector> {
const collector = new ContextEventCollector(context);
await collector._start();
await collector._emitEvents();
return collector;
}

protected constructor(context: BrowserContext) {
super();
this._attribute = loadConfig().attribute;
this._context = context;
}

async _start(): Promise<void> {
await indexPages(this._context);
async _emitEvents(): Promise<void> {
if (!isRegistered(this._context)) {
throw new Error('Use qawolf.register(context) first');
}

await this._context.exposeBinding(
'qawElementEvent',
Expand All @@ -45,31 +37,5 @@ export class ContextEventCollector extends EventEmitter {
this.emit('elementevent', event);
},
);

const script =
'(() => {\n' +
webScript +
`\nnew qawolf.PageEventCollector({ attribute: ${JSON.stringify(
this._attribute,
)} });\n` +
'})();';

try {
await Promise.all(
this._context.pages().map((page) => page.evaluate(script)),
);
} catch (error) {
if (!ignoreError(error)) throw error;

debug('evaluate error we ignored: ' + error.message);
}

try {
await this._context.addInitScript(script);
} catch (error) {
if (!ignoreError(error)) throw error;

debug('addInitScript error we ignored: ' + error.message);
}
}
}
1 change: 0 additions & 1 deletion src/qawolf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export { Config } from './config';
export { create } from './create-code/create';

export {
interceptConsoleLogs,
launch,
register,
repl,
Expand Down
39 changes: 0 additions & 39 deletions src/utils/context/indexPages.ts

This file was deleted.

99 changes: 99 additions & 0 deletions src/utils/context/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import Debug from 'debug';
import { readFileSync } from 'fs';
import { BrowserContext, Page } from 'playwright-core';
import { basename, join } from 'path';
import { loadConfig } from '../../config';
import { Registry } from '../Registry';
import { saveArtifacts } from './saveArtifacts';

const debug = Debug('qawolf:register');

const scriptPath = require.resolve('../../../build/qawolf.web.js');
const webScript = readFileSync(scriptPath, 'utf8');

export type IndexedPage = Page & {
createdIndex: number;
};

export type RegisteredBrowserContext = BrowserContext & {
_qawRegistered: boolean;
};

export const addInitScript = async (context: BrowserContext): Promise<void> => {
const attribute = JSON.stringify(loadConfig().attribute);

const script =
'(() => {\n' +
webScript +
`\nnew qawolf.PageEventCollector({ attribute: ${attribute} });\n` +
'})();';

await context.addInitScript(script);
};

export const isRegistered = (context: BrowserContext): boolean => {
return !!(context as RegisteredBrowserContext)._qawRegistered;
};

export const getArtifactPath = (): string | null => {
let artifactPath = process.env.QAW_ARTIFACT_PATH;
if (!artifactPath) return null;

if (require.main) {
// store artifacts under the name of the main module, if there is one
// ex. /artifacts/search.test.js
artifactPath = join(artifactPath, basename(require.main.filename));
}

// store artifacts under the name of the browser being tested
const browserName = process.env.QAW_BROWSER;
if (browserName && artifactPath) {
artifactPath = join(artifactPath, browserName);
}

return artifactPath;
};

export const indexPages = async (context: BrowserContext): Promise<void> => {
/**
* Set page.createdIndex on pages.
*/
let index = 0;

const pages = context.pages();
if (pages.length > 1) {
throw new Error(
`Cannot index pages when more than 1 exist (${pages.length})`,
);
}

if (pages[0]) {
debug(`index existing page ${index}`);
(pages[0] as IndexedPage).createdIndex = index++;
}

context.on('page', (page: IndexedPage) => {
debug(`index created page ${index}`);
page.createdIndex = index++;
});
};

export const register = async (context: BrowserContext): Promise<void> => {
Registry.instance().setContext(context);

if (isRegistered(context)) return;
(context as RegisteredBrowserContext)._qawRegistered = true;

const promises: Promise<any>[] = [];

promises.push(addInitScript(context));

promises.push(indexPages(context));

const artifactPath = getArtifactPath();
if (artifactPath) {
promises.push(saveArtifacts(context, artifactPath));
}

await Promise.all(promises);
};
7 changes: 4 additions & 3 deletions src/utils/context/waitForPage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BrowserContext } from 'playwright-core';
import { isNull } from 'util';
import { indexPages, IndexedPage } from './indexPages';
import { IndexedPage, isRegistered } from './register';
import { waitFor } from '../waitFor';

export interface WaitForPageOptions {
Expand All @@ -13,8 +13,9 @@ export const waitForPage = async (
index: number,
options: WaitForPageOptions = {},
): Promise<IndexedPage> => {
// index pages if they are not yet
await indexPages(context);
if (!isRegistered(this._context)) {
throw new Error('Use qawolf.register(context) before qawolf.waitForPage');
}

const page = await waitFor(
async () => {
Expand Down
5 changes: 1 addition & 4 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// context utils
export { forEachPage } from './context/forEachPage';
export { indexPages, IndexedPage } from './context/indexPages';
export { register } from './context/register';
export { saveArtifacts, stopVideos } from './context/saveArtifacts';
export { waitForPage, WaitForPageOptions } from './context/waitForPage';

// page utils
export { initEvaluateScript } from './page/initEvaluateScript';
export { interceptConsoleLogs } from './page/interceptConsoleLogs';
export { openScreenshot } from './page/openScreenshot';
export { saveConsoleLogs } from './page/saveConsoleLogs';
export { saveState } from './page/saveState';
Expand All @@ -17,5 +15,4 @@ export { setState } from './page/setState';
export { getLaunchOptions, launch } from './launch';
export { repl } from './repl/repl';
export { Registry } from './Registry';
export { register } from './register';
export { waitFor } from './waitFor';
32 changes: 0 additions & 32 deletions src/utils/page/initEvaluateScript.ts

This file was deleted.

26 changes: 0 additions & 26 deletions src/utils/page/interceptConsoleLogs.ts

This file was deleted.

52 changes: 37 additions & 15 deletions src/utils/page/saveConsoleLogs.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
import Debug from 'debug';
import { appendFileSync } from 'fs';
import { ensureDir } from 'fs-extra';
import { dirname } from 'path';
// import { appendFileSync } from 'fs';
// import { ensureDir } from 'fs-extra';
// import { dirname } from 'path';
import { Page } from 'playwright-core';
import { interceptConsoleLogs } from './interceptConsoleLogs';
// import { QAWolfWeb } from '../../web';
// import { LogCallback } from '../../web/interceptConsoleLogs';

const debug = Debug('qawolf:saveConsoleLogs');
// const debug = Debug('qawolf:saveConsoleLogs');

// let logCallbackId = 0;

// export const interceptConsoleLogs = async (
// page: Page,
// callback: LogCallback,
// ): Promise<void> => {
// // TODO refactor
// // await addScriptToPage(page);

// const callbackName = `interceptLogs${logCallbackId++}`;
// await page.exposeFunction(callbackName, callback);

// await initEvaluateScript(
// page,
// (callbackName: string) => {
// const web: QAWolfWeb = (window as any).qawolf;
// web.interceptConsoleLogs(callbackName);
// },
// callbackName,
// );
// };

export const saveConsoleLogs = async (
page: Page,
savePath: string,
): Promise<void> => {
debug(`save console logs at ${savePath}`);

await ensureDir(dirname(savePath));

const callback = (level: string, message: string): void => {
const line = `${level}: ${message}\n`;
appendFileSync(savePath, line);
};

return interceptConsoleLogs(page, callback);
console.log('page', page, 'savePath', savePath);
// TODO
// debug(`save console logs at ${savePath}`);
// await ensureDir(dirname(savePath));
// const callback = (level: string, message: string): void => {
// const line = `${level}: ${message}\n`;
// appendFileSync(savePath, line);
// };
// return interceptConsoleLogs(page, callback);
};

0 comments on commit 3e8eae2

Please sign in to comment.