fix(csp): fix some of the csp tests (#211)

This commit is contained in:
Pavel Feldman 2019-12-11 13:51:03 -08:00 committed by GitHub
parent b70eebc4b2
commit 4824a25cc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 49 deletions

View File

@ -25,6 +25,7 @@ import { ClickOptions, MultiClickOptions, PointerActionOptions, SelectOption } f
import { TimeoutError } from './Errors';
import { Events } from './events';
import { Page } from './page';
import { ConsoleMessage } from './console';
const readFileAsync = helper.promisify(fs.readFile);
@ -193,28 +194,21 @@ export class Frame {
content = null,
type = ''
} = options;
if (url !== null) {
try {
const context = await this._mainContext();
if (!url && !path && !content)
throw new Error('Provide an object with a `url`, `path` or `content` property');
const context = await this._mainContext();
return this._raceWithCSPError(async () => {
if (url !== null)
return (await context.evaluateHandle(addScriptUrl, url, type)).asElement();
} catch (error) {
throw new Error(`Loading script from ${url} failed`);
if (path !== null) {
let contents = await readFileAsync(path, 'utf8');
contents += '//# sourceURL=' + path.replace(/\n/g, '');
return (await context.evaluateHandle(addScriptContent, contents, type)).asElement();
}
}
if (path !== null) {
let contents = await readFileAsync(path, 'utf8');
contents += '//# sourceURL=' + path.replace(/\n/g, '');
const context = await this._mainContext();
return (await context.evaluateHandle(addScriptContent, contents, type)).asElement();
}
if (content !== null) {
const context = await this._mainContext();
return (await context.evaluateHandle(addScriptContent, content, type)).asElement();
}
throw new Error('Provide an object with a `url`, `path` or `content` property');
if (content !== null)
return (await context.evaluateHandle(addScriptContent, content, type)).asElement();
});
async function addScriptUrl(url: string, type: string): Promise<HTMLElement> {
const script = document.createElement('script');
@ -249,29 +243,24 @@ export class Frame {
path = null,
content = null
} = options;
if (url !== null) {
try {
const context = await this._mainContext();
if (!url && !path && !content)
throw new Error('Provide an object with a `url`, `path` or `content` property');
const context = await this._mainContext();
return this._raceWithCSPError(async () => {
if (url !== null)
return (await context.evaluateHandle(addStyleUrl, url)).asElement();
} catch (error) {
throw new Error(`Loading style from ${url} failed`);
if (path !== null) {
let contents = await readFileAsync(path, 'utf8');
contents += '/*# sourceURL=' + path.replace(/\n/g, '') + '*/';
return (await context.evaluateHandle(addStyleContent, contents)).asElement();
}
}
if (path !== null) {
let contents = await readFileAsync(path, 'utf8');
contents += '/*# sourceURL=' + path.replace(/\n/g, '') + '*/';
const context = await this._mainContext();
return (await context.evaluateHandle(addStyleContent, contents)).asElement();
}
if (content !== null) {
const context = await this._mainContext();
return (await context.evaluateHandle(addStyleContent, content)).asElement();
}
throw new Error('Provide an object with a `url`, `path` or `content` property');
if (content !== null)
return (await context.evaluateHandle(addStyleContent, content)).asElement();
});
async function addStyleUrl(url: string): Promise<HTMLElement> {
const link = document.createElement('link');
link.rel = 'stylesheet';
@ -299,6 +288,36 @@ export class Frame {
}
}
private async _raceWithCSPError(func: () => Promise<dom.ElementHandle>): Promise<dom.ElementHandle> {
const listeners: RegisteredListener[] = [];
let result: dom.ElementHandle | undefined;
let error: Error | undefined;
let cspMessage: ConsoleMessage | undefined;
const actionPromise = new Promise<dom.ElementHandle>(async (resolve) => {
try {
result = await func();
} catch (e) {
error = e;
}
resolve();
});
const errorPromise = new Promise(resolve => {
listeners.push(helper.addEventListener(this._page, Events.Page.Console, (message: ConsoleMessage) => {
if (message.type() === 'error' && message.text().includes('Content Security Policy')) {
cspMessage = message;
resolve();
}
}));
});
await Promise.race([actionPromise, errorPromise]);
helper.removeEventListeners(listeners);
if (cspMessage)
throw new Error(cspMessage.text());
if (error)
throw error;
return result;
}
async click(selector: string | types.Selector, options?: ClickOptions) {
const domWorld = await this._utilityDOMWorld();
const handle = await domWorld.$(types.clearSelector(selector));

View File

@ -709,7 +709,7 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
} catch (e) {
error = e;
}
expect(error.message).toBe('Loading script from /nonexistfile.js failed');
expect(error).not.toBe(null);
});
it('should work with a path', async({page, server}) => {
@ -719,7 +719,7 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
expect(await page.evaluate(() => __injected)).toBe(42);
});
it.skip(WEBKIT)('should include sourcemap when path is provided', async({page, server}) => {
it('should include sourceURL when path is provided', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.addScriptTag({ path: path.join(__dirname, 'assets/injectedfile.js') });
const result = await page.evaluate(() => __injectedError.stack);
@ -733,8 +733,8 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
expect(await page.evaluate(() => __injected)).toBe(35);
});
// @see https://github.com/GoogleChrome/puppeteer/issues/4840
xit('should throw when added with content to the CSP page', async({page, server}) => {
// Firefox fires onload for blocked script before it issues the CSP console error.
it.skip(FFOX)('should throw when added with content to the CSP page', async({page, server}) => {
await page.goto(server.PREFIX + '/csp.html');
let error = null;
await page.addScriptTag({ content: 'window.__injected = 35;' }).catch(e => error = e);
@ -775,7 +775,7 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
} catch (e) {
error = e;
}
expect(error.message).toBe('Loading style from /nonexistfile.js failed');
expect(error).not.toBe(null);
});
it('should work with a path', async({page, server}) => {
@ -785,7 +785,7 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
expect(await page.evaluate(`window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')`)).toBe('rgb(255, 0, 0)');
});
it('should include sourcemap when path is provided', async({page, server}) => {
it('should include sourceURL when path is provided', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.addStyleTag({ path: path.join(__dirname, 'assets/injectedstyle.css') });
const styleHandle = await page.$('style');
@ -800,14 +800,14 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
expect(await page.evaluate(`window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')`)).toBe('rgb(0, 128, 0)');
});
it.skip(FFOX || WEBKIT)('should throw when added with content to the CSP page', async({page, server}) => {
it('should throw when added with content to the CSP page', async({page, server}) => {
await page.goto(server.PREFIX + '/csp.html');
let error = null;
await page.addStyleTag({ content: 'body { background-color: green; }' }).catch(e => error = e);
expect(error).toBeTruthy();
});
it.skip(WEBKIT)('should throw when added with URL to the CSP page', async({page, server}) => {
it('should throw when added with URL to the CSP page', async({page, server}) => {
await page.goto(server.PREFIX + '/csp.html');
let error = null;
await page.addStyleTag({ url: server.CROSS_PROCESS_PREFIX + '/injectedstyle.css' }).catch(e => error = e);