From 7afd8bbf979cb36f1a3dd3b29de2f3db8368de48 Mon Sep 17 00:00:00 2001 From: Ryan Christian <33403762+rschristian@users.noreply.github.com> Date: Thu, 14 Apr 2022 19:12:14 -0500 Subject: [PATCH] refactor: build test suite (#1670) Co-authored-by: Leah --- .changeset/purple-chefs-yell.md | 5 + packages/cli/lib/commands/build.js | 2 +- packages/cli/lib/lib/webpack/run-webpack.js | 4 +- packages/cli/lib/resources/template.html | 2 +- packages/cli/tests/build.test.js | 511 ++++++++++++------ packages/cli/tests/create.test.js | 7 +- packages/cli/tests/images/build.js | 63 ++- packages/cli/tests/lib/cli.js | 14 +- packages/cli/tests/lib/output.js | 10 +- .../css-auto-modules/components/index.js | 4 + .../css-auto-modules/components/style.css | 3 + .../subjects/css-auto-modules/global.css | 3 + .../tests/subjects/css-auto-modules/index.js | 14 + .../subjects/css-auto-modules/package.json | 4 + .../subjects/css-auto-modules/routes/index.js | 4 + .../css-auto-modules/routes/style.css | 3 + .../cli/tests/subjects/css-imports/index.js | 2 + .../tests/subjects/css-imports/package.json | 4 + .../cli/tests/subjects/css-imports/style.css | 5 + .../tests/subjects/css-imports/styles/a.css | 5 + .../tests/subjects/css-imports/styles/b.css | 3 + .../tests/subjects/css-imports/styles/img.jpg | Bin 0 -> 56080 bytes .../cli/tests/subjects/css-inline/index.js | 5 + .../tests/subjects/css-inline/package.json | 4 + .../cli/tests/subjects/css-inline/style.css | 7 + .../components/app/index.js | 0 .../components/app/style.scss | 0 .../subjects/{sass => css-sass}/index.js | 0 .../cli/tests/subjects/css-sass/package.json | 4 + .../tests/subjects/css-side-effect/index.js | 1 + .../package.json | 2 +- .../style.css | 0 .../subjects/custom-babelrc/package.json | 2 +- .../subjects/custom-template/package.json | 2 +- .../subjects/custom-webpack/package.json | 2 +- packages/cli/tests/subjects/minimal/index.js | 4 + .../cli/tests/subjects/minimal/package.json | 4 + packages/cli/tests/subjects/minimal/style.css | 3 + .../package.json | 2 +- .../multiple-prerendering/package.json | 2 +- .../subjects/preload-chunks/package.json | 2 +- .../prerendering-hydration/package.json | 2 +- .../package.json | 2 +- .../cli/tests/subjects/public-path/index.js | 4 + .../tests/subjects/public-path/package.json | 4 + .../subjects/public-path/preact.config.js | 3 + .../cli/tests/subjects/public-path/style.css | 0 packages/cli/tests/subjects/sass/package.json | 4 - .../tests/subjects/side-effect-css/index.js | 6 - .../tests/subjects/static-root/package.json | 2 +- 50 files changed, 522 insertions(+), 223 deletions(-) create mode 100644 .changeset/purple-chefs-yell.md create mode 100644 packages/cli/tests/subjects/css-auto-modules/components/index.js create mode 100644 packages/cli/tests/subjects/css-auto-modules/components/style.css create mode 100644 packages/cli/tests/subjects/css-auto-modules/global.css create mode 100644 packages/cli/tests/subjects/css-auto-modules/index.js create mode 100644 packages/cli/tests/subjects/css-auto-modules/package.json create mode 100644 packages/cli/tests/subjects/css-auto-modules/routes/index.js create mode 100644 packages/cli/tests/subjects/css-auto-modules/routes/style.css create mode 100644 packages/cli/tests/subjects/css-imports/index.js create mode 100644 packages/cli/tests/subjects/css-imports/package.json create mode 100644 packages/cli/tests/subjects/css-imports/style.css create mode 100644 packages/cli/tests/subjects/css-imports/styles/a.css create mode 100644 packages/cli/tests/subjects/css-imports/styles/b.css create mode 100644 packages/cli/tests/subjects/css-imports/styles/img.jpg create mode 100644 packages/cli/tests/subjects/css-inline/index.js create mode 100644 packages/cli/tests/subjects/css-inline/package.json create mode 100644 packages/cli/tests/subjects/css-inline/style.css rename packages/cli/tests/subjects/{sass => css-sass}/components/app/index.js (100%) rename packages/cli/tests/subjects/{sass => css-sass}/components/app/style.scss (100%) rename packages/cli/tests/subjects/{sass => css-sass}/index.js (100%) create mode 100644 packages/cli/tests/subjects/css-sass/package.json create mode 100644 packages/cli/tests/subjects/css-side-effect/index.js rename packages/cli/tests/subjects/{side-effect-css => css-side-effect}/package.json (51%) rename packages/cli/tests/subjects/{side-effect-css => css-side-effect}/style.css (100%) create mode 100644 packages/cli/tests/subjects/minimal/index.js create mode 100644 packages/cli/tests/subjects/minimal/package.json create mode 100644 packages/cli/tests/subjects/minimal/style.css create mode 100644 packages/cli/tests/subjects/public-path/index.js create mode 100644 packages/cli/tests/subjects/public-path/package.json create mode 100644 packages/cli/tests/subjects/public-path/preact.config.js create mode 100644 packages/cli/tests/subjects/public-path/style.css delete mode 100644 packages/cli/tests/subjects/sass/package.json delete mode 100644 packages/cli/tests/subjects/side-effect-css/index.js diff --git a/.changeset/purple-chefs-yell.md b/.changeset/purple-chefs-yell.md new file mode 100644 index 000000000..8167d6d31 --- /dev/null +++ b/.changeset/purple-chefs-yell.md @@ -0,0 +1,5 @@ +--- +'preact-cli': patch +--- + +Corrects 'build --json' ouput location and 'apple-touch-icon' will respect the publicPath automatically diff --git a/packages/cli/lib/commands/build.js b/packages/cli/lib/commands/build.js index 2b965e552..411b39baa 100644 --- a/packages/cli/lib/commands/build.js +++ b/packages/cli/lib/commands/build.js @@ -107,7 +107,7 @@ async function command(src, argv) { let stats = await runWebpack(argv, false); if (argv.json) { - await runWebpack.writeJsonStats(stats); + await runWebpack.writeJsonStats(cwd, stats); } } diff --git a/packages/cli/lib/lib/webpack/run-webpack.js b/packages/cli/lib/lib/webpack/run-webpack.js index c82de0d72..abc1544f5 100644 --- a/packages/cli/lib/lib/webpack/run-webpack.js +++ b/packages/cli/lib/lib/webpack/run-webpack.js @@ -122,8 +122,8 @@ function showStats(stats, isProd) { return stats; } -function writeJsonStats(stats) { - let outputPath = resolve(process.cwd(), 'stats.json'); +function writeJsonStats(cwd, stats) { + let outputPath = resolve(cwd, 'stats.json'); let jsonStats = stats.toJson({ json: true, chunkModules: true, diff --git a/packages/cli/lib/resources/template.html b/packages/cli/lib/resources/template.html index 770c48b2b..4b33acd6f 100644 --- a/packages/cli/lib/resources/template.html +++ b/packages/cli/lib/resources/template.html @@ -6,7 +6,7 @@ - + <% preact.headEnd %> diff --git a/packages/cli/tests/build.test.js b/packages/cli/tests/build.test.js index fe172d934..a2be5370b 100644 --- a/packages/cli/tests/build.test.js +++ b/packages/cli/tests/build.test.js @@ -1,5 +1,6 @@ const { join } = require('path'); -const { access, readdir, readFile, writeFile } = require('fs').promises; +const { access, mkdir, readdir, readFile, rename, unlink, writeFile } = + require('fs').promises; const looksLike = require('html-looks-like'); const { create, build } = require('./lib/cli'); const { snapshot } = require('./lib/utils'); @@ -46,28 +47,40 @@ function testMatch(received, expected) { } } +/** + * Get build output file as utf-8 string + * @param {string} dir + * @param {RegExp | string} file + * @returns {Promise} + */ +async function getOutputFile(dir, file) { + if (typeof file !== 'string') { + // @ts-ignore + file = (await readdir(join(dir, 'build'))).find(f => file.test(f)); + } + return await readFile(join(dir, 'build', file), 'utf8'); +} + describe('preact build', () => { - it(`builds the 'default' template`, async () => { + it('builds the `default` template', async () => { let dir = await create('default'); await build(dir); - dir = join(dir, 'build'); - let output = await snapshot(dir); + let output = await snapshot(join(dir, 'build')); testMatch(output, images.default); }); - it(`builds the 'default' template with esm`, async () => { + it('builds the `default` template with esm', async () => { let dir = await create('default'); await build(dir, { esm: true }); - dir = join(dir, 'build'); - let output = await snapshot(dir); + let output = await snapshot(join(dir, 'build')); testMatch(output, images['default-esm']); }); - it(`builds the 'typescript' template`, async () => { + it('builds the `typescript` template', async () => { let dir = await create('typescript'); // The tsconfig.json in the template covers the test directory, @@ -77,157 +90,13 @@ describe('preact build', () => { // Remove when https://github.com/preactjs/enzyme-adapter-preact-pure/issues/161 is resolved shell.exec('rm tsconfig.json'); - expect(() => build(dir)).not.toThrow(); - }); - - it('should use SASS styles', async () => { - let dir = await subject('sass'); - await build(dir); - - let body = await getBody(dir); - looksLike(body, images.sass); - }); - - it('should use custom `.babelrc`', async () => { - // app with custom .babelrc enabling async functions - let dir = await subject('custom-babelrc'); - - await build(dir); - - const bundleFile = (await readdir(`${dir}/build`)).find(file => - /bundle\.\w{5}\.js$/.test(file) - ); - const transpiledChunk = await readFile( - `${dir}/build/${bundleFile}`, - 'utf8' - ); - - // when tragetting only last 1 chrome version, babel preserves - // arrow function. So checking for the delay function code from delay function in - // https://github.com/preactjs/preact-cli/blob/master/packages/cli/tests/subjects/custom-babelrc/index.js - expect(transpiledChunk.includes('=>setTimeout')).toBe(true); - }); - - prerenderUrlFiles.forEach(prerenderUrls => { - it(`should prerender the routes provided with '${prerenderUrls}'`, async () => { - let dir = await subject('multiple-prerendering'); - await build(dir, { prerenderUrls }); - - const body1 = await getBody(dir); - looksLike(body1, images.prerender.home); - - const body2 = await getBody(dir, 'route66/index.html'); - looksLike(body2, images.prerender.route); - - const body3 = await getBody(dir, 'custom/index.html'); - looksLike(body3, images.prerender.custom); - - const head1 = await getHead(dir); - expect(head1).toEqual( - expect.stringMatching(getRegExpFromMarkup(images.prerender.heads.home)) - ); - - const head2 = await getHead(dir, 'route66/index.html'); - expect(head2).toEqual( - expect.stringMatching( - getRegExpFromMarkup(images.prerender.heads.route66) - ) - ); - - const head3 = await getHead(dir, 'custom/index.html'); - expect(head3).toEqual( - expect.stringMatching( - getRegExpFromMarkup(images.prerender.heads.custom) - ) - ); - }); - }); - - prerenderUrlFiles.forEach(prerenderUrls => { - it(`should prerender the routes with data provided with '${prerenderUrls}' via provider`, async () => { - let dir = await subject('multiple-prerendering-with-provider'); - await build(dir, { prerenderUrls }); - - const body1 = await getBody(dir); - looksLike(body1, images.prerender.home); - - const body2 = await getBody(dir, 'route66/index.html'); - looksLike(body2, images.prerender.route); - - const body3 = await getBody(dir, 'custom/index.html'); - looksLike(body3, images.prerender.custom); - - const body4 = await getBody(dir, 'customhook/index.html'); - looksLike(body4, images.prerender.customhook); - - const body5 = await getBody(dir, 'htmlsafe/index.html'); - looksLike(body5, images.prerender.htmlSafe); - - const head1 = await getHead(dir); - expect(head1).toEqual( - expect.stringMatching(getRegExpFromMarkup(images.prerender.heads.home)) - ); - - const head2 = await getHead(dir, 'route66/index.html'); - expect(head2).toEqual( - expect.stringMatching( - getRegExpFromMarkup(images.prerender.heads.route66) - ) - ); - - const head3 = await getHead(dir, 'custom/index.html'); - expect(head3).toEqual( - expect.stringMatching( - getRegExpFromMarkup(images.prerender.heads.custom) - ) - ); - }); - }); - - it('should preload correct files', async () => { - let dir = await subject('preload-chunks'); - await build(dir, { preload: true }); - - const head1 = await getHead(dir); - expect(head1).toEqual( - expect.stringMatching(getRegExpFromMarkup(images.preload.head)) - ); - }); - - it('should use custom `preact.config.js`', async () => { - // app with stable output name via preact.config.js - let dir = await subject('custom-webpack'); - await build(dir); - - let stableOutput = join(dir, 'build/bundle.js'); - expect(await access(stableOutput)).toBeUndefined(); - }); - - it('should use custom `template.html`', async () => { - let dir = await subject('custom-template'); - await build(dir); - - let file = join(dir, 'build/index.html'); - let html = await readFile(file, 'utf-8'); - - expect(html).toEqual( - expect.stringMatching(getRegExpFromMarkup(images.template)) - ); + await expect(build(dir)).resolves.not.toThrow(); }); it('should patch global location object', async () => { let dir = await subject('location-patch'); - expect(() => build(dir)).not.toThrow(); - }); - it('should import non-modules CSS even when side effects are false', async () => { - let dir = await subject('side-effect-css'); - await build(dir); - - let head = await getHead(dir); - expect(head).toEqual( - expect.stringMatching(getRegExpFromMarkup(images.sideEffectCss)) - ); + await expect(build(dir)).resolves.not.toThrow(); }); it('should copy resources from static to build directory', async () => { @@ -237,16 +106,6 @@ describe('preact build', () => { expect(await access(file)).toBeUndefined(); }); - it('should error out for invalid CLI argument', async () => { - let dir = await subject('custom-template'); - const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}); - await expect(build(dir, { 'service-worker': false })).rejects.toEqual( - new Error('Invalid argument found.') - ); - expect(mockExit).toHaveBeenCalledWith(1); - mockExit.mockRestore(); - }); - describe('Push manifest plugin', () => { it('should produce correct default `push-manifest.json`', async () => { let dir = await create('default'); @@ -326,4 +185,328 @@ describe('preact build', () => { // "Hello World!" should replace 'process.env.PREACT_APP_MY_VARIABLE' expect(transpiledChunk.includes('console.log("Hello World!")')).toBe(true); }); + + it('should respect `publicPath` value', async () => { + let dir = await subject('public-path'); + await build(dir); + const html = await getOutputFile(dir, 'index.html'); + + expect(html).toEqual( + expect.stringMatching(getRegExpFromMarkup(images.publicPath)) + ); + }); + + describe('CLI Options', () => { + it('--src', async () => { + let dir = await subject('minimal'); + + await mkdir(join(dir, 'renamed-src')); + await rename(join(dir, 'index.js'), join(dir, 'renamed-src/index.js')); + await rename(join(dir, 'style.css'), join(dir, 'renamed-src/style.css')); + + await expect(build(dir, { src: 'renamed-src' })).resolves.toBeUndefined(); + }); + + it('--dest', async () => { + let dir = await subject('minimal'); + + await build(dir, { dest: 'renamed-dest' }); + expect(await access(join(dir, 'renamed-dest'))).toBeUndefined(); + }); + + it('--sw', async () => { + let dir = await subject('minimal'); + + const logSpy = jest.spyOn(process.stdout, 'write'); + + await build(dir, { sw: true }); + expect(await access(join(dir, 'build', 'sw.js'))).toBeUndefined(); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('Could not find sw.js') + ); + + await build(dir, { sw: false }); + await expect(access(join(dir, 'build', 'sw.js'))).rejects.toThrow( + 'no such file or directory' + ); + }); + + it('--babelConfig', async () => { + let dir = await subject('custom-babelrc'); + + await build(dir); + let transpiledChunk = await getOutputFile(dir, /bundle\.\w{5}\.js$/); + expect(/=>\s?setTimeout/.test(transpiledChunk)).toBe(true); + + await rename(join(dir, '.babelrc'), join(dir, 'babel.config.json')); + await build(dir, { + babelConfig: 'babel.config.json', + }); + transpiledChunk = await getOutputFile(dir, /bundle\.\w{5}\.js$/); + expect(/=>\s?setTimeout/.test(transpiledChunk)).toBe(true); + }); + + it('--json', async () => { + let dir = await subject('minimal'); + + await build(dir, { json: true }); + expect(await access(join(dir, 'stats.json'))).toBeUndefined(); + // Need to clean up manually as it is placed in project root + await unlink(join(dir, 'stats.json')); + + await build(dir, { json: false }); + await expect(access(join(dir, 'stats.json'))).rejects.toThrow( + 'no such file or directory' + ); + }); + + it('--template', async () => { + let dir = await subject('custom-template'); + + await rename( + join(dir, 'template.html'), + join(dir, 'renamed-template.html') + ); + await build(dir, { template: 'renamed-template.html' }); + + const html = await getOutputFile(dir, 'index.html'); + expect(html).toEqual( + expect.stringMatching(getRegExpFromMarkup(images.template)) + ); + }); + + it('--preload', async () => { + let dir = await subject('preload-chunks'); + + await build(dir, { preload: true }); + let head = await getHead(dir); + expect(head).toEqual( + expect.stringMatching(getRegExpFromMarkup(images.preload.true)) + ); + + await build(dir, { preload: false }); + head = await getHead(dir); + expect(head).toEqual( + expect.stringMatching(getRegExpFromMarkup(images.preload.false)) + ); + }); + + it('--prerender', async () => { + let dir = await subject('minimal'); + + await build(dir, { prerender: true }); + let html = await getOutputFile(dir, 'index.html'); + expect(html).toMatch('

Minimal App

'); + + await build(dir, { prerender: false }); + html = await getOutputFile(dir, 'index.html'); + expect(html).not.toMatch('

Minimal App

'); + }); + + it('--prerenderUrls', async () => { + let dir = await subject('multiple-prerendering'); + + await build(dir, { prerenderUrls: 'prerender-urls.json' }); + expect(await access(join(dir, 'build/index.html'))).toBeUndefined(); + expect( + await access(join(dir, 'build/route66/index.html')) + ).toBeUndefined(); + expect( + await access(join(dir, 'build/custom/index.html')) + ).toBeUndefined(); + + await rename( + join(dir, 'prerender-urls.json'), + join(dir, 'renamed-urls.json') + ); + await build(dir, { prerenderUrls: 'renamed-urls.json' }); + expect(await access(join(dir, 'build/index.html'))).toBeUndefined(); + expect( + await access(join(dir, 'build/route66/index.html')) + ).toBeUndefined(); + expect( + await access(join(dir, 'build/custom/index.html')) + ).toBeUndefined(); + }); + + it('--inline-css', async () => { + let dir = await subject('minimal'); + + await build(dir, { 'inline-css': true }); + let head = await getHead(dir); + expect(head).toMatch(''); + + await build(dir, { 'inline-css': false }); + head = await getOutputFile(dir, 'index.html'); + expect(head).not.toMatch(/'); + }); + + // Issue #1411 + it('should preserve side-effectful CSS imports even if package.json claims no side effects', async () => { + let dir = await subject('css-side-effect'); + await build(dir); + + const builtStylesheet = await getOutputFile(dir, /bundle\.\w{5}\.css$/); + expect(builtStylesheet).toMatch('h1{background:#673ab8}'); + }); + + it('should use SASS styles', async () => { + let dir = await subject('css-sass'); + await build(dir); + + let body = await getBody(dir); + looksLike(body, images.sass); + }); + }); + + describe('prerender', () => { + prerenderUrlFiles.forEach(prerenderUrls => { + it(`should prerender the routes provided with '${prerenderUrls}'`, async () => { + let dir = await subject('multiple-prerendering'); + await build(dir, { prerenderUrls }); + + const body1 = await getBody(dir); + looksLike(body1, images.prerender.home); + + const body2 = await getBody(dir, 'route66/index.html'); + looksLike(body2, images.prerender.route); + + const body3 = await getBody(dir, 'custom/index.html'); + looksLike(body3, images.prerender.custom); + + const head1 = await getHead(dir); + expect(head1).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.home) + ) + ); + + const head2 = await getHead(dir, 'route66/index.html'); + expect(head2).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.route66) + ) + ); + + const head3 = await getHead(dir, 'custom/index.html'); + expect(head3).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.custom) + ) + ); + }); + }); + + prerenderUrlFiles.forEach(prerenderUrls => { + it(`should prerender the routes with data provided with '${prerenderUrls}' via provider`, async () => { + let dir = await subject('multiple-prerendering-with-provider'); + await build(dir, { prerenderUrls }); + + const body1 = await getBody(dir); + looksLike(body1, images.prerender.home); + + const body2 = await getBody(dir, 'route66/index.html'); + looksLike(body2, images.prerender.route); + + const body3 = await getBody(dir, 'custom/index.html'); + looksLike(body3, images.prerender.custom); + + const body4 = await getBody(dir, 'customhook/index.html'); + looksLike(body4, images.prerender.customhook); + + const body5 = await getBody(dir, 'htmlsafe/index.html'); + looksLike(body5, images.prerender.htmlSafe); + + const head1 = await getHead(dir); + expect(head1).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.home) + ) + ); + + const head2 = await getHead(dir, 'route66/index.html'); + expect(head2).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.route66) + ) + ); + + const head3 = await getHead(dir, 'custom/index.html'); + expect(head3).toEqual( + expect.stringMatching( + getRegExpFromMarkup(images.prerender.heads.custom) + ) + ); + }); + }); + }); }); diff --git a/packages/cli/tests/create.test.js b/packages/cli/tests/create.test.js index 0c13dae8c..35dcece05 100644 --- a/packages/cli/tests/create.test.js +++ b/packages/cli/tests/create.test.js @@ -1,4 +1,4 @@ -const { readFileSync } = require('fs'); +const { readFile } = require('fs').promises; const { relative, resolve } = require('path'); const { create } = require('./lib/cli'); const { expand } = require('./lib/utils'); @@ -19,7 +19,7 @@ describe('preact create', () => { let dir = await create('netlify'); const templateFilePath = resolve(__dirname, dir, 'src', 'template.html'); - const template = readFileSync(templateFilePath).toString('utf8'); + const template = await readFile(templateFilePath, 'utf8'); expect(template.includes('twitter:card')).toEqual(true); }); @@ -28,12 +28,13 @@ describe('preact create', () => { let dir = await create('simple'); const templateFilePath = resolve(__dirname, dir, 'src', 'template.html'); - const template = readFileSync(templateFilePath).toString('utf8'); + const template = await readFile(templateFilePath, 'utf8'); expect(template.includes('apple-touch-icon')).toEqual(true); }); it('should fail given an invalid name', async () => { + // @ts-ignore const exit = jest.spyOn(process, 'exit').mockImplementation(() => {}); await create('simple', '*()@!#!$-Invalid-Name'); diff --git a/packages/cli/tests/images/build.js b/packages/cli/tests/images/build.js index ab4371d7a..6dd3bc987 100644 --- a/packages/cli/tests/images/build.js +++ b/packages/cli/tests/images/build.js @@ -57,23 +57,6 @@ exports.sass = ` `; -exports.sideEffectCss = ` - - - side-effect-css<\\/title> - <meta name="viewport" content="width=device-width,initial-scale=1"> - <meta name="mobile-web-app-capable" content="yes"> - <meta name="apple-mobile-web-app-capable" content="yes"> - <link rel="apple-touch-icon" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\"> - <link rel="manifest" href="\\/manifest\\.json"> - <style>h1{background:#673ab8}<\\/style> - <link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\"> - <noscript> - <link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\"> - </noscript> -<\\/head> -`; - exports.prerender = {}; exports.prerender.heads = {}; @@ -130,10 +113,10 @@ exports.prerender.heads.custom = ` exports.preload = {}; -exports.preload.head = ` +exports.preload.true = ` <head> <meta charset=\\"utf-8\\"> - <title>preact-prerender<\\/title> + <title>preact-preload-chunks<\\/title> <meta name=\\"viewport\\" content=\\"width=device-width,initial-scale=1\\"> <meta name=\\"mobile-web-app-capable\\" content=\\"yes\\"> <meta name=\\"apple-mobile-web-app-capable\\" content=\\"yes\\"> @@ -150,6 +133,23 @@ exports.preload.head = ` </head> `; +exports.preload.false = ` +<head> + <meta charset=\\"utf-8\\"> + <title>preact-preload-chunks<\\/title> + <meta name=\\"viewport\\" content=\\"width=device-width,initial-scale=1\\"> + <meta name=\\"mobile-web-app-capable\\" content=\\"yes\\"> + <meta name=\\"apple-mobile-web-app-capable\\" content=\\"yes\\"> + <link rel=\\"apple-touch-icon\\" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\"> + <link rel=\\"manifest\\" href=\\"\\/manifest\\.json\\"> + <style>html{padding:0}<\\/style> + <link href=\\"\\/bundle\\.\\w{5}\\.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\"> + <noscript> + <link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\"> + </noscript> +</head> +`; + exports.prerender.home = ` <body> <div id="app"> @@ -200,7 +200,7 @@ exports.template = ` <html lang="en"> <head> <meta charset="utf-8"> - <title>preact-webpack + preact-custom-template @@ -308,3 +308,26 @@ exports.pushManifestAlteredFilenames = ` } } `; + +exports.publicPath = ` + + + + + preact-public-path + + + + + + + + + +

