From a39789b176f74d8a67d13bcb33f400caad812fda Mon Sep 17 00:00:00 2001 From: Peter Burns Date: Wed, 2 May 2018 20:33:00 -0700 Subject: [PATCH 1/2] Add an integration test of our import.meta support. --- .../src/test/integration/integration_test.ts | 201 ++++++++++++++++-- 1 file changed, 180 insertions(+), 21 deletions(-) diff --git a/packages/cli/src/test/integration/integration_test.ts b/packages/cli/src/test/integration/integration_test.ts index 488695d81..6b62d59bc 100644 --- a/packages/cli/src/test/integration/integration_test.ts +++ b/packages/cli/src/test/integration/integration_test.ts @@ -18,8 +18,14 @@ import {runCommand} from './run-command'; import {createElementGenerator} from '../../init/element/element'; import {createGithubGenerator} from '../../init/github'; import * as puppeteer from 'puppeteer'; -import {startServers} from 'polyserve'; -import {ProjectConfig} from 'polymer-project-config'; +import {startServers, ServerOptions} from 'polyserve'; +import {ProjectConfig, ProjectOptions} from 'polymer-project-config'; +import * as tempMod from 'temp'; +import * as fs from 'fs'; + +const temp = tempMod.track(); + +const disposables: Array<() => void | Promise> = []; // A zero privilege github token of a nonce account, used for quota. const githubToken = '8d8622bf09bb1d85cb411b5e475a35e742a7ce35'; @@ -28,7 +34,30 @@ const githubToken = '8d8622bf09bb1d85cb411b5e475a35e742a7ce35'; // windows. const isWindows = process.platform === 'win32'; const skipOnWindows = isWindows ? test.skip : test; +const binPath = path.join(__dirname, '../../../', 'bin', 'polymer.js'); + +// Serves the given directory with polyserve, returns a fully qualified +// url of the server. +async function serve(dirToServe: string, options: ServerOptions = {}) { + const startResult = await startServers({root: dirToServe, ...options}); + if (startResult.kind === 'MultipleServers') { + for (const server of startResult.servers) { + server.server.close(); + } + throw new Error(`Unexpected startResult`); + } + disposables.push(() => { + startResult.server.close(); + }); + const address = startResult.server.address(); + return `http://${address.address}:${address.port}`; +} +/** + * Like puppeteer's page.goto(), except it fails if any uncaught exceptions are + * thrown, and it waits a few rAFs after the load to be really sure the page is + * ready. + */ async function gotoOrDie( page: puppeteer.Page, url: string, configurationName?: string) { const configurationMessage = @@ -60,15 +89,14 @@ async function gotoOrDie( } suite('integration tests', function() { - const binPath = path.join(__dirname, '../../../', 'bin', 'polymer.js'); - // Extend timeout limit to 90 seconds for slower systems this.timeout(120000); - const disposables: Array<() => void | Promise> = []; - teardown(async () => { + + suiteTeardown(async () => { await Promise.all(disposables.map((d) => d())); disposables.length = 0; }); + teardown(async () => {}); suite('init templates', () => { skipOnWindows('test the Polymer 3.x element template', async () => { @@ -152,28 +180,16 @@ suite('integration tests', function() { // and pokes around to test that the site is serving a working Shop. async function assertThatShopWorks( dirToServe: string, configurationName: string) { - const startResult = await startServers({root: dirToServe}); - if (startResult.kind === 'MultipleServers') { - for (const server of startResult.servers) { - server.server.close(); - } - throw new Error(`Unexpected startResult`); - } - disposables.push(() => { - startResult.server.close(); - }); - const address = startResult.server.address(); - const baseUrl = `http://${address.address}:${address.port}`; + const baseUrl = await serve(dirToServe); const debugging = !!process.env['DEBUG_CLI_TESTS']; - let browser; + let browser: puppeteer.Browser; if (debugging) { browser = await puppeteer.launch({headless: false, slowMo: 250}); } else { browser = await puppeteer.launch(); } - const page = await browser.newPage(); - disposables.push(() => page.close()); + disposables.push(() => browser.close()); // Evaluate an expression as a string in the browser. const evaluate = async (expression: string) => { @@ -376,3 +392,146 @@ suite('integration tests', function() { }); }); }); + +suite('import.meta support', async () => { + let tempDir: string; + // Build options, copied from shop. + const options: ProjectOptions = { + entrypoint: 'index.html', + builds: [ + { + name: 'esm-bundled', + browserCapabilities: ['es2015', 'modules'], + js: {minify: true}, + css: {minify: true}, + html: {minify: true}, + bundle: true + }, + { + name: 'es6-bundled', + browserCapabilities: ['es2015'], + js: {minify: true, transformModulesToAmd: true}, + css: {minify: true}, + html: {minify: true}, + bundle: true + }, + { + name: 'es5-bundled', + js: {compile: true, minify: true, transformModulesToAmd: true}, + css: {minify: true}, + html: {minify: true}, + bundle: true + } + ], + moduleResolution: 'node', + npm: true + }; + suiteSetup(function() { + tempDir = temp.mkdirSync('-import-meta'); + + // An inline import.meta test fixture! + fs.writeFileSync(path.join(tempDir, 'index.html'), ` + + `); + fs.mkdirSync(path.join(tempDir, 'subdir')); + fs.writeFileSync(path.join(tempDir, 'subdir/index.html'), ` + + `); + fs.writeFileSync(path.join(tempDir, 'subdir', 'foo.js'), ` + window.fooUrl = import.meta.url; + `); + fs.writeFileSync( + path.join(tempDir, 'package.json'), + JSON.stringify({name: 'import-meta-test'})); + fs.writeFileSync( + path.join(tempDir, 'polymer.json'), JSON.stringify(options)); + }); + teardown(async () => { + await Promise.all(disposables.map((d) => d())); + disposables.length = 0; + }); + + // The given url should be a fully qualified + const assertPageWorksCorrectly = async (baseUrl: string) => { + const browser = await puppeteer.launch(); + disposables.push(() => browser.close()); + const page = await browser.newPage(); + await gotoOrDie(page, `${baseUrl}/`); + assert.deepEqual(await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + await gotoOrDie(page, `${baseUrl}/index.html`); + assert.deepEqual( + await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/index.html`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + await gotoOrDie(page, `${baseUrl}/subdir/`); + assert.deepEqual( + await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/subdir/`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + await gotoOrDie(page, `${baseUrl}/subdir/index.html`); + assert.deepEqual( + await page.evaluate(`window.indexHtmlUrl`), + `${baseUrl}/subdir/index.html`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + return page; + }; + + test('import.meta works uncompiled in chrome', async function() { + const url = await serve(tempDir, {compile: 'never'}); + const page = await assertPageWorksCorrectly(url); + await gotoOrDie(page, `${url}/`); + assert.include( + await page.content(), + 'import.meta', + 'expected import.meta to not be compiled out!'); + }); + + let testName = 'import.meta works in chrome with polyserve es5 compilation'; + test(testName, async function() { + const url = await serve(tempDir, {compile: 'always'}); + const page = await assertPageWorksCorrectly(url); + await gotoOrDie(page, `${url}/`); + assert.notInclude( + await page.content(), + 'import.meta', + 'expected import.meta to be compiled out!'); + }); + + // Unskip in https://github.com/Polymer/tools/pull/300 + suite.skip('after building', () => { + suiteSetup(async function() { + this.timeout(20 * 1000); + await runCommand(binPath, ['build'], {cwd: tempDir}); + }); + for (const buildOption of options.builds!) { + const buildName = buildOption.name || 'default'; + testName = `import.meta works in build configuration ${buildName}`; + test(testName, async function() { + const url = await serve( + path.join(tempDir, 'build', buildName), {compile: 'always'}); + const page = await assertPageWorksCorrectly(url); + await gotoOrDie(page, `${url}/`); + if (buildName !== 'esm-bundle') { + assert.notInclude( + await page.content(), + 'import.meta', + 'expected import.meta to be compiled out!'); + } else { + assert.include( + await page.content(), + 'import.meta', + 'expected import.meta to not be compiled out!'); + } + }); + } + }); +}); From b5823e2a5ff56e8ed8234231fc58d4ce546b54dd Mon Sep 17 00:00:00 2001 From: Peter Burns Date: Thu, 3 May 2018 14:27:09 -0700 Subject: [PATCH 2/2] Also test built output for import.meta. --- .../src/test/integration/integration_test.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/test/integration/integration_test.ts b/packages/cli/src/test/integration/integration_test.ts index 6b62d59bc..00014700a 100644 --- a/packages/cli/src/test/integration/integration_test.ts +++ b/packages/cli/src/test/integration/integration_test.ts @@ -458,7 +458,8 @@ suite('import.meta support', async () => { }); // The given url should be a fully qualified - const assertPageWorksCorrectly = async (baseUrl: string) => { + const assertPageWorksCorrectly = + async (baseUrl: string, skipTestingSubdir: boolean = false) => { const browser = await puppeteer.launch(); disposables.push(() => browser.close()); const page = await browser.newPage(); @@ -471,17 +472,19 @@ suite('import.meta support', async () => { await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/index.html`); assert.deepEqual( await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); - await gotoOrDie(page, `${baseUrl}/subdir/`); - assert.deepEqual( - await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/subdir/`); - assert.deepEqual( - await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); - await gotoOrDie(page, `${baseUrl}/subdir/index.html`); - assert.deepEqual( - await page.evaluate(`window.indexHtmlUrl`), - `${baseUrl}/subdir/index.html`); - assert.deepEqual( - await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + if (!skipTestingSubdir) { + await gotoOrDie(page, `${baseUrl}/subdir/`); + assert.deepEqual( + await page.evaluate(`window.indexHtmlUrl`), `${baseUrl}/subdir/`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + await gotoOrDie(page, `${baseUrl}/subdir/index.html`); + assert.deepEqual( + await page.evaluate(`window.indexHtmlUrl`), + `${baseUrl}/subdir/index.html`); + assert.deepEqual( + await page.evaluate('window.fooUrl'), `${baseUrl}/subdir/foo.js`); + } return page; }; @@ -506,8 +509,7 @@ suite('import.meta support', async () => { 'expected import.meta to be compiled out!'); }); - // Unskip in https://github.com/Polymer/tools/pull/300 - suite.skip('after building', () => { + suite('after building', () => { suiteSetup(async function() { this.timeout(20 * 1000); await runCommand(binPath, ['build'], {cwd: tempDir}); @@ -518,7 +520,7 @@ suite('import.meta support', async () => { test(testName, async function() { const url = await serve( path.join(tempDir, 'build', buildName), {compile: 'always'}); - const page = await assertPageWorksCorrectly(url); + const page = await assertPageWorksCorrectly(url, true); await gotoOrDie(page, `${url}/`); if (buildName !== 'esm-bundle') { assert.notInclude(