puppeteer/test/input.spec.js
Jack Franklin 17cd8703f9
chore: migrate unit tests to Mocha (#5600)
Rather than maintain our own test runner we should instead lean on the community and use Mocha which is very popular and also our test runner of choice in DevTools too.

Note that this commit doesn't remove the TestRunner source as it's still used for other unit tests, but they will be updated in a future PR and then we can remove the TestRunner.

The main bulk of this PR is updating the tests as the old TestRunner passed in contextual data via the `it` function callback whereas Mocha does not, so we introduce some helpers for the tests to make it easier.
2020-04-09 07:56:25 +02:00

268 lines
9.8 KiB
JavaScript

/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const path = require('path');
const expect = require('expect');
const {getTestState,setupTestBrowserHooks,setupTestPageAndContextHooks} = require('./mocha-utils');
const FILE_TO_UPLOAD = path.join(__dirname, '/assets/file-to-upload.txt');
describe('input tests', function() {
setupTestBrowserHooks();
setupTestPageAndContextHooks();
describeFailsFirefox('input', function() {
it('should upload the file', async() => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/fileupload.html');
const filePath = path.relative(process.cwd(), FILE_TO_UPLOAD);
const input = await page.$('input');
await page.evaluate(e => {
window._inputEvents = [];
e.addEventListener('change', ev => window._inputEvents.push(ev.type));
e.addEventListener('input', ev => window._inputEvents.push(ev.type));
}, input);
await input.uploadFile(filePath);
expect(await page.evaluate(e => e.files[0].name, input)).toBe('file-to-upload.txt');
expect(await page.evaluate(() => window._inputEvents)).toEqual(['input', 'change']);
expect(await page.evaluate(e => {
const reader = new FileReader();
const promise = new Promise(fulfill => reader.onload = fulfill);
reader.readAsText(e.files[0]);
return promise.then(() => reader.result);
}, input)).toBe('contents of the file');
});
});
describeFailsFirefox('Page.waitForFileChooser', function() {
it('should work when file input is attached to DOM', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
expect(chooser).toBeTruthy();
});
it('should work when file input is not attached to DOM', async() => {
const { page } = getTestState();
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.evaluate(() => {
const el = document.createElement('input');
el.type = 'file';
el.click();
}),
]);
expect(chooser).toBeTruthy();
});
it('should respect timeout', async() => {
const { page, puppeteer } = getTestState();
let error = null;
await page.waitForFileChooser({timeout: 1}).catch(e => error = e);
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
});
it('should respect default timeout when there is no custom timeout', async() => {
const { page, puppeteer } = getTestState();
page.setDefaultTimeout(1);
let error = null;
await page.waitForFileChooser().catch(e => error = e);
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
});
it('should prioritize exact timeout over default timeout', async() => {
const { page, puppeteer } = getTestState();
page.setDefaultTimeout(0);
let error = null;
await page.waitForFileChooser({timeout: 1}).catch(e => error = e);
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
});
it('should work with no timeout', async() => {
const { page } = getTestState();
const [chooser] = await Promise.all([
page.waitForFileChooser({timeout: 0}),
page.evaluate(() => setTimeout(() => {
const el = document.createElement('input');
el.type = 'file';
el.click();
}, 50))
]);
expect(chooser).toBeTruthy();
});
it('should return the same file chooser when there are many watchdogs simultaneously', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [fileChooser1, fileChooser2] = await Promise.all([
page.waitForFileChooser(),
page.waitForFileChooser(),
page.$eval('input', input => input.click()),
]);
expect(fileChooser1 === fileChooser2).toBe(true);
});
});
describeFailsFirefox('FileChooser.accept', function() {
it('should accept single file', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file oninput='javascript:console.timeStamp()'>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
await Promise.all([
chooser.accept([FILE_TO_UPLOAD]),
new Promise(x => page.once('metrics', x)),
]);
expect(await page.$eval('input', input => input.files.length)).toBe(1);
expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt');
});
it('should be able to read selected file', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
page.waitForFileChooser().then(chooser => chooser.accept([FILE_TO_UPLOAD]));
expect(await page.$eval('input', async picker => {
picker.click();
await new Promise(x => picker.oninput = x);
const reader = new FileReader();
const promise = new Promise(fulfill => reader.onload = fulfill);
reader.readAsText(picker.files[0]);
return promise.then(() => reader.result);
})).toBe('contents of the file');
});
it('should be able to reset selected files with empty file list', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
page.waitForFileChooser().then(chooser => chooser.accept([FILE_TO_UPLOAD]));
expect(await page.$eval('input', async picker => {
picker.click();
await new Promise(x => picker.oninput = x);
return picker.files.length;
})).toBe(1);
page.waitForFileChooser().then(chooser => chooser.accept([]));
expect(await page.$eval('input', async picker => {
picker.click();
await new Promise(x => picker.oninput = x);
return picker.files.length;
})).toBe(0);
});
it('should not accept multiple files for single-file input', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
let error = null;
await chooser.accept([
path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt'),
path.relative(process.cwd(), __dirname + '/assets/pptr.png'),
]).catch(e => error = e);
expect(error).not.toBe(null);
});
it('should fail when accepting file chooser twice', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.$eval('input', input => input.click()),
]);
await fileChooser.accept([]);
let error = null;
await fileChooser.accept([]).catch(e => error = e);
expect(error.message).toBe('Cannot accept FileChooser which is already handled!');
});
});
describeFailsFirefox('FileChooser.cancel', function() {
it('should cancel dialog', async() => {
const { page } = getTestState();
// Consider file chooser canceled if we can summon another one.
// There's no reliable way in WebPlatform to see that FileChooser was
// canceled.
await page.setContent(`<input type=file>`);
const [fileChooser1] = await Promise.all([
page.waitForFileChooser(),
page.$eval('input', input => input.click()),
]);
await fileChooser1.cancel();
// If this resolves, than we successfully canceled file chooser.
await Promise.all([
page.waitForFileChooser(),
page.$eval('input', input => input.click()),
]);
});
it('should fail when canceling file chooser twice', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.$eval('input', input => input.click()),
]);
await fileChooser.cancel();
let error = null;
await fileChooser.cancel().catch(e => error = e);
expect(error.message).toBe('Cannot cancel FileChooser which is already handled!');
});
});
describeFailsFirefox('FileChooser.isMultiple', () => {
it('should work for single file pick', async() => {
const { page } = getTestState();
await page.setContent(`<input type=file>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
expect(chooser.isMultiple()).toBe(false);
});
it('should work for "multiple"', async() => {
const { page } = getTestState();
await page.setContent(`<input multiple type=file>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
expect(chooser.isMultiple()).toBe(true);
});
it('should work for "webkitdirectory"', async() => {
const { page } = getTestState();
await page.setContent(`<input multiple webkitdirectory type=file>`);
const [chooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input'),
]);
expect(chooser.isMultiple()).toBe(true);
});
});
});