Public path test

+ + + + + +`; diff --git a/packages/cli/tests/lib/cli.js b/packages/cli/tests/lib/cli.js index 6e5b2c8a0..226e7cac8 100644 --- a/packages/cli/tests/lib/cli.js +++ b/packages/cli/tests/lib/cli.js @@ -7,10 +7,12 @@ const shell = require('shelljs'); const root = join(__dirname, '../../../..'); async function linkPackage(name, from, to) { - await symlink( - join(from, 'node_modules', name), - join(to, 'node_modules', name) - ); + try { + await symlink( + join(from, 'node_modules', name), + join(to, 'node_modules', name) + ); + } catch {} } const argv = { @@ -23,7 +25,7 @@ const argv = { }; exports.create = async function (template, name) { - let dest = tmpDir(); + let dest = await tmpDir(); name = name || `test-${template}`; await cmd.create(template, dest, { name, cwd: '.' }); @@ -42,7 +44,7 @@ exports.build = async function (cwd, options, installNodeModules = false) { } let opts = Object.assign({}, { cwd }, argv, options); - return await cmd.build(argv.src, opts); + return await cmd.build(opts.src, opts); }; exports.watch = function (cwd, port, host = '127.0.0.1') { diff --git a/packages/cli/tests/lib/output.js b/packages/cli/tests/lib/output.js index bd9c4d3ea..ef06c185b 100644 --- a/packages/cli/tests/lib/output.js +++ b/packages/cli/tests/lib/output.js @@ -1,4 +1,4 @@ -const { existsSync, mkdirSync } = require('fs'); +const { mkdir } = require('fs').promises; const copy = require('ncp'); const { resolve } = require('path'); const { promisify } = require('util'); @@ -6,20 +6,18 @@ const { promisify } = require('util'); const output = resolve(__dirname, '../output'); const subjects = resolve(__dirname, '../subjects'); -function tmpDir() { +async function tmpDir() { let str = Math.random() .toString(36) .replace(/[^a-z]+/g, '') .substr(0, 12); - if (!existsSync(output)) { - mkdirSync(output, { recursive: true }); - } + await mkdir(output, { recursive: true }); return resolve(output, str); } async function subject(name) { let src = resolve(subjects, name); - let dest = tmpDir(); + let dest = await tmpDir(); await promisify(copy)(src, dest); return dest; } diff --git a/packages/cli/tests/subjects/css-auto-modules/components/index.js b/packages/cli/tests/subjects/css-auto-modules/components/index.js new file mode 100644 index 000000000..5a0b70c6f --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/components/index.js @@ -0,0 +1,4 @@ +import { h } from 'preact'; +import styles from './style.css'; + +export default () =>

This is a fancy component!

; diff --git a/packages/cli/tests/subjects/css-auto-modules/components/style.css b/packages/cli/tests/subjects/css-auto-modules/components/style.css new file mode 100644 index 000000000..c275a6d60 --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/components/style.css @@ -0,0 +1,3 @@ +.text { + color: tan; +} diff --git a/packages/cli/tests/subjects/css-auto-modules/global.css b/packages/cli/tests/subjects/css-auto-modules/global.css new file mode 100644 index 000000000..818d40628 --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/global.css @@ -0,0 +1,3 @@ +h1 { + color: red; +} diff --git a/packages/cli/tests/subjects/css-auto-modules/index.js b/packages/cli/tests/subjects/css-auto-modules/index.js new file mode 100644 index 000000000..70410436c --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/index.js @@ -0,0 +1,14 @@ +import { h } from 'preact'; +import Component from './components'; +import Route from './routes'; +import './global.css'; + +export default () => { + return ( +
+

This is an app with some fancy styles!

+ + +
+ ); +}; diff --git a/packages/cli/tests/subjects/css-auto-modules/package.json b/packages/cli/tests/subjects/css-auto-modules/package.json new file mode 100644 index 000000000..5fe5d2619 --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-auto-css-modules" +} diff --git a/packages/cli/tests/subjects/css-auto-modules/routes/index.js b/packages/cli/tests/subjects/css-auto-modules/routes/index.js new file mode 100644 index 000000000..32c34e32d --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/routes/index.js @@ -0,0 +1,4 @@ +import { h } from 'preact'; +import styles from './style.css'; + +export default () =>

This is a fancy route!

; diff --git a/packages/cli/tests/subjects/css-auto-modules/routes/style.css b/packages/cli/tests/subjects/css-auto-modules/routes/style.css new file mode 100644 index 000000000..65c9e2935 --- /dev/null +++ b/packages/cli/tests/subjects/css-auto-modules/routes/style.css @@ -0,0 +1,3 @@ +.text { + color: red; +} diff --git a/packages/cli/tests/subjects/css-imports/index.js b/packages/cli/tests/subjects/css-imports/index.js new file mode 100644 index 000000000..2454b6160 --- /dev/null +++ b/packages/cli/tests/subjects/css-imports/index.js @@ -0,0 +1,2 @@ +import './styles/a.css'; +import './style.css'; diff --git a/packages/cli/tests/subjects/css-imports/package.json b/packages/cli/tests/subjects/css-imports/package.json new file mode 100644 index 000000000..6ccd93518 --- /dev/null +++ b/packages/cli/tests/subjects/css-imports/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-css-imports" +} diff --git a/packages/cli/tests/subjects/css-imports/style.css b/packages/cli/tests/subjects/css-imports/style.css new file mode 100644 index 000000000..f11fea93a --- /dev/null +++ b/packages/cli/tests/subjects/css-imports/style.css @@ -0,0 +1,5 @@ +@import '~fake-module/style.css'; + +h1 { + background: peachpuff; +} diff --git a/packages/cli/tests/subjects/css-imports/styles/a.css b/packages/cli/tests/subjects/css-imports/styles/a.css new file mode 100644 index 000000000..538ddb935 --- /dev/null +++ b/packages/cli/tests/subjects/css-imports/styles/a.css @@ -0,0 +1,5 @@ +@import 'b.css'; + +body { + background: url('./img.jpg'); +} diff --git a/packages/cli/tests/subjects/css-imports/styles/b.css b/packages/cli/tests/subjects/css-imports/styles/b.css new file mode 100644 index 000000000..b268c778e --- /dev/null +++ b/packages/cli/tests/subjects/css-imports/styles/b.css @@ -0,0 +1,3 @@ +h1 { + color: #f00; +} diff --git a/packages/cli/tests/subjects/css-imports/styles/img.jpg b/packages/cli/tests/subjects/css-imports/styles/img.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9d59acf06b03a15bdaf072d32d6a3820f762e8e1 GIT binary patch literal 56080 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 LKJ5$m`=kHaDgJ2f literal 0 HcmV?d00001 diff --git a/packages/cli/tests/subjects/css-inline/index.js b/packages/cli/tests/subjects/css-inline/index.js new file mode 100644 index 000000000..581bd47fe --- /dev/null +++ b/packages/cli/tests/subjects/css-inline/index.js @@ -0,0 +1,5 @@ +import { h } from 'preact'; + +import './style.css'; + +export default () =>

Test CSS inlining

; diff --git a/packages/cli/tests/subjects/css-inline/package.json b/packages/cli/tests/subjects/css-inline/package.json new file mode 100644 index 000000000..a1b73aea6 --- /dev/null +++ b/packages/cli/tests/subjects/css-inline/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-css-inline" +} diff --git a/packages/cli/tests/subjects/css-inline/style.css b/packages/cli/tests/subjects/css-inline/style.css new file mode 100644 index 000000000..13bed0ddc --- /dev/null +++ b/packages/cli/tests/subjects/css-inline/style.css @@ -0,0 +1,7 @@ +h1 { + color: red; +} + +div { + background: tan; +} diff --git a/packages/cli/tests/subjects/sass/components/app/index.js b/packages/cli/tests/subjects/css-sass/components/app/index.js similarity index 100% rename from packages/cli/tests/subjects/sass/components/app/index.js rename to packages/cli/tests/subjects/css-sass/components/app/index.js diff --git a/packages/cli/tests/subjects/sass/components/app/style.scss b/packages/cli/tests/subjects/css-sass/components/app/style.scss similarity index 100% rename from packages/cli/tests/subjects/sass/components/app/style.scss rename to packages/cli/tests/subjects/css-sass/components/app/style.scss diff --git a/packages/cli/tests/subjects/sass/index.js b/packages/cli/tests/subjects/css-sass/index.js similarity index 100% rename from packages/cli/tests/subjects/sass/index.js rename to packages/cli/tests/subjects/css-sass/index.js diff --git a/packages/cli/tests/subjects/css-sass/package.json b/packages/cli/tests/subjects/css-sass/package.json new file mode 100644 index 000000000..219a2cca7 --- /dev/null +++ b/packages/cli/tests/subjects/css-sass/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-css-sass" +} diff --git a/packages/cli/tests/subjects/css-side-effect/index.js b/packages/cli/tests/subjects/css-side-effect/index.js new file mode 100644 index 000000000..aa3357bf6 --- /dev/null +++ b/packages/cli/tests/subjects/css-side-effect/index.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/packages/cli/tests/subjects/side-effect-css/package.json b/packages/cli/tests/subjects/css-side-effect/package.json similarity index 51% rename from packages/cli/tests/subjects/side-effect-css/package.json rename to packages/cli/tests/subjects/css-side-effect/package.json index 54dee66f7..a66e868f1 100644 --- a/packages/cli/tests/subjects/side-effect-css/package.json +++ b/packages/cli/tests/subjects/css-side-effect/package.json @@ -1,5 +1,5 @@ { "private": true, - "name": "side-effect-css", + "name": "preact-css-side-effect-import", "sideEffects": false } diff --git a/packages/cli/tests/subjects/side-effect-css/style.css b/packages/cli/tests/subjects/css-side-effect/style.css similarity index 100% rename from packages/cli/tests/subjects/side-effect-css/style.css rename to packages/cli/tests/subjects/css-side-effect/style.css diff --git a/packages/cli/tests/subjects/custom-babelrc/package.json b/packages/cli/tests/subjects/custom-babelrc/package.json index babdc8863..69b15618c 100644 --- a/packages/cli/tests/subjects/custom-babelrc/package.json +++ b/packages/cli/tests/subjects/custom-babelrc/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-babelrc" + "name": "preact-custom-babelrc" } diff --git a/packages/cli/tests/subjects/custom-template/package.json b/packages/cli/tests/subjects/custom-template/package.json index 94671fbec..3f0525704 100644 --- a/packages/cli/tests/subjects/custom-template/package.json +++ b/packages/cli/tests/subjects/custom-template/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-webpack" + "name": "preact-custom-template" } diff --git a/packages/cli/tests/subjects/custom-webpack/package.json b/packages/cli/tests/subjects/custom-webpack/package.json index 94671fbec..f765efc28 100644 --- a/packages/cli/tests/subjects/custom-webpack/package.json +++ b/packages/cli/tests/subjects/custom-webpack/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-webpack" + "name": "preact-custom-webpack" } diff --git a/packages/cli/tests/subjects/minimal/index.js b/packages/cli/tests/subjects/minimal/index.js new file mode 100644 index 000000000..31aba19f0 --- /dev/null +++ b/packages/cli/tests/subjects/minimal/index.js @@ -0,0 +1,4 @@ +import { h } from 'preact'; +import './style.css'; + +export default () =>

