From 079aaf124f239aafe37615a458f9d9b21d24a101 Mon Sep 17 00:00:00 2001 From: Drew Powers Date: Thu, 23 Sep 2021 12:08:46 -0600 Subject: [PATCH 1/8] Try mocha/chai test runners --- package.json | 2 - packages/astro/package.json | 8 +- packages/astro/test/astro-assets.test.js | 11 +- packages/astro/test/astro-attrs.test.js | 29 +- packages/astro/test/astro-basic.test.js | 67 +- packages/astro/test/astro-children.test.js | 41 +- packages/astro/test/astro-client-only.test.js | 13 +- .../astro/test/astro-component-code.test.js | 49 +- packages/astro/test/astro-components.test.js | 28 +- .../astro/test/astro-css-bundling.test.js | 24 +- packages/astro/test/astro-doctype.test.js | 41 +- packages/astro/test/astro-dynamic.test.js | 26 +- packages/astro/test/astro-expr.test.js | 58 +- .../astro/test/astro-external-files.test.js | 10 +- packages/astro/test/astro-fallback.test.js | 7 +- .../astro/test/astro-get-static-paths.test.js | 10 +- packages/astro/test/astro-global.test.js | 32 +- .../astro/test/astro-markdown-plugins.test.js | 14 +- packages/astro/test/astro-markdown.test.js | 86 +- .../astro/test/astro-pageDirectoryUrl.test.js | 11 +- packages/astro/test/astro-pages.test.js | 7 +- packages/astro/test/astro-pagination.test.js | 22 +- packages/astro/test/astro-public.test.js | 11 +- packages/astro/test/astro-rss.test.js | 8 +- packages/astro/test/astro-scripts.test.js | 32 +- packages/astro/test/astro-sitemap.test.js | 10 +- packages/astro/test/astro-slots.test.js | 80 +- packages/astro/test/astro-styles-ssr.test.js | 44 +- packages/astro/test/builtins.test.js | 18 +- packages/astro/test/config-validate.test.js | 21 +- packages/astro/test/config.test.js | 21 +- packages/astro/test/custom-elements.test.js | 54 +- packages/astro/test/fetch.test.js | 10 +- packages/astro/test/lit-element.test.js | 20 +- packages/astro/test/markdown.test.js | 18 +- packages/astro/test/preact-component.test.js | 36 +- packages/astro/test/react-component.test.js | 42 +- packages/astro/test/route-manifest.test.js | 45 +- packages/astro/test/vue-component.test.js | 13 +- yarn.lock | 1590 +++-------------- 40 files changed, 798 insertions(+), 1871 deletions(-) diff --git a/package.json b/package.json index ba5cf0fbf056..4be4b4610289 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "devDependencies": { "@changesets/cli": "^2.16.0", "@octokit/action": "^3.15.4", - "@types/jest": "^27.0.2", "@typescript-eslint/eslint-plugin": "^4.31.2", "@typescript-eslint/parser": "^4.31.2", "del": "^6.0.0", @@ -53,7 +52,6 @@ "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "execa": "^5.0.0", - "jest": "^27.2.1", "lerna": "^4.0.0", "prettier": "^2.4.1", "tiny-glob": "^0.2.8", diff --git a/packages/astro/package.json b/packages/astro/package.json index f37fee7e8061..7a773a7c947f 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -36,7 +36,7 @@ "dev": "astro-scripts dev \"src/**/*.ts\"", "postbuild": "astro-scripts copy \"src/**/*.astro\"", "benchmark": "node test/benchmark/dev.bench.js && node test/benchmark/build.bench.js", - "test": "NODE_OPTIONS=--experimental-vm-modules jest" + "test": "mocha --timeout 15000" }, "dependencies": { "@astrojs/compiler": "^0.1.0-canary.46", @@ -79,12 +79,16 @@ }, "devDependencies": { "@types/babel__core": "^7.1.15", + "@types/chai": "^4.2.22", "@types/connect": "^3.4.35", "@types/mime": "^2.0.3", + "@types/mocha": "^9.0.0", "@types/node-fetch": "^2.5.12", "@types/send": "^0.17.1", "@types/yargs-parser": "^20.2.1", - "cheerio": "^1.0.0-rc.10" + "chai": "^4.3.4", + "cheerio": "^1.0.0-rc.10", + "mocha": "^9.1.1" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0", diff --git a/packages/astro/test/astro-assets.test.js b/packages/astro/test/astro-assets.test.js index 0e8d52e19938..4981d75cc9b6 100644 --- a/packages/astro/test/astro-assets.test.js +++ b/packages/astro/test/astro-assets.test.js @@ -1,29 +1,30 @@ /** * UNCOMMENT: add support for automatic and srcset in build +import { expect } from 'chai'; import { loadFixture } from './test-utils'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-assets/' }); await fixture.build(); }); // TODO: add automatic asset bundling describe('Assets', () => { - test('built the base image', async () => { + it('built the base image', async () => { await fixture.readFile('/images/twitter.png'); }); - test('built the 2x image', async () => { + it('built the 2x image', async () => { await fixture.readFile('/images/twitter@2x.png'); }); - test('built the 3x image', async () => { + it('built the 3x image', async () => { await fixture.readFile('/images/twitter@3x.png'); }); }); */ -test.skip('is skipped', () => {}); +it.skip('is skipped', () => {}); diff --git a/packages/astro/test/astro-attrs.test.js b/packages/astro/test/astro-attrs.test.js index 4052a3b17e0b..29b31d8c640a 100644 --- a/packages/astro/test/astro-attrs.test.js +++ b/packages/astro/test/astro-attrs.test.js @@ -1,15 +1,16 @@ +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-attrs/' }); await fixture.build(); }); -describe('Attributes', () => { - test('Passes attributes to elements as expected', async () => { +describe('Attributes', async () => { + it('Passes attributes to elements as expected', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); @@ -25,32 +26,32 @@ describe('Attributes', () => { for (const [k, v] of Object.entries(attrs)) { const attr = $(`#${k}`).attr('attr'); - expect(attr).toBe(v); + expect(attr).to.equal(v); } }); - test('Passes boolean attributes to components as expected', async () => { + it('Passes boolean attributes to components as expected', async () => { const html = await fixture.readFile('/component/index.html'); const $ = cheerio.load(html); - expect($('#true').attr('attr')).toBe('attr-true'); - expect($('#true').attr('type')).toBe('boolean'); - expect($('#false').attr('attr')).toBe('attr-false'); - expect($('#false').attr('type')).toBe('boolean'); + expect($('#true').attr('attr')).to.equal('attr-true'); + expect($('#true').attr('type')).to.equal('boolean'); + expect($('#false').attr('attr')).to.equal('attr-false'); + expect($('#false').attr('type')).to.equal('boolean'); }); - test('Passes namespaced attributes as expected', async () => { + it('Passes namespaced attributes as expected', async () => { const html = await fixture.readFile('/namespaced/index.html'); const $ = cheerio.load(html); - expect($('div').attr('xmlns:happy')).toBe('https://example.com/schemas/happy'); - expect($('img').attr('happy:smile')).toBe('sweet'); + expect($('div').attr('xmlns:happy')).to.equal('https://example.com/schemas/happy'); + expect($('img').attr('happy:smile')).to.equal('sweet'); }); - test('Passes namespaced attributes to components as expected', async () => { + it('Passes namespaced attributes to components as expected', async () => { const html = await fixture.readFile('/namespaced-component/index.html'); const $ = cheerio.load(html); - expect($('span').attr('on:click')).toEqual('(event) => console.log(event)'); + expect($('span').attr('on:click')).to.deep.equal('(event) => console.log(event)'); }); }); diff --git a/packages/astro/test/astro-basic.test.js b/packages/astro/test/astro-basic.test.js index 1b38a48d54fe..b678fddcd7a0 100644 --- a/packages/astro/test/astro-basic.test.js +++ b/packages/astro/test/astro-basic.test.js @@ -1,10 +1,11 @@ +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; let previewServer; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-basic/' }); await fixture.build(); previewServer = await fixture.preview(); @@ -12,85 +13,85 @@ beforeAll(async () => { describe('Astro basics', () => { describe('build', () => { - test('Can load page', async () => { + it('Can load page', async () => { const html = await fixture.readFile(`/index.html`); const $ = cheerio.load(html); - expect($('h1').text()).toBe('Hello world!'); + expect($('h1').text()).to.equal('Hello world!'); }); - test('Correctly serializes boolean attributes', async () => { + it('Correctly serializes boolean attributes', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); - expect($('h1').attr('data-something')).toBe(''); - expect($('h2').attr('not-data-ok')).toBe(''); + expect($('h1').attr('data-something')).to.equal(''); + expect($('h2').attr('not-data-ok')).to.equal(''); }); - test('Selector with an empty body', async () => { + it('Selector with an empty body', async () => { const html = await fixture.readFile('/empty-class/index.html'); const $ = cheerio.load(html); - expect($('.author')).toHaveLength(1); + expect($('.author')).to.have.lengthOf(1); }); - test('Allows forward-slashes in mustache tags (#407)', async () => { + it('Allows forward-slashes in mustache tags (#407)', async () => { const html = await fixture.readFile('/forward-slash/index.html'); const $ = cheerio.load(html); - expect($('a[href="/post/one"]')).toHaveLength(1); - expect($('a[href="/post/two"]')).toHaveLength(1); - expect($('a[href="/post/three"]')).toHaveLength(1); + expect($('a[href="/post/one"]')).to.have.lengthOf(1); + expect($('a[href="/post/two"]')).to.have.lengthOf(1); + expect($('a[href="/post/three"]')).to.have.lengthOf(1); }); - test('Allows spread attributes (#521)', async () => { + it('Allows spread attributes (#521)', async () => { const html = await fixture.readFile('/spread/index.html'); const $ = cheerio.load(html); - expect($('#spread-leading')).toHaveLength(1); - expect($('#spread-leading').attr('a')).toBe('0'); - expect($('#spread-leading').attr('b')).toBe('1'); - expect($('#spread-leading').attr('c')).toBe('2'); + expect($('#spread-leading')).to.have.lengthOf(1); + expect($('#spread-leading').attr('a')).to.equal('0'); + expect($('#spread-leading').attr('b')).to.equal('1'); + expect($('#spread-leading').attr('c')).to.equal('2'); - expect($('#spread-trailing')).toHaveLength(1); - expect($('#spread-trailing').attr('a')).toBe('0'); - expect($('#spread-trailing').attr('b')).toBe('1'); - expect($('#spread-trailing').attr('c')).toBe('2'); + expect($('#spread-trailing')).to.have.lengthOf(1); + expect($('#spread-trailing').attr('a')).to.equal('0'); + expect($('#spread-trailing').attr('b')).to.equal('1'); + expect($('#spread-trailing').attr('c')).to.equal('2'); }); - test('Allows spread attributes with TypeScript (#521)', async () => { + it('Allows spread attributes with TypeScript (#521)', async () => { const html = await fixture.readFile('/spread/index.html'); const $ = cheerio.load(html); - expect($('#spread-ts')).toHaveLength(1); - expect($('#spread-ts').attr('a')).toBe('0'); - expect($('#spread-ts').attr('b')).toBe('1'); - expect($('#spread-ts').attr('c')).toBe('2'); + expect($('#spread-ts')).to.have.lengthOf(1); + expect($('#spread-ts').attr('a')).to.equal('0'); + expect($('#spread-ts').attr('b')).to.equal('1'); + expect($('#spread-ts').attr('c')).to.equal('2'); }); - test('Allows using the Fragment element to be used', async () => { + it('Allows using the Fragment element to be used', async () => { const html = await fixture.readFile('/fragment/index.html'); const $ = cheerio.load(html); // will be 1 if element rendered correctly - expect($('#one')).toHaveLength(1); + expect($('#one')).to.have.lengthOf(1); }); }); describe('preview', () => { - test('returns 200 for valid URLs', async () => { + it('returns 200 for valid URLs', async () => { const result = await fixture.fetch('/'); - expect(result.status).toBe(200); + expect(result.status).to.equal(200); }); - test('returns 404 for invalid URLs', async () => { + it('returns 404 for invalid URLs', async () => { const result = await fixture.fetch('/bad-url'); - expect(result.status).toBe(404); + expect(result.status).to.equal(404); }); }); }); // important: close preview server (free up port and connection) -afterAll(async () => { +after(async () => { if (previewServer) await previewServer.stop(); }); diff --git a/packages/astro/test/astro-children.test.js b/packages/astro/test/astro-children.test.js index f624b1b61159..9bb18b0fcdd0 100644 --- a/packages/astro/test/astro-children.test.js +++ b/packages/astro/test/astro-children.test.js @@ -1,12 +1,13 @@ /** * UNCOMMENT when Component slots lands in new compiler +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-children/', renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-vue', '@astrojs/renderer-svelte'], @@ -16,63 +17,63 @@ beforeAll(async () => { // TODO: waiting on Component slots describe('Component children', () => { - test('Passes string children to framework components', async () => { + it('Passes string children to framework components', async () => { const html = await fixture.readFile('/strings/index.html'); const $ = cheerio.load(html); // test 1: Can pass text to Preact components const $preact = $('#preact'); - expect($preact.text().trim()).toBe('Hello world'); + expect($preact.text().trim()).to.equal('Hello world'); // test 2: Can pass text to Vue components const $vue = $('#vue'); - expect($vue.text().trim()).toBe('Hello world'); + expect($vue.text().trim()).to.equal('Hello world'); // test 3: Can pass text to Svelte components const $svelte = $('#svelte'); - expect($svelte.text().trim()).toBe('Hello world'); + expect($svelte.text().trim()).to.equal('Hello world'); }); - test('Passes markup children to framework components', async () => { + it('Passes markup children to framework components', async () => { const html = await fixture.readFile('/markup/index.html'); const $ = cheerio.load(html); // test 1: Can pass markup to Preact components const $preact = $('#preact h1'); - expect($preact.text().trim()).toBe('Hello world'); + expect($preact.text().trim()).to.equal('Hello world'); // test 2: Can pass markup to Vue components const $vue = $('#vue h1'); - expect($vue.text().trim()).toBe('Hello world'); + expect($vue.text().trim()).to.equal('Hello world'); // test 3: Can pass markup to Svelte components const $svelte = $('#svelte h1'); - expect($svelte.text().trim()).toBe('Hello world'); + expect($svelte.text().trim()).to.equal('Hello world'); }); - test('Passes multiple children to framework components', async () => { + it('Passes multiple children to framework components', async () => { const html = await fixture.readFile('/multiple/index.html'); const $ = cheerio.load(html); // test 1: Can pass multiple children to Preact components const $preact = $('#preact'); - expect($preact.children()).toHaveLength(2); - expect($preact.children(':first-child').text().trim()).toBe('Hello world'); - expect($preact.children(':last-child').text().trim()).toBe('Goodbye world'); + expect($preact.children()).to.have.lengthOf(2); + expect($preact.children(':first-child').text().trim()).to.equal('Hello world'); + expect($preact.children(':last-child').text().trim()).to.equal('Goodbye world'); // test 2: Can pass multiple children to Vue components const $vue = $('#vue'); - expect($vue.children()).toHaveLength(2); - expect($vue.children(':first-child').text().trim()).toBe('Hello world'); - expect($vue.children(':last-child').text().trim()).toBe('Goodbye world'); + expect($vue.children()).to.have.lengthOf(2); + expect($vue.children(':first-child').text().trim()).to.equal('Hello world'); + expect($vue.children(':last-child').text().trim()).to.equal('Goodbye world'); // test 3: Can pass multiple children to Svelte components const $svelte = $('#svelte'); - expect($svelte.children()).toHaveLength(2); - expect($svelte.children(':first-child').text().trim()).toBe('Hello world'); - expect($svelte.children(':last-child').text().trim()).toBe('Goodbye world'); + expect($svelte.children()).to.have.lengthOf(2); + expect($svelte.children(':first-child').text().trim()).to.equal('Hello world'); + expect($svelte.children(':last-child').text().trim()).to.equal('Goodbye world'); }); }); */ -test.skip('is skipped', () => {}); +it.skip('is skipped', () => {}); diff --git a/packages/astro/test/astro-client-only.test.js b/packages/astro/test/astro-client-only.test.js index e1ebe836c3ff..6dfcb8d0a843 100644 --- a/packages/astro/test/astro-client-only.test.js +++ b/packages/astro/test/astro-client-only.test.js @@ -1,23 +1,24 @@ /** * UNCOMMENT: when "window is not defined" error fixed in Vite +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-client-only/' }); await fixture.build(); }); // TODO: fix "window is not defined" error in Vite describe('Client only components', () => { - test.skip('Loads pages using client:only hydrator', async () => { + it('Loads pages using client:only hydrator', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); // test 1: is empty - expect($('astro-root').html()).toBe(''); + expect($('astro-root').html()).to.equal(''); // test 2: svelte renderer is on the page const exp = /import\("(.+?)"\)/g; @@ -27,13 +28,13 @@ describe('Client only components', () => { svelteRenderer = match[1]; } } - expect(svelteRenderer).toBeTruthy(); + expect(svelteRenderer).to.be.ok; // test 3: can load svelte renderer // result = await fixture.fetch(svelteRenderer); - // expect(result.status).toBe(200); + // expect(result.status).to.equal(200); }); }); */ -test.skip('is skipped', () => {}); +it.skip('is skipped', () => {}); diff --git a/packages/astro/test/astro-component-code.test.js b/packages/astro/test/astro-component-code.test.js index 678c16349766..e925e9299eb9 100644 --- a/packages/astro/test/astro-component-code.test.js +++ b/packages/astro/test/astro-component-code.test.js @@ -1,79 +1,80 @@ /** * UNCOMMENT: fix top-level expressions in components +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-component-code/' }); await fixture.build(); }); describe(' { - test(' without lang or theme', async () => { + it(' without lang or theme', async () => { let html = await fixture.readFile('/no-lang/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); - expect($('pre').attr('style')).toBe('background-color: #0d1117; overflow-x: auto;', 'applies default and overflow'); - expect($('pre > code')).toHaveLength(1); + expect($('pre')).to.have.lengthOf(1); + expect($('pre').attr('style')).to.equal('background-color: #0d1117; overflow-x: auto;', 'applies default and overflow'); + expect($('pre > code')).to.have.lengthOf(1); // test: contains some generated spans expect($('pre > code span').length).toBeGreaterThan(1); }); - test('', async () => { + it('', async () => { let html = await fixture.readFile('/basic/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); + expect($('pre')).to.have.lengthOf(1); expect($('pre').attr('class'), 'astro-code'); - expect($('pre > code')).toHaveLength(1); + expect($('pre > code')).to.have.lengthOf(1); // test: contains many generated spans expect($('pre > code span').length).toBeGreaterThanOrEqual(6); }); - test('', async () => { + it('', async () => { let html = await fixture.readFile('/custom-theme/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); - expect($('pre').attr('class')).toBe('astro-code'); - expect($('pre').attr('style')).toBe('background-color: #2e3440ff; overflow-x: auto;', 'applies custom theme'); + expect($('pre')).to.have.lengthOf(1); + expect($('pre').attr('class')).to.equal('astro-code'); + expect($('pre').attr('style')).to.equal('background-color: #2e3440ff; overflow-x: auto;', 'applies custom theme'); }); - test('', async () => { + it('', async () => { { let html = await fixture.readFile('/wrap-true/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); + expect($('pre')).to.have.lengthOf(1); // test: applies wrap overflow - expect($('pre').attr('style')).toBe('background-color: #0d1117; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;'); + expect($('pre').attr('style')).to.equal('background-color: #0d1117; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;'); } { let html = await fixture.readFile('/wrap-false/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); + expect($('pre')).to.have.lengthOf(1); // test: applies wrap overflow - expect($('pre').attr('style')).toBe('background-color: #0d1117; overflow-x: auto;'); + expect($('pre').attr('style')).to.equal('background-color: #0d1117; overflow-x: auto;'); } { let html = await fixture.readFile('/wrap-null/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); + expect($('pre')).to.have.lengthOf(1); // test: applies wrap overflow - expect($('pre').attr('style')).toBe('background-color: #0d1117'); + expect($('pre').attr('style')).to.equal('background-color: #0d1117'); } }); - test('', async () => { + it('', async () => { let html = await fixture.readFile('/css-theme/index.html'); const $ = cheerio.load(html); - expect($('pre')).toHaveLength(1); - expect($('pre').attr('class')).toBe('astro-code'); + expect($('pre')).to.have.lengthOf(1); + expect($('pre').attr('class')).to.equal('astro-code'); expect( $('pre, pre span') .map((i, f) => (f.attribs ? f.attribs.style : 'no style found')) .toArray() - ).toEqual([ + ).to.deep.equal([ 'background-color: var(--astro-code-color-background); overflow-x: auto;', 'color: var(--astro-code-token-constant)', 'color: var(--astro-code-token-function)', @@ -85,4 +86,4 @@ describe(' { }); */ -test.skip('is skipped', () => {}); +it.skip('is skipped', () => {}); diff --git a/packages/astro/test/astro-components.test.js b/packages/astro/test/astro-components.test.js index a9eaf8918324..f3a193ae757e 100644 --- a/packages/astro/test/astro-components.test.js +++ b/packages/astro/test/astro-components.test.js @@ -1,56 +1,56 @@ /** * UNCOMMENT: add support for functional components in frontmatter - +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-components/' }); await fixture.build(); }); // TODO: add support for functional components in frontmatter describe('Components tests', () => { - test('Astro components are able to render framework components', async () => { + it('Astro components are able to render framework components', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); // test 1: Renders Astro component const $astro = $('#astro'); - expect($astro.children()).toHaveLength(3); + expect($astro.children()).to.have.lengthOf(3); // test 2: Renders React component const $react = $('#react'); - expect($react).not.toHaveLength(0); + expect($react).not.to.have.lengthOf(0); // test 3: Renders Vue component const $vue = $('#vue'); - expect($vue).not.toHaveLength(0); + expect($vue).not.to.have.lengthOf(0); // test 4: Renders Svelte component const $svelte = $('#svelte'); - expect($svelte).not.toHaveLength(0); + expect($svelte).not.to.have.lengthOf(0); }); - test('Allows Components defined in frontmatter', async () => { + it('Allows Components defined in frontmatter', async () => { const html = await fixture.readFile('/frontmatter-component/index.html'); const $ = cheerio.load(html); - expect($('h1')).toHaveLength(1); + expect($('h1')).to.have.lengthOf(1); }); - test('Still throws an error for undefined components', async () => { + it('Still throws an error for undefined components', async () => { const result = await fixture.readFile('/undefined-component/index.html'); - expect(result.status).toBe(500); + expect(result.status).to.equal(500); }); - test('Client attrs not added', async () => { + it('Client attrs not added', async () => { const html = await fixture.readFile('/client/index.html'); - expect(html).not.toEqual(expect.stringMatching(/"client:load": true/)); + expect(html).not.to.include(`"client:load": true`); }); }); */ -test.skip('is skipped', () => {}); +it.skip('is skipped', () => {}); diff --git a/packages/astro/test/astro-css-bundling.test.js b/packages/astro/test/astro-css-bundling.test.js index ca4867ec0604..fddb258e6c8f 100644 --- a/packages/astro/test/astro-css-bundling.test.js +++ b/packages/astro/test/astro-css-bundling.test.js @@ -1,6 +1,6 @@ /** * UNCOMMENT: implement CSS bundling - +import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils'; @@ -17,13 +17,13 @@ const UNEXPECTED_CSS = ['/_astro/components/nav.css', '../css/typography.css', ' let fixture; -beforeAll(async () => { +before(async () => { fixture = await loadFixture({ projectRoot: './fixtures/astro-css-bundling/' }); await fixture.build({ mode: 'production' }); }); describe('CSS Bundling', () => { - test('Bundles CSS', async () => { + it('Bundles CSS', async () => { const builtCSS = new Set(); // for all HTML files… @@ -34,34 +34,34 @@ describe('CSS Bundling', () => { // test 1: assert new bundled CSS is present for (const href of css) { const link = $(`link[rel="stylesheet"][href^="${href}"]`); - expect(link).toHaveLength(1); + expect(link).to.have.lengthOf(1); builtCSS.add(link.attr('href')); } // test 2: assert old CSS was removed for (const href of UNEXPECTED_CSS) { const link = $(`link[rel="stylesheet"][href="${href}"]`); - expect(link).toHaveLength(0); + expect(link).to.have.lengthOf(0); } // test 3: preload tags was not removed and attributes was preserved if (filepath === '/preload/index.html') { const stylesheet = $('link[rel="stylesheet"][href^="/_astro/preload/index-"]'); const preload = $('link[rel="preload"][href^="/_astro/preload/index-"]'); - expect(stylesheet[0].attribs.media).toBe('print'); - expect(preload).toHaveLength(1); // Preload tag was removed + expect(stylesheet[0].attribs.media).to.equal('print'); + expect(preload).to.have.lengthOf(1); // Preload tag was removed } // test 4: preload tags was not removed and attributes was preserved if (filepath === '/preload-merge/index.html') { const preload = $('link[rel="preload"]'); - expect(preload).toHaveLength(1); + expect(preload).to.have.lengthOf(1); } // test 5: assert all bundled CSS was built and contains CSS for (const url of builtCSS.keys()) { const css = await context.readFile(url); - expect(css).toBeTruthy(); + expect(css).to.be.ok; } // test 6: assert ordering is preserved (typography.css before colors.css) @@ -73,11 +73,11 @@ describe('CSS Bundling', () => { // test 7: assert multiple style blocks were bundled (Nav.astro includes 2 scoped style blocks) const scopedNavStyles = [...bundledContents.matchAll('.nav.astro-')]; - expect(scopedNavStyles).toHaveLength(2); + expect(scopedNavStyles).to.have.lengthOf(2); // test 8: assert `); + const scripts = Array.from(result.scripts); + return template.replace('', styles.join('\n') + scripts.join('\n') + ''); +} + +export async function renderAstroComponent(component: InstanceType) { + let template = ''; + + for await (const value of component) { + if (value || value === 0) { + template += value; + } + } + + return template; +} + +function renderElement(name: string, { props: _props, children = '' }: { props: Record; children?: string }) { + const { hoist: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props; + if (defineVars) { + if (name === 'style') { + children = defineStyleVars(astroId, defineVars) + '\n' + children; + } + if (name === 'script') { + children = defineScriptVars(defineVars) + '\n' + children; + } + } + return `<${name}${spreadAttributes(props)}>${children}`; +} diff --git a/packages/astro/src/runtime/astro.ts b/packages/astro/src/runtime/astro.ts deleted file mode 100644 index d01716f1f692..000000000000 --- a/packages/astro/src/runtime/astro.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { AstroComponent, AstroComponentFactory } from '../internal'; - -import { spreadAttributes, defineStyleVars, defineScriptVars } from '../internal'; - -export async function renderAstroComponent(component: InstanceType) { - let template = ''; - - for await (const value of component) { - if (value || value === 0) { - template += value; - } - } - - return template; -} - -export async function renderToString(result: any, componentFactory: AstroComponentFactory, props: any, children: any) { - const Component = await componentFactory(result, props, children); - let template = await renderAstroComponent(Component); - return template; -} - -export async function renderPage(result: any, Component: AstroComponentFactory, props: any, children: any) { - const template = await renderToString(result, Component, props, children); - const styles = Array.from(result.styles).map((style) => ``); - const scripts = Array.from(result.scripts); - return template.replace('', styles.join('\n') + scripts.join('\n') + ''); -} - -function renderElement(name: string, { props: _props, children = ''}: { props: Record, children?: string }) { - const { hoist: _, "data-astro-id": astroId, "define:vars": defineVars, ...props } = _props; - if (defineVars) { - if (name === 'style') { - children = defineStyleVars(astroId, defineVars) + '\n' + children; - } - if (name === 'script') { - children = defineScriptVars(defineVars) + '\n' + children; - } - } - return `<${name}${spreadAttributes(props)}>${children}` -} diff --git a/packages/astro/src/runtime/ssr.ts b/packages/astro/src/runtime/ssr.ts index 122a299f7f5c..0f561d30edb4 100644 --- a/packages/astro/src/runtime/ssr.ts +++ b/packages/astro/src/runtime/ssr.ts @@ -9,8 +9,8 @@ import { fileURLToPath } from 'url'; import fs from 'fs'; import path from 'path'; import slash from 'slash'; -import { renderPage } from './astro.js'; import glob from 'tiny-glob'; +import { renderPage } from '../internal/index.js'; import { generatePaginateFunction } from './paginate.js'; import { getParams, validateGetStaticPathsModule, validateGetStaticPathsResult } from './routing.js'; import { parseNpmName, canonicalURL as getCanonicalURL, codeFrame } from './util.js'; From 2d80febd1c21ba6126fcd00b77d6a1a01a202d80 Mon Sep 17 00:00:00 2001 From: Drew Powers Date: Thu, 23 Sep 2021 16:07:14 -0600 Subject: [PATCH 8/8] Fix styles --- .github/workflows/ci.yml | 7 ++-- .github/workflows/release-next.yml | 6 ++- packages/astro/package.json | 8 ++-- packages/astro/src/internal/index.ts | 2 +- packages/astro/src/runtime/ssr.ts | 40 ++++++------------- packages/renderers/renderer-lit/package.json | 1 + .../renderers/renderer-preact/package.json | 1 + .../renderers/renderer-react/package.json | 1 + .../renderers/renderer-solid/package.json | 1 + .../renderers/renderer-svelte/package.json | 1 + packages/renderers/renderer-vue/package.json | 1 + yarn.lock | 36 ----------------- 12 files changed, 31 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cb74d05830a..df1ab7310fe6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,10 @@ jobs: matrix: os: [ubuntu-latest] node_version: [12, 14, 16] - include: - - os: windows-latest - node_version: 14 + # TODO: uncomment this (Vite has trouble resolving imports on Windows) + # include: + # - os: windows-latest + # node_version: 14 fail-fast: false env: LANG: en-us diff --git a/.github/workflows/release-next.yml b/.github/workflows/release-next.yml index 855788c80763..79c3b093ac25 100644 --- a/.github/workflows/release-next.yml +++ b/.github/workflows/release-next.yml @@ -18,8 +18,10 @@ jobs: run: yarn changeset version --snapshot compiler - # 2. discard examples/docs/www changes (just in case) run: git checkout -- examples/ docs/ www/ - - # 3: auth + - # 3: use compiler--next renderers (but don’t commit) + run: cd packages/astro && yarn add @astrojs/renderer-preact@next--compiler @astrojs/renderer-react@next--compiler @astrojs/renderer-svelte@next--compiler @astrojs/renderer-vue@next--compiler && cd ../.. + - # 4: auth run: echo '//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}' > ${{ github.workspace }}/.npmrc - - # 4: publish! + - # 5: publish! run: yarn release --tag next--compiler diff --git a/packages/astro/package.json b/packages/astro/package.json index 0642668c822e..eb95b2b82656 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -42,10 +42,10 @@ "dependencies": { "@astrojs/compiler": "^0.1.0-canary.46", "@astrojs/markdown-remark": "^0.3.1", - "@astrojs/renderer-preact": "0.0.0-compiler-2021821225719", - "@astrojs/renderer-react": "0.0.0-compiler-2021821225719", - "@astrojs/renderer-svelte": "0.0.0-compiler-2021821225719", - "@astrojs/renderer-vue": "0.0.0-compiler-2021821225719", + "@astrojs/renderer-preact": "^0.2.2", + "@astrojs/renderer-react": "^0.2.1", + "@astrojs/renderer-svelte": "^0.1.2", + "@astrojs/renderer-vue": "^0.1.8", "@babel/core": "^7.15.5", "@web/rollup-plugin-html": "^1.9.1", "astring": "^1.7.5", diff --git a/packages/astro/src/internal/index.ts b/packages/astro/src/internal/index.ts index b9d5ddeaadcb..067fe6c6763a 100644 --- a/packages/astro/src/internal/index.ts +++ b/packages/astro/src/internal/index.ts @@ -236,7 +236,7 @@ export async function renderToString(result: any, componentFactory: AstroCompone export async function renderPage(result: any, Component: AstroComponentFactory, props: any, children: any) { const template = await renderToString(result, Component, props, children); - const styles = Array.from(result.styles).map((style) => ``); + const styles = Array.from(result.styles).map((style: any) => renderElement('style', style)); const scripts = Array.from(result.scripts); return template.replace('', styles.join('\n') + scripts.join('\n') + ''); } diff --git a/packages/astro/src/runtime/ssr.ts b/packages/astro/src/runtime/ssr.ts index 0f561d30edb4..8b4dde7f739c 100644 --- a/packages/astro/src/runtime/ssr.ts +++ b/packages/astro/src/runtime/ssr.ts @@ -44,41 +44,25 @@ const cache = new Map(); // TODO: improve validation and error handling here. async function resolveRenderers(viteServer: ViteDevServer, ids: string[]) { - const resolve = viteServer.config.createResolver(); const renderers = await Promise.all( ids.map(async (renderer) => { if (cache.has(renderer)) return cache.get(renderer); - const resolvedRenderer: any = {}; + const resolvedRenderer: any = {}; // We can dynamically import the renderer by itself because it shouldn't have // any non-standard imports, the index is just meta info. // The other entrypoints need to be loaded through Vite. - const { default: instance } = await import(renderer); - - // This resolves the renderer's entrypoints to a final URL through Vite - const getPath = async (src: string) => { - const spec = path.posix.join(instance.name, src); - const resolved = await resolve(spec); - if (!resolved) { - throw new Error(`Unable to resolve "${spec}" to a package!`); - } - return resolved; - }; - - resolvedRenderer.name = instance.name; - if (instance.client) { - resolvedRenderer.source = await getPath(instance.client); - } - if (Array.isArray(instance.hydrationPolyfills)) { - resolvedRenderer.hydrationPolyfills = await Promise.all(instance.hydrationPolyfills.map((src: string) => getPath(src))); - } - if (Array.isArray(instance.polyfills)) { - resolvedRenderer.polyfills = await Promise.all(instance.polyfills.map((src: string) => getPath(src))); - } - - const { url } = await viteServer.moduleGraph.ensureEntryFromUrl(await getPath(instance.server)); - const { default: server } = await viteServer.ssrLoadModule(url); - resolvedRenderer.ssr = server; + const { + default: { name, client, polyfills, hydrationPolyfills, server }, + } = await import(renderer); + + resolvedRenderer.name = name; + if (client) resolvedRenderer.source = path.posix.join(renderer, client); + if (Array.isArray(hydrationPolyfills)) resolvedRenderer.hydrationPolyfills = hydrationPolyfills.map((src: string) => path.posix.join(renderer, src)); + if (Array.isArray(polyfills)) resolvedRenderer.polyfills = polyfills.map((src: string) => path.posix.join(renderer, src)); + const { url } = await viteServer.moduleGraph.ensureEntryFromUrl(path.posix.join(renderer, server)); + const { default: rendererSSR } = await viteServer.ssrLoadModule(url); + resolvedRenderer.ssr = rendererSSR; cache.set(renderer, resolvedRenderer); return resolvedRenderer; diff --git a/packages/renderers/renderer-lit/package.json b/packages/renderers/renderer-lit/package.json index 97b23af92955..05ee8c2c4f5c 100644 --- a/packages/renderers/renderer-lit/package.json +++ b/packages/renderers/renderer-lit/package.json @@ -5,6 +5,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./server.js": "./server.js", "./client-shim.js": "./client-shim.js", "./package.json": "./package.json" diff --git a/packages/renderers/renderer-preact/package.json b/packages/renderers/renderer-preact/package.json index a94857d6b36b..8edc15fcf130 100644 --- a/packages/renderers/renderer-preact/package.json +++ b/packages/renderers/renderer-preact/package.json @@ -4,6 +4,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./client": "./client.js", "./server": "./server.js", "./package.json": "./package.json" diff --git a/packages/renderers/renderer-react/package.json b/packages/renderers/renderer-react/package.json index 63ac1ab394de..cbbd52d419df 100644 --- a/packages/renderers/renderer-react/package.json +++ b/packages/renderers/renderer-react/package.json @@ -4,6 +4,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./client": "./client.js", "./server": "./server.js", "./package.json": "./package.json" diff --git a/packages/renderers/renderer-solid/package.json b/packages/renderers/renderer-solid/package.json index c607273040b8..13b987733114 100644 --- a/packages/renderers/renderer-solid/package.json +++ b/packages/renderers/renderer-solid/package.json @@ -4,6 +4,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./client": "./client.js", "./server": "./server.js", "./package.json": "./package.json" diff --git a/packages/renderers/renderer-svelte/package.json b/packages/renderers/renderer-svelte/package.json index 921df26ae9b9..6e86e80785ab 100644 --- a/packages/renderers/renderer-svelte/package.json +++ b/packages/renderers/renderer-svelte/package.json @@ -4,6 +4,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./client": "./client.js", "./server": "./server.js", "./package.json": "./package.json" diff --git a/packages/renderers/renderer-vue/package.json b/packages/renderers/renderer-vue/package.json index d0a2a5ef40c2..52d94094d91e 100644 --- a/packages/renderers/renderer-vue/package.json +++ b/packages/renderers/renderer-vue/package.json @@ -4,6 +4,7 @@ "type": "module", "exports": { ".": "./index.js", + "./*": "./*", "./client": "./client.js", "./server": "./server.js", "./package.json": "./package.json" diff --git a/yarn.lock b/yarn.lock index 79f2c8ffe97f..5ee29a175a64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -113,42 +113,6 @@ dependencies: typescript "^4.3.5" -"@astrojs/renderer-preact@0.0.0-compiler-2021821225719": - version "0.0.0-compiler-2021821225719" - resolved "https://registry.yarnpkg.com/@astrojs/renderer-preact/-/renderer-preact-0.0.0-compiler-2021821225719.tgz#d6f987ae94820220269e863967dac4203970fc48" - integrity sha512-IonFU0ATk9/jfL8P7AgGryHmEWAtirjbfUX/aQYIejOC+H+c6jD7OUIBNGi1KLo5wY9IwCQ06FK/UBOkuboPXw== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.14.5" - preact "^10.5.14" - preact-render-to-string "^5.1.19" - -"@astrojs/renderer-react@0.0.0-compiler-2021821225719": - version "0.0.0-compiler-2021821225719" - resolved "https://registry.yarnpkg.com/@astrojs/renderer-react/-/renderer-react-0.0.0-compiler-2021821225719.tgz#b0d86875b9c4fd5a7180d1c45424b69276414843" - integrity sha512-018I1M5Ea1P6/eVdW5azxTpoyjXjp9lBGCfSYTW7Zn0UIP9Ry2BgD9BH6cYvHqIK9hyI/5u7VjZttPPP0r/yLA== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.14.5" - react "^17.0.2" - react-dom "^17.0.2" - -"@astrojs/renderer-svelte@0.0.0-compiler-2021821225719": - version "0.0.0-compiler-2021821225719" - resolved "https://registry.yarnpkg.com/@astrojs/renderer-svelte/-/renderer-svelte-0.0.0-compiler-2021821225719.tgz#0f3af4c9990caf1e7e870c8e6adfeddfd5437640" - integrity sha512-1uEd8+Bo3pHkmn3gmup+HTNR4Nmuu1YH1bDQHIucq7TtiWfUK2FufR7SrlaoXT2otSB4TUwwIq1dKvhgjtUJMQ== - dependencies: - "@sveltejs/vite-plugin-svelte" "^1.0.0-next.19" - svelte "^3.42.3" - -"@astrojs/renderer-vue@0.0.0-compiler-2021821225719": - version "0.0.0-compiler-2021821225719" - resolved "https://registry.yarnpkg.com/@astrojs/renderer-vue/-/renderer-vue-0.0.0-compiler-2021821225719.tgz#56654e2f775a14d1b88a58d5b7854c780c877413" - integrity sha512-D6uQwxLtSlKjq2ql6aUkqplimb4zR3xs8kLLQMhfpn6cnXiqwzwzdRYvM8f6q05fO/lNrvDp+m0ed4jbGZKQSg== - dependencies: - "@vitejs/plugin-vue" "^1.6.0" - "@vue/compiler-sfc" "^3.2.6" - "@vue/server-renderer" "^3.2.6" - vue "^3.2.6" - "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"