chore: add type tests (#8588)
This commit is contained in:
parent
7001322cd1
commit
e499515fd6
@ -3,6 +3,5 @@ build/
|
||||
coverage/
|
||||
doclint/
|
||||
lib/
|
||||
test-ts-types/
|
||||
tsconfig.tsbuildinfo
|
||||
vendor/
|
||||
|
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -55,8 +55,7 @@ jobs:
|
||||
# See https://github.com/puppeteer/puppeteer/issues/7710 for more info
|
||||
# npm run generate:docs
|
||||
npm run test:protocol-revision
|
||||
# TODO(jrandolf): Find a better way to test TypeScript source files.
|
||||
# npm run test:types
|
||||
npm run test:types
|
||||
|
||||
- name: Run commit lint
|
||||
run: |
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,7 +15,5 @@ node_modules/
|
||||
package-lock.json
|
||||
puppeteer.api.json
|
||||
puppeteer*.tgz
|
||||
test-ts-types/**/dist/
|
||||
test-ts-types/**/node_modules
|
||||
tsconfig.tsbuildinfo
|
||||
yarn.lock
|
@ -9,7 +9,6 @@ lib/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
package.json
|
||||
test-ts-types/
|
||||
test/assets/
|
||||
tsconfig.tsbuildinfo
|
||||
vendor/
|
||||
|
@ -36,7 +36,7 @@
|
||||
"test:pinned-deps": "ts-node -s scripts/ensure-pinned-deps",
|
||||
"test:install": "scripts/test-install.sh",
|
||||
"test:debug": "npm run build:test && mocha --inspect-brk",
|
||||
"test:types": "ts-node -s scripts/test-ts-definition-files.ts",
|
||||
"test:types": "tsc -b test-d",
|
||||
"prepublishOnly": "npm run build",
|
||||
"prepare": "node typescript-if-required.js && ([[ $HUSKY = 0 ]] || husky install)",
|
||||
"lint": "npm run build && npm run lint:eslint && npm run doc && npm run lint:prettier",
|
||||
@ -126,6 +126,7 @@
|
||||
"sinon": "14.0.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"text-diff": "1.0.1",
|
||||
"tsd": "0.21.0",
|
||||
"typescript": "4.7.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,217 +0,0 @@
|
||||
import {spawnSync} from 'child_process';
|
||||
import {version} from '../package.json';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
const PROJECT_FOLDERS_ROOT = 'test-ts-types';
|
||||
const EXPECTED_ERRORS = new Map<string, string[]>([
|
||||
[
|
||||
'ts-esm-import-esm-output',
|
||||
[
|
||||
"bad.ts(6,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(8,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(12,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.ts(20,5): error TS2345: Argument of type '(divElem: number) => any' is not assignable to parameter of type 'EvaluateFn<HTMLAnchorElement, any, any>'.",
|
||||
"bad.ts(20,34): error TS2339: Property 'innerText' does not exist on type 'number'.",
|
||||
"bad.ts(24,45): error TS2344: Type '(x: number) => string' does not satisfy the constraint 'EvaluateFn<HTMLAnchorElement, any, any>'.",
|
||||
"bad.ts(27,34): error TS2339: Property 'innerText' does not exist on type 'number'.",
|
||||
],
|
||||
],
|
||||
[
|
||||
'ts-esm-import-cjs-output',
|
||||
[
|
||||
"bad.ts(6,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(8,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(12,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'ts-cjs-import-cjs-output',
|
||||
[
|
||||
"bad.ts(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.ts(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.ts(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-esm-import-cjs-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
"bad.js(22,5): error TS2345: Argument of type '(divElem: number) => any' is not assignable to parameter of type 'EvaluateFn<HTMLElement, any, any>'.",
|
||||
"bad.js(22,26): error TS2339: Property 'innerText' does not exist on type 'number'.",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-cjs-import-esm-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-esm-import-esm-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
[
|
||||
'js-cjs-import-cjs-output',
|
||||
[
|
||||
"bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
|
||||
"bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
|
||||
'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
|
||||
"bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
|
||||
],
|
||||
],
|
||||
]);
|
||||
const PROJECT_FOLDERS = [...EXPECTED_ERRORS.keys()];
|
||||
|
||||
if (!process.env['CI']) {
|
||||
console.log(`IMPORTANT: this script assumes you have compiled Puppeteer
|
||||
and its types file before running. Make sure you have run:
|
||||
=> npm run build:tsc && npm run generate:types
|
||||
before executing this script locally.`);
|
||||
}
|
||||
|
||||
function packPuppeteer() {
|
||||
console.log('Packing Puppeteer');
|
||||
const result = spawnSync('npm', ['pack'], {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
console.log('Failed to pack Puppeteer', result.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Move from puppeteer-X.Y.Z.tgz to puppeteer.tgz so we don't have to update
|
||||
// it when versions change.
|
||||
const moveResult = spawnSync('mv', [
|
||||
`puppeteer-${version}.tgz`,
|
||||
'puppeteer.tgz',
|
||||
]);
|
||||
if (moveResult.status !== 0) {
|
||||
console.log('Failed to rename Puppeteer tar', moveResult.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return `puppeteer.tgz`;
|
||||
}
|
||||
|
||||
const tar = packPuppeteer();
|
||||
const tarPath = path.join(process.cwd(), tar);
|
||||
|
||||
function compileAndCatchErrors(projectLocation: string) {
|
||||
const {status, stdout, stderr} = spawnSync('npm', ['run', 'compile'], {
|
||||
cwd: projectLocation,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
const tsErrorMesssage = stdout.split('\n');
|
||||
|
||||
if (status === 0) {
|
||||
console.error(
|
||||
`Running tsc on ${projectLocation} succeeded without triggering the expected errors.`
|
||||
);
|
||||
console.log(stdout, stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return {
|
||||
tsErrorMesssage,
|
||||
};
|
||||
}
|
||||
|
||||
function testProject(folder: string) {
|
||||
console.log('\nTesting:', folder);
|
||||
const projectLocation = path.join(
|
||||
process.cwd(),
|
||||
PROJECT_FOLDERS_ROOT,
|
||||
folder
|
||||
);
|
||||
|
||||
const tarLocation = path.relative(projectLocation, tarPath);
|
||||
console.log('===> Clearing left over node_modules to ensure clean slate');
|
||||
try {
|
||||
fs.rmdirSync(path.join(projectLocation, 'node_modules'), {
|
||||
recursive: true,
|
||||
});
|
||||
} catch (_error) {
|
||||
// We don't care if this errors because if it did it's most likely because
|
||||
// there was no node_modules folder, which is fine.
|
||||
}
|
||||
console.log('===> Installing Puppeteer from tar file', tarLocation);
|
||||
const {status, stderr, stdout} = spawnSync('npm', ['install', tarLocation], {
|
||||
env: {
|
||||
...process.env,
|
||||
PUPPETEER_SKIP_DOWNLOAD: '1',
|
||||
},
|
||||
cwd: projectLocation,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
|
||||
if (status) {
|
||||
console.error(
|
||||
'Installing the tar file unexpectedly failed',
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
process.exit(status);
|
||||
}
|
||||
console.log('===> Running compile to ensure expected errors only.');
|
||||
const result = compileAndCatchErrors(projectLocation);
|
||||
const expectedErrors = EXPECTED_ERRORS.get(folder) || [];
|
||||
if (
|
||||
result.tsErrorMesssage.find(line => {
|
||||
return line.includes('good.ts') || line.includes('good.js');
|
||||
})
|
||||
) {
|
||||
console.error(
|
||||
`Error for ${projectLocation} contained unexpected failures in good.ts/good.js:\n${result.tsErrorMesssage.join(
|
||||
'\n'
|
||||
)}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const errorsInTsMessage = result.tsErrorMesssage.filter(line => {
|
||||
return line.includes('bad.ts') || line.includes('bad.js');
|
||||
});
|
||||
const expectedErrorsThatHaveOccurred = new Set<string>();
|
||||
const unexpectedErrors = errorsInTsMessage.filter(message => {
|
||||
const isExpected = expectedErrors.some(expectedError => {
|
||||
const isExpected = message.startsWith(expectedError);
|
||||
if (isExpected) {
|
||||
expectedErrorsThatHaveOccurred.add(expectedError);
|
||||
}
|
||||
return isExpected;
|
||||
});
|
||||
return !isExpected;
|
||||
});
|
||||
|
||||
if (unexpectedErrors.length) {
|
||||
console.error(
|
||||
`${projectLocation} had unexpected TS errors: ${unexpectedErrors.join(
|
||||
'\n'
|
||||
)}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
expectedErrors.forEach(expected => {
|
||||
if (!expectedErrorsThatHaveOccurred.has(expected)) {
|
||||
console.error(
|
||||
`${projectLocation} expected error that was not thrown: ${expected}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
console.log('===> ✅ Type-checked correctly.');
|
||||
}
|
||||
|
||||
PROJECT_FOLDERS.forEach(folder => {
|
||||
testProject(folder);
|
||||
});
|
@ -167,7 +167,7 @@ export class JSHandle<T = unknown> {
|
||||
[this, ...Params]
|
||||
>
|
||||
>(
|
||||
pageFunction: Func,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): // @ts-expect-error Circularity here is okay because we only need the return
|
||||
// type which doesn't use `this`.
|
||||
|
158
test-d/ElementHandle.test-d.ts
Normal file
158
test-d/ElementHandle.test-d.ts
Normal file
@ -0,0 +1,158 @@
|
||||
import {expectNotType, expectType} from 'tsd';
|
||||
import {ElementHandle} from '../lib/esm/puppeteer/common/ElementHandle.js';
|
||||
|
||||
declare const handle: ElementHandle;
|
||||
|
||||
{
|
||||
{
|
||||
expectType<ElementHandle<HTMLAnchorElement> | null>(await handle.$('a'));
|
||||
expectNotType<ElementHandle<Element> | null>(await handle.$('a'));
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<HTMLDivElement> | null>(await handle.$('div'));
|
||||
expectNotType<ElementHandle<Element> | null>(await handle.$('div'));
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<Element> | null>(await handle.$('some-custom'));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
expectType<ElementHandle<HTMLAnchorElement>[]>(await handle.$$('a'));
|
||||
expectNotType<ElementHandle<Element>[]>(await handle.$$('a'));
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<HTMLDivElement>[]>(await handle.$$('div'));
|
||||
expectNotType<ElementHandle<Element>[]>(await handle.$$('div'));
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<Element>[]>(await handle.$$('some-custom'));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
expectType<void>(
|
||||
await handle.$eval(
|
||||
'a',
|
||||
(element, int) => {
|
||||
expectType<HTMLAnchorElement>(element);
|
||||
expectType<number>(int);
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<void>(
|
||||
await handle.$eval(
|
||||
'div',
|
||||
(element, int, str) => {
|
||||
expectType<HTMLDivElement>(element);
|
||||
expectType<number>(int);
|
||||
expectType<string>(str);
|
||||
},
|
||||
1,
|
||||
''
|
||||
)
|
||||
);
|
||||
expectType<number>(
|
||||
await handle.$eval(
|
||||
'a',
|
||||
(element, value) => {
|
||||
expectType<HTMLAnchorElement>(element);
|
||||
return value;
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<number>(
|
||||
await handle.$eval(
|
||||
'some-element',
|
||||
(element, value) => {
|
||||
expectType<Element>(element);
|
||||
return value;
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<HTMLAnchorElement>(
|
||||
await handle.$eval('a', element => {
|
||||
return element;
|
||||
})
|
||||
);
|
||||
expectType<unknown>(await handle.$eval('a', 'document'));
|
||||
}
|
||||
|
||||
{
|
||||
expectType<void>(
|
||||
await handle.$$eval(
|
||||
'a',
|
||||
(elements, int) => {
|
||||
expectType<HTMLAnchorElement[]>(elements);
|
||||
expectType<number>(int);
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<void>(
|
||||
await handle.$$eval(
|
||||
'div',
|
||||
(elements, int, str) => {
|
||||
expectType<HTMLDivElement[]>(elements);
|
||||
expectType<number>(int);
|
||||
expectType<string>(str);
|
||||
},
|
||||
1,
|
||||
''
|
||||
)
|
||||
);
|
||||
expectType<number>(
|
||||
await handle.$$eval(
|
||||
'a',
|
||||
(elements, value) => {
|
||||
expectType<HTMLAnchorElement[]>(elements);
|
||||
return value;
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<number>(
|
||||
await handle.$$eval(
|
||||
'some-element',
|
||||
(elements, value) => {
|
||||
expectType<Element[]>(elements);
|
||||
return value;
|
||||
},
|
||||
1
|
||||
)
|
||||
);
|
||||
expectType<HTMLAnchorElement[]>(
|
||||
await handle.$$eval('a', elements => {
|
||||
return elements;
|
||||
})
|
||||
);
|
||||
expectType<unknown>(await handle.$$eval('a', 'document'));
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
expectType<ElementHandle<HTMLAnchorElement> | null>(
|
||||
await handle.waitForSelector('a')
|
||||
);
|
||||
expectNotType<ElementHandle<Element> | null>(
|
||||
await handle.waitForSelector('a')
|
||||
);
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<HTMLDivElement> | null>(
|
||||
await handle.waitForSelector('div')
|
||||
);
|
||||
expectNotType<ElementHandle<Element> | null>(
|
||||
await handle.waitForSelector('div')
|
||||
);
|
||||
}
|
||||
{
|
||||
expectType<ElementHandle<Element> | null>(
|
||||
await handle.waitForSelector('some-custom')
|
||||
);
|
||||
}
|
||||
}
|
84
test-d/JSHandle.test-d.ts
Normal file
84
test-d/JSHandle.test-d.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import {expectAssignable, expectNotAssignable, expectType} from 'tsd';
|
||||
import {ElementHandle} from '../lib/esm/puppeteer/common/ElementHandle.js';
|
||||
import {JSHandle} from '../lib/esm/puppeteer/common/JSHandle.js';
|
||||
|
||||
declare const handle: JSHandle;
|
||||
|
||||
{
|
||||
expectType<unknown>(await handle.evaluate('document'));
|
||||
expectType<number>(
|
||||
await handle.evaluate(() => {
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
expectType<HTMLElement>(
|
||||
await handle.evaluate(() => {
|
||||
return document.body;
|
||||
})
|
||||
);
|
||||
expectType<string>(
|
||||
await handle.evaluate(() => {
|
||||
return '';
|
||||
})
|
||||
);
|
||||
expectType<string>(
|
||||
await handle.evaluate((value, str) => {
|
||||
expectNotAssignable<never>(value);
|
||||
expectType<string>(str);
|
||||
return '';
|
||||
}, '')
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
expectType<JSHandle>(await handle.evaluateHandle('document'));
|
||||
expectType<JSHandle<number>>(
|
||||
await handle.evaluateHandle(() => {
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
expectType<JSHandle<string>>(
|
||||
await handle.evaluateHandle(() => {
|
||||
return '';
|
||||
})
|
||||
);
|
||||
expectType<JSHandle<string>>(
|
||||
await handle.evaluateHandle((value, str) => {
|
||||
expectNotAssignable<never>(value);
|
||||
expectType<string>(str);
|
||||
return '';
|
||||
}, '')
|
||||
);
|
||||
expectType<ElementHandle<HTMLElement>>(
|
||||
await handle.evaluateHandle(() => {
|
||||
return document.body;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
declare const handle2: JSHandle<{test: number}>;
|
||||
|
||||
{
|
||||
{
|
||||
expectType<JSHandle<number>>(await handle2.getProperty('test'));
|
||||
expectNotAssignable<JSHandle<string>>(await handle2.getProperty('test'));
|
||||
}
|
||||
{
|
||||
expectType<JSHandle<unknown>>(
|
||||
await handle2.getProperty('key-doesnt-exist')
|
||||
);
|
||||
expectAssignable<JSHandle<string>>(
|
||||
await handle2.getProperty('key-doesnt-exist')
|
||||
);
|
||||
expectAssignable<JSHandle<number>>(
|
||||
await handle2.getProperty('key-doesnt-exist')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
handle.evaluate((value, other) => {
|
||||
expectType<unknown>(value);
|
||||
expectType<{test: number}>(other);
|
||||
}, handle2);
|
||||
}
|
15
test-d/puppeteer.test-d.ts
Normal file
15
test-d/puppeteer.test-d.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {expectType} from 'tsd';
|
||||
import {
|
||||
connect,
|
||||
createBrowserFetcher,
|
||||
defaultArgs,
|
||||
executablePath,
|
||||
launch,
|
||||
default as puppeteer,
|
||||
} from '../lib/esm/puppeteer/puppeteer.js';
|
||||
|
||||
expectType<typeof launch>(puppeteer.launch);
|
||||
expectType<typeof connect>(puppeteer.connect);
|
||||
expectType<typeof createBrowserFetcher>(puppeteer.createBrowserFetcher);
|
||||
expectType<typeof defaultArgs>(puppeteer.defaultArgs);
|
||||
expectType<typeof executablePath>(puppeteer.executablePath);
|
8
test-d/tsconfig.json
Normal file
8
test-d/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"module": "ESNext"
|
||||
},
|
||||
"references": [{"path": "../src/tsconfig.esm.json"}]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,17 +0,0 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,17 +0,0 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
const contentsOfDiv = await div.evaluate(
|
||||
/**
|
||||
* @param {number} divElem
|
||||
* @returns number
|
||||
*/
|
||||
(divElem) => divElem.innerText
|
||||
);
|
||||
}
|
||||
run();
|
@ -1,17 +0,0 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLElement>}
|
||||
*/
|
||||
const div = await page.$('div');
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,17 +0,0 @@
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = await page.$('div');
|
||||
if (div) {
|
||||
/**
|
||||
* @type {puppeteer.ElementHandle<HTMLAnchorElement>}
|
||||
*/
|
||||
const newDiv = div;
|
||||
console.log('got a div!', newDiv);
|
||||
}
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.js", "bad.js"]
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$(
|
||||
'div'
|
||||
)) as puppeteer.ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,16 +0,0 @@
|
||||
import puppeteer = require('puppeteer');
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
page.on('request', (request) => {
|
||||
const resourceType = request.resourceType();
|
||||
});
|
||||
const div = (await page.$(
|
||||
'div'
|
||||
)) as puppeteer.ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$(
|
||||
'div'
|
||||
)) as puppeteer.ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,13 +0,0 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
import type { ElementHandle } from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = (await page.$('div')) as ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
// Typo in "launch"
|
||||
const browser = await puppeteer.launh();
|
||||
// Typo: "devices"
|
||||
const devices = puppeteer.devics;
|
||||
console.log(devices);
|
||||
const browser2 = await puppeteer.launch();
|
||||
// 'foo' is invalid argument
|
||||
const page = await browser2.newPage('foo');
|
||||
const div = (await page.$(
|
||||
'div'
|
||||
)) as puppeteer.ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
const contentsOfDiv = await div.evaluate(
|
||||
// Bad: the type system will know here that divElem is an HTMLAnchorElement
|
||||
// and won't let me tell it it's a number
|
||||
(divElem: number) => divElem.innerText
|
||||
);
|
||||
// Bad: the type system will know here that divElem is an HTMLAnchorElement
|
||||
// and won't let me tell it it's a number via the generic
|
||||
const contentsOfDiv2 = await div.evaluate<(x: number) => string>(
|
||||
// Bad: now I've forced it to be a number (which is an error also)
|
||||
// I can't call `innerText` on it.
|
||||
(divElem: number) => divElem.innerText
|
||||
);
|
||||
}
|
||||
run();
|
@ -1,15 +0,0 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import * as puppeteer from 'puppeteer';
|
||||
import type { ElementHandle } from 'puppeteer';
|
||||
|
||||
async function run() {
|
||||
const browser = await puppeteer.launch();
|
||||
const devices = puppeteer.devices;
|
||||
console.log(devices);
|
||||
const page = await browser.newPage();
|
||||
const div = (await page.$('div')) as ElementHandle<HTMLAnchorElement>;
|
||||
console.log('got a div!', div);
|
||||
|
||||
const contentsOfDiv = await div.evaluate((divElem) => divElem.innerText);
|
||||
}
|
||||
run();
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "test-ts-types-ts-esm",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Test project with TypeScript, ESM output",
|
||||
"scripts": {
|
||||
"compile": "../../node_modules/.bin/tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer": "file:../../puppeteer.tgz"
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"files": ["good.ts", "bad.ts"]
|
||||
}
|
Loading…
Reference in New Issue
Block a user