Minimal App

; diff --git a/packages/cli/tests/subjects/minimal/package.json b/packages/cli/tests/subjects/minimal/package.json new file mode 100644 index 000000000..b40c254dc --- /dev/null +++ b/packages/cli/tests/subjects/minimal/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-minimal" +} diff --git a/packages/cli/tests/subjects/minimal/style.css b/packages/cli/tests/subjects/minimal/style.css new file mode 100644 index 000000000..818d40628 --- /dev/null +++ b/packages/cli/tests/subjects/minimal/style.css @@ -0,0 +1,3 @@ +h1 { + color: red; +} diff --git a/packages/cli/tests/subjects/multiple-prerendering-with-provider/package.json b/packages/cli/tests/subjects/multiple-prerendering-with-provider/package.json index 8f8310dad..65d8c9c55 100644 --- a/packages/cli/tests/subjects/multiple-prerendering-with-provider/package.json +++ b/packages/cli/tests/subjects/multiple-prerendering-with-provider/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-prerender" + "name": "preact-multiple-prerender-with-provider" } diff --git a/packages/cli/tests/subjects/multiple-prerendering/package.json b/packages/cli/tests/subjects/multiple-prerendering/package.json index 8f8310dad..37da750d7 100644 --- a/packages/cli/tests/subjects/multiple-prerendering/package.json +++ b/packages/cli/tests/subjects/multiple-prerendering/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-prerender" + "name": "preact-multiple-prerender" } diff --git a/packages/cli/tests/subjects/preload-chunks/package.json b/packages/cli/tests/subjects/preload-chunks/package.json index 8f8310dad..e877bc349 100644 --- a/packages/cli/tests/subjects/preload-chunks/package.json +++ b/packages/cli/tests/subjects/preload-chunks/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-prerender" + "name": "preact-preload-chunks" } diff --git a/packages/cli/tests/subjects/prerendering-hydration/package.json b/packages/cli/tests/subjects/prerendering-hydration/package.json index babdc8863..7a6401ba5 100644 --- a/packages/cli/tests/subjects/prerendering-hydration/package.json +++ b/packages/cli/tests/subjects/prerendering-hydration/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-babelrc" + "name": "preact-prerendering-hydration" } diff --git a/packages/cli/tests/subjects/progressive-hydration-preact8/package.json b/packages/cli/tests/subjects/progressive-hydration-preact8/package.json index f5ced7f6d..ba6ec7590 100644 --- a/packages/cli/tests/subjects/progressive-hydration-preact8/package.json +++ b/packages/cli/tests/subjects/progressive-hydration-preact8/package.json @@ -1,6 +1,6 @@ { "private": true, - "name": "preact-prerender", + "name": "preact-prerendering-hydration-preact8", "dependencies": { "preact": "8.5.3", "preact-render-to-string": "4.1.0" diff --git a/packages/cli/tests/subjects/public-path/index.js b/packages/cli/tests/subjects/public-path/index.js new file mode 100644 index 000000000..7152cbbe1 --- /dev/null +++ b/packages/cli/tests/subjects/public-path/index.js @@ -0,0 +1,4 @@ +import { h } from 'preact'; +import './style.css'; + +export default () =>

Public path test

; diff --git a/packages/cli/tests/subjects/public-path/package.json b/packages/cli/tests/subjects/public-path/package.json new file mode 100644 index 000000000..e87954cc2 --- /dev/null +++ b/packages/cli/tests/subjects/public-path/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "name": "preact-public-path" +} diff --git a/packages/cli/tests/subjects/public-path/preact.config.js b/packages/cli/tests/subjects/public-path/preact.config.js new file mode 100644 index 000000000..e882c91b2 --- /dev/null +++ b/packages/cli/tests/subjects/public-path/preact.config.js @@ -0,0 +1,3 @@ +module.exports = function (config) { + config.output.publicPath = '/example-path/'; +}; diff --git a/packages/cli/tests/subjects/public-path/style.css b/packages/cli/tests/subjects/public-path/style.css new file mode 100644 index 000000000..e69de29bb diff --git a/packages/cli/tests/subjects/sass/package.json b/packages/cli/tests/subjects/sass/package.json deleted file mode 100644 index 9d0b0baa8..000000000 --- a/packages/cli/tests/subjects/sass/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "name": "preact-sass" -} diff --git a/packages/cli/tests/subjects/side-effect-css/index.js b/packages/cli/tests/subjects/side-effect-css/index.js deleted file mode 100644 index fd48dbdf4..000000000 --- a/packages/cli/tests/subjects/side-effect-css/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { h } from 'preact'; -import './style.css'; - -export default () => { - return

SideEffect CSS test

; -}; diff --git a/packages/cli/tests/subjects/static-root/package.json b/packages/cli/tests/subjects/static-root/package.json index 2a79fab6c..de041c7eb 100644 --- a/packages/cli/tests/subjects/static-root/package.json +++ b/packages/cli/tests/subjects/static-root/package.json @@ -1,4 +1,4 @@ { "private": true, - "name": "preact-prerender" + "name": "preact-static-root" }