From 7bdcfb750ae5e8a9e2a0ee68c7ac03b82215d08f Mon Sep 17 00:00:00 2001 From: Ming-jun Lu <40516784+mingjunlu@users.noreply.github.com> Date: Fri, 16 Feb 2024 01:58:17 +0800 Subject: chore: migrate several tests to `node:test` (#10133) * chore: migrate test files whose names start with `a` to `node:test` * update assertion * chore: remove mocha script --------- Co-authored-by: Emanuele Stoppa --- packages/astro/package.json | 2 +- packages/astro/test/api-routes.nodetest.js | 21 ++ packages/astro/test/api-routes.test.js | 20 -- packages/astro/test/astro-client-only.nodetest.js | 121 ++++++++++++ packages/astro/test/astro-client-only.test.js | 120 ------------ .../astro/test/astro-component-code.nodetest.js | 124 ++++++++++++ packages/astro/test/astro-component-code.test.js | 115 ----------- packages/astro/test/astro-cookies.nodetest.js | 144 ++++++++++++++ packages/astro/test/astro-cookies.test.js | 143 -------------- packages/astro/test/astro-css-bundling.nodetest.js | 115 +++++++++++ packages/astro/test/astro-css-bundling.test.js | 114 ----------- packages/astro/test/astro-dev-headers.nodetest.js | 40 ++++ packages/astro/test/astro-dev-headers.test.js | 39 ---- packages/astro/test/astro-directives.nodetest.js | 103 ++++++++++ packages/astro/test/astro-directives.test.js | 98 ---------- packages/astro/test/astro-doctype.nodetest.js | 76 ++++++++ packages/astro/test/astro-doctype.test.js | 74 ------- packages/astro/test/astro-dynamic.nodetest.js | 80 ++++++++ packages/astro/test/astro-dynamic.test.js | 79 -------- packages/astro/test/astro-envs.nodetest.js | 124 ++++++++++++ packages/astro/test/astro-envs.test.js | 123 ------------ packages/astro/test/astro-expr.nodetest.js | 130 +++++++++++++ packages/astro/test/astro-expr.test.js | 126 ------------ packages/astro/test/astro-fallback.nodetest.js | 21 ++ packages/astro/test/astro-fallback.test.js | 20 -- .../astro/test/astro-get-static-paths.nodetest.js | 128 +++++++++++++ packages/astro/test/astro-get-static-paths.test.js | 130 ------------- packages/astro/test/astro-global.nodetest.js | 138 +++++++++++++ packages/astro/test/astro-global.test.js | 136 ------------- packages/astro/test/astro-object-style.nodetest.js | 33 ++++ packages/astro/test/astro-object-style.test.js | 32 ---- packages/astro/test/astro-pages.nodetest.js | 63 ++++++ packages/astro/test/astro-pages.test.js | 58 ------ packages/astro/test/astro-partial-html.nodetest.js | 50 +++++ packages/astro/test/astro-partial-html.test.js | 49 ----- .../astro/test/astro-preview-headers.nodetest.js | 41 ++++ packages/astro/test/astro-preview-headers.test.js | 40 ---- packages/astro/test/astro-scripts.nodetest.js | 213 +++++++++++++++++++++ packages/astro/test/astro-scripts.test.js | 211 -------------------- packages/astro/test/astro-slots-nested.nodetest.js | 62 ++++++ packages/astro/test/astro-slots-nested.test.js | 61 ------ packages/astro/test/astro-sync.nodetest.js | 107 +++++++++++ packages/astro/test/astro-sync.test.js | 88 --------- 43 files changed, 1935 insertions(+), 1877 deletions(-) create mode 100644 packages/astro/test/api-routes.nodetest.js delete mode 100644 packages/astro/test/api-routes.test.js create mode 100644 packages/astro/test/astro-client-only.nodetest.js delete mode 100644 packages/astro/test/astro-client-only.test.js create mode 100644 packages/astro/test/astro-component-code.nodetest.js delete mode 100644 packages/astro/test/astro-component-code.test.js create mode 100644 packages/astro/test/astro-cookies.nodetest.js delete mode 100644 packages/astro/test/astro-cookies.test.js create mode 100644 packages/astro/test/astro-css-bundling.nodetest.js delete mode 100644 packages/astro/test/astro-css-bundling.test.js create mode 100644 packages/astro/test/astro-dev-headers.nodetest.js delete mode 100644 packages/astro/test/astro-dev-headers.test.js create mode 100644 packages/astro/test/astro-directives.nodetest.js delete mode 100644 packages/astro/test/astro-directives.test.js create mode 100644 packages/astro/test/astro-doctype.nodetest.js delete mode 100644 packages/astro/test/astro-doctype.test.js create mode 100644 packages/astro/test/astro-dynamic.nodetest.js delete mode 100644 packages/astro/test/astro-dynamic.test.js create mode 100644 packages/astro/test/astro-envs.nodetest.js delete mode 100644 packages/astro/test/astro-envs.test.js create mode 100644 packages/astro/test/astro-expr.nodetest.js delete mode 100644 packages/astro/test/astro-expr.test.js create mode 100644 packages/astro/test/astro-fallback.nodetest.js delete mode 100644 packages/astro/test/astro-fallback.test.js create mode 100644 packages/astro/test/astro-get-static-paths.nodetest.js delete mode 100644 packages/astro/test/astro-get-static-paths.test.js create mode 100644 packages/astro/test/astro-global.nodetest.js delete mode 100644 packages/astro/test/astro-global.test.js create mode 100644 packages/astro/test/astro-object-style.nodetest.js delete mode 100644 packages/astro/test/astro-object-style.test.js create mode 100644 packages/astro/test/astro-pages.nodetest.js delete mode 100644 packages/astro/test/astro-pages.test.js create mode 100644 packages/astro/test/astro-partial-html.nodetest.js delete mode 100644 packages/astro/test/astro-partial-html.test.js create mode 100644 packages/astro/test/astro-preview-headers.nodetest.js delete mode 100644 packages/astro/test/astro-preview-headers.test.js create mode 100644 packages/astro/test/astro-scripts.nodetest.js delete mode 100644 packages/astro/test/astro-scripts.test.js create mode 100644 packages/astro/test/astro-slots-nested.nodetest.js delete mode 100644 packages/astro/test/astro-slots-nested.test.js create mode 100644 packages/astro/test/astro-sync.nodetest.js delete mode 100644 packages/astro/test/astro-sync.test.js diff --git a/packages/astro/package.json b/packages/astro/package.json index 6fe67b2e0..2399ed3e1 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -107,7 +107,7 @@ "build:ci": "pnpm run prebuild && astro-scripts build \"src/**/*.{ts,js}\" && pnpm run postbuild", "dev": "astro-scripts dev --copy-wasm --prebuild \"src/runtime/server/astro-island.ts\" --prebuild \"src/runtime/client/{idle,load,media,only,visible}.ts\" \"src/**/*.{ts,js}\"", "postbuild": "astro-scripts copy \"src/**/*.astro\" && astro-scripts copy \"src/**/*.wasm\"", - "test": "pnpm run test:node && mocha ./test/*.test.js --exit --timeout 30000", + "test": "pnpm run test:node", "test:match": "mocha ./test/*.test.js --timeout 30000 -g", "test:e2e": "playwright test", "test:e2e:match": "playwright test -g", diff --git a/packages/astro/test/api-routes.nodetest.js b/packages/astro/test/api-routes.nodetest.js new file mode 100644 index 000000000..4e2a5c7d0 --- /dev/null +++ b/packages/astro/test/api-routes.nodetest.js @@ -0,0 +1,21 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +describe('API routes', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ root: './fixtures/api-routes/' }); + await fixture.build(); + }); + + describe('Binary data', () => { + it('can be returned from a response', async () => { + const dat = await fixture.readFile('/binary.dat', null); + assert.equal(dat.length, 1); + assert.equal(dat[0], 0xff); + }); + }); +}); diff --git a/packages/astro/test/api-routes.test.js b/packages/astro/test/api-routes.test.js deleted file mode 100644 index 278d2454e..000000000 --- a/packages/astro/test/api-routes.test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { expect } from 'chai'; -import { loadFixture } from './test-utils.js'; - -describe('API routes', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; - - before(async () => { - fixture = await loadFixture({ root: './fixtures/api-routes/' }); - await fixture.build(); - }); - - describe('Binary data', () => { - it('can be returned from a response', async () => { - const dat = await fixture.readFile('/binary.dat', null); - expect(dat.length).to.equal(1); - expect(dat[0]).to.equal(0xff); - }); - }); -}); diff --git a/packages/astro/test/astro-client-only.nodetest.js b/packages/astro/test/astro-client-only.nodetest.js new file mode 100644 index 000000000..88b762e73 --- /dev/null +++ b/packages/astro/test/astro-client-only.nodetest.js @@ -0,0 +1,121 @@ +import { load as cheerioLoad } from 'cheerio'; +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +describe('Client only components', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-client-only/', + // test suite was authored when inlineStylesheets defaulted to never + build: { inlineStylesheets: 'never' }, + }); + await fixture.build(); + }); + + it('Loads pages using client:only hydrator', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerioLoad(html); + + // test 1: is empty + assert.equal($('astro-island').html(), ''); + + // test 2: svelte renderer is on the page + assert.ok($('astro-island').attr('renderer-url')); + }); + + it('Adds the CSS to the page', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerioLoad(html); + + const stylesheets = await Promise.all( + $('link[rel=stylesheet]').map((_, el) => { + return fixture.readFile(el.attribs.href); + }) + ); + const css = stylesheets.join(''); + + // yellowgreen minified + assert.match(css, /#9acd32/, 'Svelte styles are added'); + assert.match(css, /Courier New/, 'Global styles are added'); + }); + + it('Adds the CSS to the page - standalone svelte component', async () => { + const html = await fixture.readFile('/persistent-counter-standalone/index.html'); + const $ = cheerioLoad(html); + + assert.equal($('head link[rel=stylesheet]').length, 1); + + const href = $('link[rel=stylesheet]').attr('href'); + const css = await fixture.readFile(href); + + assert.match(css, /tomato/, 'Svelte styles are added'); + }); + + it('Includes CSS from components that use CSS modules', async () => { + const html = await fixture.readFile('/css-modules/index.html'); + const $ = cheerioLoad(html); + assert.equal($('link[rel=stylesheet]').length, 1); + }); + + it('Includes CSS from package components', async () => { + const html = await fixture.readFile('/pkg/index.html'); + const $ = cheerioLoad(html); + assert.equal($('link[rel=stylesheet]').length, 1); + }); +}); + +describe('Client only components subpath', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + site: 'https://site.com', + base: '/blog', + root: './fixtures/astro-client-only/', + // test suite was authored when inlineStylesheets defaulted to never + build: { inlineStylesheets: 'never' }, + }); + await fixture.build(); + }); + + it('Loads pages using client:only hydrator', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerioLoad(html); + + // test 1: is empty + assert.equal($('astro-island').html(), ''); + + // test 2: svelte renderer is on the page + assert.ok($('astro-island').attr('renderer-url')); + }); + + it('Adds the CSS to the page', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerioLoad(html); + + const stylesheets = await Promise.all( + $('link[rel=stylesheet]').map((_, el) => { + return fixture.readFile(el.attribs.href.replace(/\/blog/, '')); + }) + ); + const css = stylesheets.join(''); + + // yellowgreen minified + assert.match(css, /#9acd32/, 'Svelte styles are added'); + assert.match(css, /Courier New/, 'Global styles are added'); + }); + + it('Adds the CSS to the page for TSX components', async () => { + const html = await fixture.readFile('/tsx-no-extension/index.html'); + const $ = cheerioLoad(html); + + const href = $('link[rel=stylesheet]').attr('href'); + const css = await fixture.readFile(href.replace(/\/blog/, '')); + + assert.match(css, /purple/, 'Global styles from tsx component are added'); + }); +}); diff --git a/packages/astro/test/astro-client-only.test.js b/packages/astro/test/astro-client-only.test.js deleted file mode 100644 index 92b1beda4..000000000 --- a/packages/astro/test/astro-client-only.test.js +++ /dev/null @@ -1,120 +0,0 @@ -import { expect } from 'chai'; -import { load as cheerioLoad } from 'cheerio'; -import { loadFixture } from './test-utils.js'; - -describe('Client only components', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; - - before(async () => { - fixture = await loadFixture({ - root: './fixtures/astro-client-only/', - // test suite was authored when inlineStylesheets defaulted to never - build: { inlineStylesheets: 'never' }, - }); - await fixture.build(); - }); - - it('Loads pages using client:only hydrator', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - // test 1: is empty - expect($('astro-island').html()).to.equal(''); - - // test 2: svelte renderer is on the page - expect($('astro-island').attr('renderer-url')).to.be.ok; - }); - - it('Adds the CSS to the page', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const stylesheets = await Promise.all( - $('link[rel=stylesheet]').map((_, el) => { - return fixture.readFile(el.attribs.href); - }) - ); - const css = stylesheets.join(''); - - // yellowgreen minified - expect(css).to.contain('#9acd32', 'Svelte styles are added'); - expect(css).to.include('Courier New', 'Global styles are added'); - }); - - it('Adds the CSS to the page - standalone svelte component', async () => { - const html = await fixture.readFile('/persistent-counter-standalone/index.html'); - const $ = cheerioLoad(html); - - expect($('head link[rel=stylesheet]')).to.have.a.lengthOf(1); - - const href = $('link[rel=stylesheet]').attr('href'); - const css = await fixture.readFile(href); - - expect(css).to.match(/tomato/, 'Svelte styles are added'); - }); - - it('Includes CSS from components that use CSS modules', async () => { - const html = await fixture.readFile('/css-modules/index.html'); - const $ = cheerioLoad(html); - expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1); - }); - - it('Includes CSS from package components', async () => { - const html = await fixture.readFile('/pkg/index.html'); - const $ = cheerioLoad(html); - expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1); - }); -}); - -describe('Client only components subpath', () => { - let fixture; - - before(async () => { - fixture = await loadFixture({ - site: 'https://site.com', - base: '/blog', - root: './fixtures/astro-client-only/', - // test suite was authored when inlineStylesheets defaulted to never - build: { inlineStylesheets: 'never' }, - }); - await fixture.build(); - }); - - it('Loads pages using client:only hydrator', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - // test 1: is empty - expect($('astro-island').html()).to.equal(''); - - // test 2: svelte renderer is on the page - expect($('astro-island').attr('renderer-url')).to.be.ok; - }); - - it('Adds the CSS to the page', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const stylesheets = await Promise.all( - $('link[rel=stylesheet]').map((_, el) => { - return fixture.readFile(el.attribs.href.replace(/\/blog/, '')); - }) - ); - const css = stylesheets.join(''); - - // yellowgreen minified - expect(css).to.contain('#9acd32', 'Svelte styles are added'); - expect(css).to.include('Courier New', 'Global styles are added'); - }); - - it('Adds the CSS to the page for TSX components', async () => { - const html = await fixture.readFile('/tsx-no-extension/index.html'); - const $ = cheerioLoad(html); - - const href = $('link[rel=stylesheet]').attr('href'); - const css = await fixture.readFile(href.replace(/\/blog/, '')); - - expect(css).to.match(/purple/, 'Global styles from tsx component are added'); - }); -}); diff --git a/packages/astro/test/astro-component-code.nodetest.js b/packages/astro/test/astro-component-code.nodetest.js new file mode 100644 index 000000000..1a3a23ea7 --- /dev/null +++ b/packages/astro/test/astro-component-code.nodetest.js @@ -0,0 +1,124 @@ +import * as cheerio from 'cheerio'; +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +describe('', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ root: './fixtures/astro-component-code/' }); + await fixture.build(); + }); + + it(' without lang or theme', async () => { + let html = await fixture.readFile('/no-lang/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + assert.equal( + $('pre').attr('style'), + 'background-color:#24292e;color:#e1e4e8; overflow-x: auto;', + 'applies default and overflow' + ); + assert.equal($('pre > code').length, 1); + + // test: contains some generated spans + assert.equal($('pre > code span').length > 1, true); + }); + + it('', async () => { + let html = await fixture.readFile('/basic/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + assert.equal($('pre').attr('class'), 'astro-code github-dark'); + assert.equal($('pre > code').length, 1); + // test: contains many generated spans + assert.equal($('pre > code span').length >= 6, true); + }); + + it('', async () => { + let html = await fixture.readFile('/custom-theme/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + assert.equal($('pre').attr('class'), 'astro-code nord'); + assert.equal( + $('pre').attr('style'), + 'background-color:#2e3440ff;color:#d8dee9ff; overflow-x: auto;', + 'applies custom theme' + ); + }); + + it('', async () => { + { + let html = await fixture.readFile('/wrap-true/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + // test: applies wrap overflow + assert.equal( + $('pre').attr('style'), + 'background-color:#24292e;color:#e1e4e8; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;' + ); + } + { + let html = await fixture.readFile('/wrap-false/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + // test: applies wrap overflow + assert.equal( + $('pre').attr('style'), + 'background-color:#24292e;color:#e1e4e8; overflow-x: auto;' + ); + } + { + let html = await fixture.readFile('/wrap-null/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + // test: applies wrap overflow + assert.equal($('pre').attr('style'), 'background-color:#24292e;color:#e1e4e8'); + } + }); + + it('', async () => { + let html = await fixture.readFile('/css-theme/index.html'); + const $ = cheerio.load(html); + assert.equal($('pre').length, 1); + assert.equal($('pre').attr('class'), 'astro-code css-variables'); + assert.deepEqual( + $('pre, pre span') + .map((i, f) => (f.attribs ? f.attribs.style : 'no style found')) + .toArray(), + [ + 'background-color:var(--astro-code-color-background);color:var(--astro-code-color-text); overflow-x: auto;', + 'color:var(--astro-code-token-constant)', + 'color:var(--astro-code-token-function)', + 'color:var(--astro-code-color-text)', + 'color:var(--astro-code-token-string-expression)', + 'color:var(--astro-code-color-text)', + ] + ); + }); + + it(' with custom theme and lang', async () => { + let html = await fixture.readFile('/imported/index.html'); + const $ = cheerio.load(html); + + assert.equal($('#theme > pre').length, 1); + assert.equal( + $('#theme > pre').attr('style'), + 'background-color:#FDFDFE;color:#4E5377; overflow-x: auto;' + ); + + assert.equal($('#lang > pre').length, 1); + assert.equal($('#lang > pre > code span').length, 3); + }); + + it(' has no pre tag', async () => { + let html = await fixture.readFile('/inline/index.html'); + const $ = cheerio.load(html); + const codeEl = $('.astro-code'); + + assert.equal(codeEl.prop('tagName'), 'CODE'); + assert.match(codeEl.attr('style'), /background-color:/); + assert.equal($('pre').length, 0); + }); +}); diff --git a/packages/astro/test/astro-component-code.test.js b/packages/astro/test/astro-component-code.test.js deleted file mode 100644 index dbca3f56d..000000000 --- a/packages/astro/test/astro-component-code.test.js +++ /dev/null @@ -1,115 +0,0 @@ -import { expect } from 'chai'; -import * as cheerio from 'cheerio'; -import { loadFixture } from './test-utils.js'; - -describe('', () => { - let fixture; - - before(async () => { - fixture = await loadFixture({ root: './fixtures/astro-component-code/' }); - await fixture.build(); - }); - - it(' without lang or theme', async () => { - let html = await fixture.readFile('/no-lang/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - expect($('pre').attr('style')).to.equal( - 'background-color:#24292e;color:#e1e4e8; overflow-x: auto;', - 'applies default and overflow' - ); - expect($('pre > code')).to.have.lengthOf(1); - - // test: contains some generated spans - expect($('pre > code span').length).to.be.greaterThan(1); - }); - - it('', async () => { - let html = await fixture.readFile('/basic/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - expect($('pre').attr('class'), 'astro-code nord'); - expect($('pre > code')).to.have.lengthOf(1); - // test: contains many generated spans - expect($('pre > code span').length).to.be.greaterThanOrEqual(6); - }); - - it('', async () => { - let html = await fixture.readFile('/custom-theme/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - expect($('pre').attr('class')).to.equal('astro-code nord'); - expect($('pre').attr('style')).to.equal( - 'background-color:#2e3440ff;color:#d8dee9ff; overflow-x: auto;', - 'applies custom theme' - ); - }); - - it('', async () => { - { - let html = await fixture.readFile('/wrap-true/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - // test: applies wrap overflow - expect($('pre').attr('style')).to.equal( - 'background-color:#24292e;color:#e1e4e8; 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')).to.have.lengthOf(1); - // test: applies wrap overflow - expect($('pre').attr('style')).to.equal( - 'background-color:#24292e;color:#e1e4e8; overflow-x: auto;' - ); - } - { - let html = await fixture.readFile('/wrap-null/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - // test: applies wrap overflow - expect($('pre').attr('style')).to.equal('background-color:#24292e;color:#e1e4e8'); - } - }); - - it('', async () => { - let html = await fixture.readFile('/css-theme/index.html'); - const $ = cheerio.load(html); - expect($('pre')).to.have.lengthOf(1); - expect($('pre').attr('class')).to.equal('astro-code css-variables'); - expect( - $('pre, pre span') - .map((i, f) => (f.attribs ? f.attribs.style : 'no style found')) - .toArray() - ).to.deep.equal([ - 'background-color:var(--astro-code-color-background);color:var(--astro-code-color-text); overflow-x: auto;', - 'color:var(--astro-code-token-constant)', - 'color:var(--astro-code-token-function)', - 'color:var(--astro-code-color-text)', - 'color:var(--astro-code-token-string-expression)', - 'color:var(--astro-code-color-text)', - ]); - }); - - it(' with custom theme and lang', async () => { - let html = await fixture.readFile('/imported/index.html'); - const $ = cheerio.load(html); - - expect($('#theme > pre')).to.have.lengthOf(1); - expect($('#theme > pre').attr('style'), 'background-color: #FDFDFE; overflow-x: auto;'); - - expect($('#lang > pre')).to.have.lengthOf(1); - expect($('#lang > pre > code span').length).to.equal(3); - }); - - it(' has no pre tag', async () => { - let html = await fixture.readFile('/inline/index.html'); - const $ = cheerio.load(html); - const codeEl = $('.astro-code'); - - expect(codeEl.prop('tagName')).to.eq('CODE'); - expect(codeEl.attr('style')).to.include('background-color:'); - expect($('pre')).to.have.lengthOf(0); - }); -}); diff --git a/packages/astro/test/astro-cookies.nodetest.js b/packages/astro/test/astro-cookies.nodetest.js new file mode 100644 index 000000000..34f548109 --- /dev/null +++ b/packages/astro/test/astro-cookies.nodetest.js @@ -0,0 +1,144 @@ +import * as cheerio from 'cheerio'; +import assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; +import testAdapter from './test-adapter.js'; + +describe('Astro.cookies', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-cookies/', + output: 'server', + adapter: testAdapter(), + }); + }); + + describe('Development', () => { + /** @type {import('./test-utils').DevServer} */ + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('is able to get cookies from the request', async () => { + const response = await fixture.fetch('/get-json', { + headers: { + cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, + }, + }); + assert.equal(response.status, 200); + const html = await response.text(); + + const $ = cheerio.load(html); + assert.equal($('dd').text(), 'light'); + }); + + it('can set the cookie value', async () => { + const response = await fixture.fetch('/set-value', { + method: 'POST', + }); + assert.equal(response.status, 200); + // Bug in 18.14.1 where `set-cookie` will not be defined + // Should be fixed in 18.14.2 + if (process.versions.node !== '18.14.1') { + assert.equal(response.headers.has('set-cookie'), true); + } + }); + }); + + describe('Production', () => { + let app; + before(async () => { + await fixture.build(); + app = await fixture.loadTestAdapterApp(); + }); + + async function fetchResponse(path, requestInit) { + const request = new Request('http://example.com' + path, requestInit); + const response = await app.render(request); + return response; + } + + it('is able to get cookies from the request', async () => { + const response = await fetchResponse('/get-json', { + headers: { + cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, + }, + }); + assert.equal(response.status, 200); + const html = await response.text(); + + const $ = cheerio.load(html); + assert.equal($('dd').text(), 'light'); + }); + + it('can set the cookie value', async () => { + const response = await fetchResponse('/set-value', { + method: 'POST', + }); + assert.equal(response.status, 200); + let headers = Array.from(app.setCookieHeaders(response)); + assert.equal(headers.length, 1); + assert.match(headers[0], /Expires/); + }); + + it('app.render can include the cookie in the Set-Cookie header', async () => { + const request = new Request('http://example.com/set-value', { + method: 'POST', + }); + const response = await app.render(request, { addCookieHeader: true }); + assert.equal(response.status, 200); + const value = response.headers.get('Set-Cookie'); + assert.equal(typeof value, 'string'); + assert.equal(value.startsWith('admin=true; Expires='), true); + }); + + it('app.render can exclude the cookie from the Set-Cookie header', async () => { + const request = new Request('http://example.com/set-value', { + method: 'POST', + }); + const response = await app.render(request, { addCookieHeader: false }); + assert.equal(response.status, 200); + assert.equal(response.headers.get('Set-Cookie'), null); + }); + + it('Early returning a Response still includes set headers', async () => { + const response = await fetchResponse('/early-return', { + headers: { + cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, + }, + }); + assert.equal(response.status, 302); + let headers = Array.from(app.setCookieHeaders(response)); + assert.equal(headers.length, 1); + let raw = headers[0].slice(6); + let data = JSON.parse(decodeURIComponent(raw)); + assert.equal(typeof data, 'object'); + assert.equal(data.mode, 'dark'); + }); + + it('API route can get and set cookies', async () => { + const response = await fetchResponse('/set-prefs', { + method: 'POST', + headers: { + cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, + }, + }); + assert.equal(response.status, 302); + let headers = Array.from(app.setCookieHeaders(response)); + assert.equal(headers.length, 1); + let raw = headers[0].slice(6); + let data = JSON.parse(decodeURIComponent(raw)); + assert.equal(typeof data, 'object'); + assert.equal(data.mode, 'dark'); + }); + }); +}); diff --git a/packages/astro/test/astro-cookies.test.js b/packages/astro/test/astro-cookies.test.js deleted file mode 100644 index e201ebd87..000000000 --- a/packages/astro/test/astro-cookies.test.js +++ /dev/null @@ -1,143 +0,0 @@ -import { expect } from 'chai'; -import * as cheerio from 'cheerio'; -import { loadFixture } from './test-utils.js'; -import testAdapter from './test-adapter.js'; - -describe('Astro.cookies', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; - - before(async () => { - fixture = await loadFixture({ - root: './fixtures/astro-cookies/', - output: 'server', - adapter: testAdapter(), - }); - }); - - describe('Development', () => { - /** @type {import('./test-utils').DevServer} */ - let devServer; - - before(async () => { - devServer = await fixture.startDevServer(); - }); - - after(async () => { - await devServer.stop(); - }); - - it('is able to get cookies from the request', async () => { - const response = await fixture.fetch('/get-json', { - headers: { - cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, - }, - }); - expect(response.status).to.equal(200); - const html = await response.text(); - - const $ = cheerio.load(html); - expect($('dd').text()).to.equal('light'); - }); - - it('can set the cookie value', async () => { - const response = await fixture.fetch('/set-value', { - method: 'POST', - }); - expect(response.status).to.equal(200); - // Bug in 18.14.1 where `set-cookie` will not be defined - // Should be fixed in 18.14.2 - if (process.versions.node !== '18.14.1') { - expect(response.headers.has('set-cookie')).to.equal(true); - } - }); - }); - - describe('Production', () => { - let app; - before(async () => { - await fixture.build(); - app = await fixture.loadTestAdapterApp(); - }); - - async function fetchResponse(path, requestInit) { - const request = new Request('http://example.com' + path, requestInit); - const response = await app.render(request); - return response; - } - - it('is able to get cookies from the request', async () => { - const response = await fetchResponse('/get-json', { - headers: { - cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, - }, - }); - expect(response.status).to.equal(200); - const html = await response.text(); - - const $ = cheerio.load(html); - expect($('dd').text()).to.equal('light'); - }); - - it('can set the cookie value', async () => { - const response = await fetchResponse('/set-value', { - method: 'POST', - }); - expect(response.status).to.equal(200); - let headers = Array.from(app.setCookieHeaders(response)); - expect(headers).to.have.a.lengthOf(1); - expect(headers[0]).to.match(/Expires/); - }); - - it('app.render can include the cookie in the Set-Cookie header', async () => { - const request = new Request('http://example.com/set-value', { - method: 'POST', - }); - const response = await app.render(request, { addCookieHeader: true }); - expect(response.status).to.equal(200); - expect(response.headers.get('Set-Cookie')) - .to.be.a('string') - .and.satisfy((value) => value.startsWith('admin=true; Expires=')); - }); - - it('app.render can exclude the cookie from the Set-Cookie header', async () => { - const request = new Request('http://example.com/set-value', { - method: 'POST', - }); - const response = await app.render(request, { addCookieHeader: false }); - expect(response.status).to.equal(200); - expect(response.headers.get('Set-Cookie')).to.equal(null); - }); - - it('Early returning a Response still includes set headers', async () => { - const response = await fetchResponse('/early-return', { - headers: { - cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, - }, - }); - expect(response.status).to.equal(302); - let headers = Array.from(app.setCookieHeaders(response)); - expect(headers).to.have.a.lengthOf(1); - let raw = headers[0].slice(6); - let data = JSON.parse(decodeURIComponent(raw)); - expect(data).to.be.an('object'); - expect(data.mode).to.equal('dark'); - }); - - it('API route can get and set cookies', async () => { - const response = await fetchResponse('/set-prefs', { - method: 'POST', - headers: { - cookie: `prefs=${encodeURIComponent(JSON.stringify({ mode: 'light' }))}`, - }, - }); - expect(response.status).to.equal(302); - let headers = Array.from(app.setCookieHeaders(response)); - expect(headers).to.have.a.lengthOf(1); - let raw = headers[0].slice(6); - let data = JSON.parse(decodeURIComponent(raw)); - expect(data).to.be.an('object'); - expect(data.mode).to.equal('dark'); - }); - }); -}); diff --git a/packages/astro/test/astro-css-bundling.nodetest.js b/packages/astro/test/astro-css-bundling.nodetest.js new file mode 100644 index 000000000..150f9a381 --- /dev/null +++ b/packages/astro/test/astro-css-bundling.nodetest.js @@ -0,0 +1,115 @@ +import * as cheerio from 'cheerio'; +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +// note: the hashes should be deterministic, but updating the file contents will change hashes +// be careful not to test that the HTML simply contains CSS, because it always will! filename and quanity matter here (bundling). +const EXPECTED_CSS = { + '/index.html': ['/_astro/'], // don’t match hashes, which change based on content + '/one/index.html': ['/_astro/'], + '/two/index.html': ['/_astro/'], +}; +const UNEXPECTED_CSS = [ + '/src/components/nav.css', + '../css/typography.css', + '../css/colors.css', + '../css/page-index.css', + '../css/page-one.css', + '../css/page-two.css', +]; + +describe('CSS Bundling', function () { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + describe('defaults', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-css-bundling/', + // test suite was authored when inlineStylesheets defaulted to never + build: { inlineStylesheets: 'never' }, + }); + await fixture.build({ mode: 'production' }); + }); + + it('Bundles CSS', async () => { + const builtCSS = new Set(); + + // for all HTML files… + for (const [filepath, css] of Object.entries(EXPECTED_CSS)) { + const html = await fixture.readFile(filepath); + const $ = cheerio.load(html); + + // test 1: assert new bundled CSS is present + for (const href of css) { + const link = $(`link[rel="stylesheet"][href^="${href}"]`); + assert.equal(link.length >= 1, true); + const outHref = link.attr('href'); + builtCSS.add(outHref.startsWith('../') ? outHref.slice(2) : outHref); + } + + // test 2: assert old CSS was removed + for (const href of UNEXPECTED_CSS) { + const link = $(`link[rel="stylesheet"][href="${href}"]`); + assert.equal(link.length, 0); + } + + // test 3: assert all bundled CSS was built and contains CSS + for (const url of builtCSS.keys()) { + const bundledCss = await fixture.readFile(url); + assert.ok(bundledCss); + } + } + }); + + it('there are 4 css files', async () => { + const dir = await fixture.readdir('/_astro'); + assert.equal(dir.length, 4); + }); + + it('CSS includes hashes', async () => { + const [firstFound] = await fixture.readdir('/_astro'); + assert.match(firstFound, /[a-z]+\.[\w-]{8}\.css/); + }); + }); + + describe('using custom assetFileNames config', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-css-bundling/', + + // test suite was authored when inlineStylesheets defaulted to never + build: { inlineStylesheets: 'never' }, + + vite: { + build: { + rollupOptions: { + output: { + assetFileNames: 'assets/[name][extname]', + entryFileNames: '[name].js', + }, + }, + }, + }, + }); + await fixture.build({ mode: 'production' }); + }); + + it('there are 4 css files', async () => { + const dir = await fixture.readdir('/assets'); + assert.equal(dir.length, 4); + }); + + it('CSS does not include hashes', async () => { + const [firstFound] = await fixture.readdir('/assets'); + assert.doesNotMatch(firstFound, /[a-z]+\.[\da-z]{8}\.css/); + }); + + it('there are 2 index named CSS files', async () => { + const dir = await fixture.readdir('/assets'); + const indexNamedFiles = dir.filter((name) => name.startsWith('index')); + assert.equal(indexNamedFiles.length, 2); + }); + }); +}); diff --git a/packages/astro/test/astro-css-bundling.test.js b/packages/astro/test/astro-css-bundling.test.js deleted file mode 100644 index 9143a782b..000000000 --- a/packages/astro/test/astro-css-bundling.test.js +++ /dev/null @@ -1,114 +0,0 @@ -import { expect } from 'chai'; -import * as cheerio from 'cheerio'; -import { loadFixture } from './test-utils.js'; - -// note: the hashes should be deterministic, but updating the file contents will change hashes -// be careful not to test that the HTML simply contains CSS, because it always will! filename and quanity matter here (bundling). -const EXPECTED_CSS = { - '/index.html': ['/_astro/'], // don’t match hashes, which change based on content - '/one/index.html': ['/_astro/'], - '/two/index.html': ['/_astro/'], -}; -const UNEXPECTED_CSS = [ - '/src/components/nav.css', - '../css/typography.css', - '../css/colors.css', - '../css/page-index.css', - '../css/page-one.css', - '../css/page-two.css', -]; - -describe('CSS Bundling', function () { - /** @type {import('./test-utils').Fixture} */ - let fixture; - - describe('defaults', () => { - before(async () => { - fixture = await loadFixture({ - root: './fixtures/astro-css-bundling/', - // test suite was authored when inlineStylesheets defaulted to never - build: { inlineStylesheets: 'never' }, - }); - await fixture.build({ mode: 'production' }); - }); - - it('Bundles CSS', async () => { - const builtCSS = new Set(); - - // for all HTML files… - for (const [filepath, css] of Object.entries(EXPECTED_CSS)) { - const html = await fixture.readFile(filepath); - const $ = cheerio.load(html); - - // test 1: assert new bundled CSS is present - for (const href of css) { - const link = $(`link[rel="stylesheet"][href^="${href}"]`); - expect(link.length).to.be.greaterThanOrEqual(1); - const outHref = link.attr('href'); - builtCSS.add(outHref.startsWith('../') ? outHref.slice(2) : outHref); - } - - // test 2: assert old CSS was removed - for (const href of UNEXPECTED_CSS) { - const link = $(`link[rel="stylesheet"][href="${href}"]`); - expect(link).to.have.lengthOf(0); - } - - // test 3: assert all bundled CSS was built and contains CSS - for (const url of builtCSS.keys()) { - const bundledCss = await fixture.readFile(url); - expect(bundledCss).to.be.ok; - } - } - }); - - it('there are 4 css files', async () => { - const dir = await fixture.readdir('/_astro'); - expect(dir).to.have.a.lengthOf(4); - }); - - it('CSS includes hashes', async () => { - const [firstFound] = await fixture.readdir('/_astro'); - expect(firstFound).to.match(/[a-z]+\.[\w-]{8}\.css/); - }); - }); - - describe('using custom assetFileNames config', () => { - before(async () => { - fixture = await loadFixture({ - root: './fixtures/astro-css-bundling/', - - // test suite was authored when inlineStylesheets defaulted to never - build: { inlineStylesheets: 'never' }, - - vite: { - build: { - rollupOptions: { - output: { - assetFileNames: 'assets/[name][extname]', - entryFileNames: '[name].js', - }, - }, - }, - }, - }); - await fixture.build({ mode: 'production' }); - }); - - it('there are 4 css files', async () => { - const dir = await fixture.readdir('/assets'); - expect(dir).to.have.a.lengthOf(4); - }); - - it('CSS does not include hashes', async () => { - const [firstFound] = await fixture.readdir('/assets'); - expect(firstFound).to.not.match(/[a-z]+\.[\da-z]{8}\.css/); - }); - - it('there are 2 index named CSS files', async () => { - const dir = await fixture.readdir('/assets'); - const indexNamedFiles = dir.filter((name) => name.startsWith('index')); - expect(indexNamedFiles).to.have.a.lengthOf(2); - }); - }); -}); diff --git a/packages/astro/test/astro-dev-headers.nodetest.js b/packages/astro/test/astro-dev-headers.nodetest.js new file mode 100644 index 000000000..e119e365a --- /dev/null +++ b/packages/astro/test/astro-dev-headers.nodetest.js @@ -0,0 +1,40 @@ +import assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +describe('Astro dev headers', () => { + let fixture; + let devServer; + const headers = { + 'x-astro': 'test', + }; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-dev-headers/', + server: { + headers, + }, + }); + await fixture.build(); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + describe('dev', () => { + it('returns custom headers for valid URLs', async () => { + const result = await fixture.fetch('/'); + assert.equal(result.status, 200); + assert.equal(Object.fromEntries(result.headers)['x-astro'], headers['x-astro']); + }); + + it('does not return custom headers for invalid URLs', async () => { + const result = await fixture.fetch('/bad-url'); + assert.equal(result.status, 404); + assert.equal(Object.fromEntries(result.headers).hasOwnProperty('x-astro'), false); + }); + }); +}); diff --git a/packages/astro/test/astro-dev-headers.test.js b/packages/astro/test/astro-dev-headers.test.js deleted file mode 100644 index 7cc2266c6..000000000 --- a/packages/astro/test/astro-dev-headers.test.js +++ /dev/null @@ -1,39 +0,0 @@ -import { expect } from 'chai'; -import { loadFixture } from './test-utils.js'; - -describe('Astro dev headers', () => { - let fixture; - let devServer; - const headers = { - 'x-astro': 'test', - }; - - before(async () => { - fixture = await loadFixture({ - root: './fixtures/astro-dev-headers/', - server: { - headers, - }, - }); - await fixture.build(); - devServer = await fixture.startDevServer(); - }); - - after(async () => { - await devServer.stop(); - }); - - describe('dev', () => { - it('returns custom headers for valid URLs', async () => { - const result = await fixture.fetch('/'); - expect(result.status).to.equal(200); - expect(Object.fromEntries(result.headers)).to.include(headers); - }); - - it('does not return custom headers for invalid URLs', async () => { - const result = await fixture.fetch('/bad-url'); - expect(result.status).to.equal(404); - expect(Object.fromEntries(result.headers)).not.to.include(headers); - }); - }); -}); diff --git a/packages/astro/test/astro-directives.nodetest.js b/packages/astro/test/astro-directives.nodetest.js new file mode 100644 index 000000000..5b9e0b672 --- /dev/null +++ b/packages/astro/test/astro-directives.nodetest.js @@ -0,0 +1,103 @@ +import * as cheerio from 'cheerio'; +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from './test-utils.js'; + +describe('Directives', async () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-directives/', + // test suite was authored when inlineStylesheets defaulted to never + build: { inlineStylesheets: 'never' }, + }); + await fixture.build(); + }); + + it('Passes define:vars to script elements', async () => { + const html = await fixture.readFile('/define-vars/index.html'); + const $ = cheerio.load(html); + + assert.equal($('script').length, 5); + + let i = 0; + for (const script of $('script').toArray()) { + // Wrap script in scope ({}) to avoid redeclaration errors + assert.equal($(script).text().startsWith('(function(){'), true); + assert.equal($(script).text().endsWith('})();'), true); + if (i < 2) { + // Inline defined variables + assert.equal($(script).toString().includes('const foo = "bar"'), true); + } else if (i < 3) { + // Convert invalid keys to valid identifiers + assert.equal($(script).toString().includes('const dashCase = "bar"'), true); + } else if (i < 4) { + // Closing script tags in strings are escaped + assert.equal($(script).toString().includes('const bar = "