fix(csp): fix some of the csp tests (#211)
This commit is contained in:
parent
b70eebc4b2
commit
4824a25cc6
101
src/frames.ts
101
src/frames.ts
|
|
@ -25,6 +25,7 @@ import { ClickOptions, MultiClickOptions, PointerActionOptions, SelectOption } f
|
||||||
import { TimeoutError } from './Errors';
|
import { TimeoutError } from './Errors';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import { Page } from './page';
|
import { Page } from './page';
|
||||||
|
import { ConsoleMessage } from './console';
|
||||||
|
|
||||||
const readFileAsync = helper.promisify(fs.readFile);
|
const readFileAsync = helper.promisify(fs.readFile);
|
||||||
|
|
||||||
|
|
@ -193,28 +194,21 @@ export class Frame {
|
||||||
content = null,
|
content = null,
|
||||||
type = ''
|
type = ''
|
||||||
} = options;
|
} = options;
|
||||||
if (url !== null) {
|
if (!url && !path && !content)
|
||||||
try {
|
throw new Error('Provide an object with a `url`, `path` or `content` property');
|
||||||
const context = await this._mainContext();
|
|
||||||
|
const context = await this._mainContext();
|
||||||
|
return this._raceWithCSPError(async () => {
|
||||||
|
if (url !== null)
|
||||||
return (await context.evaluateHandle(addScriptUrl, url, type)).asElement();
|
return (await context.evaluateHandle(addScriptUrl, url, type)).asElement();
|
||||||
} catch (error) {
|
if (path !== null) {
|
||||||
throw new Error(`Loading script from ${url} failed`);
|
let contents = await readFileAsync(path, 'utf8');
|
||||||
|
contents += '//# sourceURL=' + path.replace(/\n/g, '');
|
||||||
|
return (await context.evaluateHandle(addScriptContent, contents, type)).asElement();
|
||||||
}
|
}
|
||||||
}
|
if (content !== null)
|
||||||
|
return (await context.evaluateHandle(addScriptContent, content, 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');
|
|
||||||
|
|
||||||
async function addScriptUrl(url: string, type: string): Promise<HTMLElement> {
|
async function addScriptUrl(url: string, type: string): Promise<HTMLElement> {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
|
|
@ -249,29 +243,24 @@ export class Frame {
|
||||||
path = null,
|
path = null,
|
||||||
content = null
|
content = null
|
||||||
} = options;
|
} = options;
|
||||||
if (url !== null) {
|
if (!url && !path && !content)
|
||||||
try {
|
throw new Error('Provide an object with a `url`, `path` or `content` property');
|
||||||
const context = await this._mainContext();
|
|
||||||
|
const context = await this._mainContext();
|
||||||
|
return this._raceWithCSPError(async () => {
|
||||||
|
if (url !== null)
|
||||||
return (await context.evaluateHandle(addStyleUrl, url)).asElement();
|
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 (content !== null)
|
||||||
if (path !== null) {
|
return (await context.evaluateHandle(addStyleContent, content)).asElement();
|
||||||
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');
|
|
||||||
|
|
||||||
async function addStyleUrl(url: string): Promise<HTMLElement> {
|
async function addStyleUrl(url: string): Promise<HTMLElement> {
|
||||||
const link = document.createElement('link');
|
const link = document.createElement('link');
|
||||||
link.rel = 'stylesheet';
|
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) {
|
async click(selector: string | types.Selector, options?: ClickOptions) {
|
||||||
const domWorld = await this._utilityDOMWorld();
|
const domWorld = await this._utilityDOMWorld();
|
||||||
const handle = await domWorld.$(types.clearSelector(selector));
|
const handle = await domWorld.$(types.clearSelector(selector));
|
||||||
|
|
|
||||||
|
|
@ -709,7 +709,7 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = 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}) => {
|
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);
|
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.goto(server.EMPTY_PAGE);
|
||||||
await page.addScriptTag({ path: path.join(__dirname, 'assets/injectedfile.js') });
|
await page.addScriptTag({ path: path.join(__dirname, 'assets/injectedfile.js') });
|
||||||
const result = await page.evaluate(() => __injectedError.stack);
|
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);
|
expect(await page.evaluate(() => __injected)).toBe(35);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @see https://github.com/GoogleChrome/puppeteer/issues/4840
|
// Firefox fires onload for blocked script before it issues the CSP console error.
|
||||||
xit('should throw when added with content to the CSP page', async({page, server}) => {
|
it.skip(FFOX)('should throw when added with content to the CSP page', async({page, server}) => {
|
||||||
await page.goto(server.PREFIX + '/csp.html');
|
await page.goto(server.PREFIX + '/csp.html');
|
||||||
let error = null;
|
let error = null;
|
||||||
await page.addScriptTag({ content: 'window.__injected = 35;' }).catch(e => error = e);
|
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) {
|
} catch (e) {
|
||||||
error = 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}) => {
|
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)');
|
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.goto(server.EMPTY_PAGE);
|
||||||
await page.addStyleTag({ path: path.join(__dirname, 'assets/injectedstyle.css') });
|
await page.addStyleTag({ path: path.join(__dirname, 'assets/injectedstyle.css') });
|
||||||
const styleHandle = await page.$('style');
|
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)');
|
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');
|
await page.goto(server.PREFIX + '/csp.html');
|
||||||
let error = null;
|
let error = null;
|
||||||
await page.addStyleTag({ content: 'body { background-color: green; }' }).catch(e => error = e);
|
await page.addStyleTag({ content: 'body { background-color: green; }' }).catch(e => error = e);
|
||||||
expect(error).toBeTruthy();
|
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');
|
await page.goto(server.PREFIX + '/csp.html');
|
||||||
let error = null;
|
let error = null;
|
||||||
await page.addStyleTag({ url: server.CROSS_PROCESS_PREFIX + '/injectedstyle.css' }).catch(e => error = e);
|
await page.addStyleTag({ url: server.CROSS_PROCESS_PREFIX + '/injectedstyle.css' }).catch(e => error = e);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue