diff --git a/packages/astro/package.json b/packages/astro/package.json index 1f8a8a0840..79bce5ef7c 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 --ignore ./test/lit-element.test.js && mocha ./test/lit-element.test.js --timeout 30000", + "test": "pnpm run test:node && mocha ./test/*.test.js --exit --timeout 30000", "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/fixtures/non-html-pages/src/pages/placeholder.png.ts b/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts index 1ac93597e6..5b6f63a3e2 100644 --- a/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts +++ b/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts @@ -2,13 +2,13 @@ import { promises as fs } from 'node:fs'; import type { APIRoute } from 'astro'; -export const GET: APIRoute = async function get() { +export const GET: APIRoute = async function get(ctx) { try { // Image is in the public domain. Sourced from // https://en.wikipedia.org/wiki/File:Portrait_placeholder.png const buffer = await fs.readFile('./test/fixtures/non-html-pages/src/images/placeholder.png'); // NOTE: SSG only so not Content-Type needed - return new Response(buffer.buffer) + return new Response(buffer.buffer); } catch (error: unknown) { throw new Error(`Something went wrong in placeholder.png route!: ${error as string}`); } diff --git a/packages/astro/test/lazy-layout.test.js b/packages/astro/test/lazy-layout.nodetest.js similarity index 81% rename from packages/astro/test/lazy-layout.test.js rename to packages/astro/test/lazy-layout.nodetest.js index 8f50a91dc3..4be339bafb 100644 --- a/packages/astro/test/lazy-layout.test.js +++ b/packages/astro/test/lazy-layout.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, before, it } from 'node:test'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; @@ -18,6 +19,6 @@ describe('Lazily imported layouts', () => { it('Renders styles only once', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); - expect($('link')).to.have.a.lengthOf(1); + assert.equal($('link').length, 1); }); }); diff --git a/packages/astro/test/lit-element.nodetest.js b/packages/astro/test/lit-element.nodetest.js new file mode 100644 index 0000000000..2ea5f13a94 --- /dev/null +++ b/packages/astro/test/lit-element.nodetest.js @@ -0,0 +1,154 @@ +import assert from 'node:assert/strict'; +import { describe, before, it } from 'node:test'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe( + 'LitElement test', + { timeout: 300000, skip: 'This goes in conflict with ssr-lit test file' }, + () => { + let fixture; + + const NODE_VERSION = parseFloat(process.versions.node); + const stripExpressionMarkers = (html) => html.replace(//g, ''); + + before(async () => { + // @lit-labs/ssr/ requires Node 13.9 or higher + if (NODE_VERSION < 13.9) { + return; + } + fixture = await loadFixture({ + root: './fixtures/lit-element/', + }); + await fixture.build(); + }); + + it('Renders a custom element by Constructor', async () => { + // @lit-labs/ssr/ requires Node 13.9 or higher + if (NODE_VERSION < 13.9) { + return; + } + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + // test 1: attributes rendered – non reactive properties + assert.equal($('#default').attr('foo'), 'bar'); + + // test 2: shadow rendered + assert.equal($('#default').html().includes('
Testing...
'), true); + + // test 3: string reactive property set + assert.equal( + stripExpressionMarkers($('#default').html()).includes(`
initialized
`), + true + ); + + // test 4: boolean reactive property correctly set + // Lit will equate to true because it uses + // this.hasAttribute to determine its value + assert.equal( + stripExpressionMarkers($('#default').html()).includes(`
B
`), + true + ); + + // test 5: object reactive property set + // by default objects will be stringified to [object Object] + assert.equal( + stripExpressionMarkers($('#default').html()).includes(`
data: 1
`), + true + ); + + // test 6: reactive properties are not rendered as attributes + assert.equal($('#default').attr('obj'), undefined); + assert.equal($('#default').attr('bool'), undefined); + assert.equal($('#default').attr('str'), undefined); + + // test 7: reflected reactive props are rendered as attributes + assert.equal($('#default').attr('reflectedbool'), ''); + assert.equal($('#default').attr('reflected-str'), 'default reflected string'); + assert.equal($('#default').attr('reflected-str-prop'), 'initialized reflected'); + }); + + it('Sets defer-hydration on element only when necessary', async () => { + // @lit-labs/ssr/ requires Node 13.9 or higher + if (NODE_VERSION < 13.9) { + return; + } + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + // test 1: reflected reactive props are rendered as attributes + assert.equal($('#non-deferred').attr('count'), '10'); + + // test 2: non-reactive props are set as attributes + assert.equal($('#non-deferred').attr('foo'), 'bar'); + + // test 3: components with only reflected reactive props set are not + // deferred because their state can be completely serialized via attributes + assert.equal($('#non-deferred').attr('defer-hydration'), undefined); + + // test 4: components with non-reflected reactive props set are deferred because + // their state needs to be synced with the server on the client. + assert.equal($('#default').attr('defer-hydration'), ''); + }); + + it('Correctly passes child slots', async () => { + // @lit-labs/ssr/ requires Node 13.9 or higher + if (NODE_VERSION < 13.9) { + return; + } + const html = await fixture.readFile('/slots/index.html'); + const $ = cheerio.load(html); + + const $rootMyElement = $('#root'); + const $slottedMyElement = $('#slotted'); + const $slottedSlottedMyElement = $('#slotted-slotted'); + + assert.equal($('#default').length, 3); + + // Root my-element + assert.equal($rootMyElement.children('.default').length, 2); + assert.equal($rootMyElement.children('.default').eq(1).text(), 'my-element default 2'); + + assert.equal($rootMyElement.children('[slot="named"]').length, 4); + assert.equal($rootMyElement.children('[slot="named"]').eq(1).text(), 'my-element named 2'); + assert.equal($rootMyElement.children('[slot="named"]').eq(2).attr('id'), 'list'); + assert.equal($rootMyElement.children('[slot="named"]').eq(3).attr('id'), 'slotted'); + + // Slotted my-element first level + assert.equal($slottedMyElement.children('.default').length, 1); + assert.equal( + $slottedMyElement.children('.default').eq(0).text(), + 'slotted my-element default' + ); + + assert.equal($slottedMyElement.children('[slot="named"]').length, 3); + assert.equal( + $slottedMyElement.children('[slot="named"]').eq(1).text(), + 'slotted my-element named 2' + ); + assert.equal( + $slottedMyElement.children('[slot="named"]').eq(2).attr('id'), + 'slotted-slotted' + ); + + // Slotted my-element second level + assert.equal($slottedSlottedMyElement.children('.default').length, 2); + assert.equal( + $slottedSlottedMyElement.children('.default').eq(1).text(), + 'slotted slotted my-element default 2' + ); + + assert.equal($slottedSlottedMyElement.children('[slot="named"]').length, 2); + assert.equal( + $slottedSlottedMyElement.children('[slot="named"]').eq(1).text(), + 'slotted slotted my-element named 2' + ); + }); + + it('Is able to build when behind getStaticPaths', async () => { + const dynamicPage = await fixture.readFile('/1/index.html'); + assert.equal(dynamicPage.length > 0, true); + }); + } +); diff --git a/packages/astro/test/lit-element.test.js b/packages/astro/test/lit-element.test.js deleted file mode 100644 index 9512909d8e..0000000000 --- a/packages/astro/test/lit-element.test.js +++ /dev/null @@ -1,139 +0,0 @@ -import { expect } from 'chai'; -import * as cheerio from 'cheerio'; -import { loadFixture } from './test-utils.js'; - -describe('LitElement test', function () { - this.timeout(30000); - - let fixture; - - const NODE_VERSION = parseFloat(process.versions.node); - const stripExpressionMarkers = (html) => html.replace(//g, ''); - - before(async () => { - // @lit-labs/ssr/ requires Node 13.9 or higher - if (NODE_VERSION < 13.9) { - return; - } - fixture = await loadFixture({ - root: './fixtures/lit-element/', - }); - await fixture.build(); - }); - - it('Renders a custom element by Constructor', async () => { - // @lit-labs/ssr/ requires Node 13.9 or higher - if (NODE_VERSION < 13.9) { - return; - } - const html = await fixture.readFile('/index.html'); - const $ = cheerio.load(html); - - // test 1: attributes rendered – non reactive properties - expect($('#default').attr('foo')).to.equal('bar'); - - // test 2: shadow rendered - expect($('#default').html()).to.include(`
Testing...
`); - - // test 3: string reactive property set - expect(stripExpressionMarkers($('#default').html())).to.include( - `
initialized
` - ); - - // test 4: boolean reactive property correctly set - // Lit will equate to true because it uses - // this.hasAttribute to determine its value - expect(stripExpressionMarkers($('#default').html())).to.include(`
B
`); - - // test 5: object reactive property set - // by default objects will be stringified to [object Object] - expect(stripExpressionMarkers($('#default').html())).to.include(`
data: 1
`); - - // test 6: reactive properties are not rendered as attributes - expect($('#default').attr('obj')).to.equal(undefined); - expect($('#default').attr('bool')).to.equal(undefined); - expect($('#default').attr('str')).to.equal(undefined); - - // test 7: reflected reactive props are rendered as attributes - expect($('#default').attr('reflectedbool')).to.equal(''); - expect($('#default').attr('reflected-str')).to.equal('default reflected string'); - expect($('#default').attr('reflected-str-prop')).to.equal('initialized reflected'); - }); - - it('Sets defer-hydration on element only when necessary', async () => { - // @lit-labs/ssr/ requires Node 13.9 or higher - if (NODE_VERSION < 13.9) { - return; - } - const html = await fixture.readFile('/index.html'); - const $ = cheerio.load(html); - - // test 1: reflected reactive props are rendered as attributes - expect($('#non-deferred').attr('count')).to.equal('10'); - - // test 2: non-reactive props are set as attributes - expect($('#non-deferred').attr('foo')).to.equal('bar'); - - // test 3: components with only reflected reactive props set are not - // deferred because their state can be completely serialized via attributes - expect($('#non-deferred').attr('defer-hydration')).to.equal(undefined); - - // test 4: components with non-reflected reactive props set are deferred because - // their state needs to be synced with the server on the client. - expect($('#default').attr('defer-hydration')).to.equal(''); - }); - - it('Correctly passes child slots', async () => { - // @lit-labs/ssr/ requires Node 13.9 or higher - if (NODE_VERSION < 13.9) { - return; - } - const html = await fixture.readFile('/slots/index.html'); - const $ = cheerio.load(html); - - const $rootMyElement = $('#root'); - const $slottedMyElement = $('#slotted'); - const $slottedSlottedMyElement = $('#slotted-slotted'); - - expect($('#default').length).to.equal(3); - - // Root my-element - expect($rootMyElement.children('.default').length).to.equal(2); - expect($rootMyElement.children('.default').eq(1).text()).to.equal('my-element default 2'); - - expect($rootMyElement.children('[slot="named"]').length).to.equal(4); - expect($rootMyElement.children('[slot="named"]').eq(1).text()).to.equal('my-element named 2'); - expect($rootMyElement.children('[slot="named"]').eq(2).attr('id')).to.equal('list'); - expect($rootMyElement.children('[slot="named"]').eq(3).attr('id')).to.equal('slotted'); - - // Slotted my-element first level - expect($slottedMyElement.children('.default').length).to.equal(1); - expect($slottedMyElement.children('.default').eq(0).text()).to.equal( - 'slotted my-element default' - ); - - expect($slottedMyElement.children('[slot="named"]').length).to.equal(3); - expect($slottedMyElement.children('[slot="named"]').eq(1).text()).to.equal( - 'slotted my-element named 2' - ); - expect($slottedMyElement.children('[slot="named"]').eq(2).attr('id')).to.equal( - 'slotted-slotted' - ); - - // Slotted my-element second level - expect($slottedSlottedMyElement.children('.default').length).to.equal(2); - expect($slottedSlottedMyElement.children('.default').eq(1).text()).to.equal( - 'slotted slotted my-element default 2' - ); - - expect($slottedSlottedMyElement.children('[slot="named"]').length).to.equal(2); - expect($slottedSlottedMyElement.children('[slot="named"]').eq(1).text()).to.equal( - 'slotted slotted my-element named 2' - ); - }); - - it('Is able to build when behind getStaticPaths', async () => { - const dynamicPage = await fixture.readFile('/1/index.html'); - expect(dynamicPage.length).to.be.greaterThan(0); - }); -}); diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.nodetest.js similarity index 65% rename from packages/astro/test/middleware.test.js rename to packages/astro/test/middleware.nodetest.js index 736eac25c4..b5d77c091b 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, it, before, after } from 'node:test'; import * as cheerio from 'cheerio'; import { existsSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; @@ -24,105 +25,108 @@ describe('Middleware in DEV mode', () => { it('should render locals data', async () => { const html = await fixture.fetch('/').then((res) => res.text()); const $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); }); it('should change locals data based on URL', async () => { let html = await fixture.fetch('/').then((res) => res.text()); let $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); html = await fixture.fetch('/lorem').then((res) => res.text()); $ = cheerio.load(html); - expect($('p').html()).to.equal('ipsum'); + assert.equal($('p').html(), 'ipsum'); }); it('should call a second middleware', async () => { - let html = await fixture.fetch('/second').then((res) => res.text()); - let $ = cheerio.load(html); - expect($('p').html()).to.equal('second'); + const html = await fixture.fetch('/second').then((res) => res.text()); + const $ = cheerio.load(html); + assert.equal($('p').html(), 'second'); }); it('should successfully create a new response', async () => { - let html = await fixture.fetch('/rewrite').then((res) => res.text()); - let $ = cheerio.load(html); - expect($('p').html()).to.be.null; - expect($('span').html()).to.equal('New content!!'); + const html = await fixture.fetch('/rewrite').then((res) => res.text()); + const $ = cheerio.load(html); + assert.equal($('p').html(), null); + assert.equal($('span').html(), 'New content!!'); }); it('should return a new response that is a 500', async () => { await fixture.fetch('/broken-500').then((res) => { - expect(res.status).to.equal(500); + assert.equal(res.status, 500); return res.text(); }); }); it('should successfully render a page if the middleware calls only next() and returns nothing', async () => { - let html = await fixture.fetch('/not-interested').then((res) => res.text()); - let $ = cheerio.load(html); - expect($('p').html()).to.equal('Not interested'); + const html = await fixture.fetch('/not-interested').then((res) => res.text()); + const $ = cheerio.load(html); + assert.equal($('p').html(), 'Not interested'); }); it("should throw an error when the middleware doesn't call next or doesn't return a response", async () => { - let html = await fixture.fetch('/does-nothing').then((res) => res.text()); - let $ = cheerio.load(html); - expect($('title').html()).to.equal('MiddlewareNoDataOrNextCalled'); + const html = await fixture.fetch('/does-nothing').then((res) => res.text()); + const $ = cheerio.load(html); + assert.equal($('title').html(), 'MiddlewareNoDataOrNextCalled'); }); it('should allow setting cookies', async () => { - let res = await fixture.fetch('/'); - expect(res.headers.get('set-cookie')).to.equal('foo=bar'); + const res = await fixture.fetch('/'); + assert.equal(res.headers.get('set-cookie'), 'foo=bar'); }); it('should be able to clone the response', async () => { - let res = await fixture.fetch('/clone'); - let html = await res.text(); - expect(html).to.contain('it works'); + const res = await fixture.fetch('/clone'); + const html = await res.text(); + assert.equal(html.includes('it works'), true); }); it('should forward cookies set in a component when the middleware returns a new response', async () => { - let res = await fixture.fetch('/return-response-cookies'); - let headers = res.headers; - expect(headers.get('set-cookie')).to.not.equal(null); + const res = await fixture.fetch('/return-response-cookies'); + const headers = res.headers; + assert.notEqual(headers.get('set-cookie'), null); }); describe('Integration hooks', () => { it('Integration middleware marked as "pre" runs', async () => { - let res = await fixture.fetch('/integration-pre'); - let json = await res.json(); - expect(json.pre).to.equal('works'); + const res = await fixture.fetch('/integration-pre'); + const json = await res.json(); + assert.equal(json.pre, 'works'); }); it('Integration middleware marked as "post" runs', async () => { - let res = await fixture.fetch('/integration-post'); - let json = await res.json(); - expect(json.post).to.equal('works'); + const res = await fixture.fetch('/integration-post'); + const json = await res.json(); + assert.equal(json.post, 'works'); }); }); +}); - describe('Integration hooks with no user middleware', () => { - before(async () => { - fixture = await loadFixture({ - root: './fixtures/middleware-no-user-middleware/', - }); - devServer = await fixture.startDevServer(); +describe('Integration hooks with no user middleware', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + let devServer; + before(async () => { + fixture = await loadFixture({ + root: './fixtures/middleware-no-user-middleware/', }); + devServer = await fixture.startDevServer(); + }); - after(async () => { - await devServer.stop(); - }); + after(async () => { + await devServer.stop(); + }); - it('Integration middleware marked as "pre" runs', async () => { - let res = await fixture.fetch('/pre'); - let json = await res.json(); - expect(json.pre).to.equal('works'); - }); + it('Integration middleware marked as "pre" runs', async () => { + const res = await fixture.fetch('/pre'); + const json = await res.json(); + assert.equal(json.pre, 'works'); + }); - it('Integration middleware marked as "post" runs', async () => { - let res = await fixture.fetch('/post'); - let json = await res.json(); - expect(json.post).to.equal('works'); - }); + it('Integration middleware marked as "post" runs', async () => { + const res = await fixture.fetch('/post'); + const json = await res.json(); + assert.equal(json.post, 'works'); }); }); @@ -140,17 +144,17 @@ describe('Middleware in PROD mode, SSG', () => { it('should render locals data', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); }); it('should change locals data based on URL', async () => { let html = await fixture.readFile('/index.html'); let $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); html = await fixture.readFile('/second/index.html'); $ = cheerio.load(html); - expect($('p').html()).to.equal('second'); + assert.equal($('p').html(), 'second'); }); }); @@ -176,32 +180,32 @@ describe('Middleware API in PROD mode, SSR', () => { const response = await app.render(request); const html = await response.text(); const $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); }); it('should change locals data based on URL', async () => { let response = await app.render(new Request('http://example.com/')); let html = await response.text(); let $ = cheerio.load(html); - expect($('p').html()).to.equal('bar'); + assert.equal($('p').html(), 'bar'); response = await app.render(new Request('http://example.com/lorem')); html = await response.text(); $ = cheerio.load(html); - expect($('p').html()).to.equal('ipsum'); + assert.equal($('p').html(), 'ipsum'); }); it('should successfully redirect to another page', async () => { const request = new Request('http://example.com/redirect'); const response = await app.render(request); - expect(response.status).to.equal(302); + assert.equal(response.status, 302); }); it('should call a second middleware', async () => { const response = await app.render(new Request('http://example.com/second')); const html = await response.text(); const $ = cheerio.load(html); - expect($('p').html()).to.equal('second'); + assert.equal($('p').html(), 'second'); }); it('should successfully create a new response', async () => { @@ -209,14 +213,14 @@ describe('Middleware API in PROD mode, SSR', () => { const response = await app.render(request); const html = await response.text(); const $ = cheerio.load(html); - expect($('p').html()).to.be.null; - expect($('span').html()).to.equal('New content!!'); + assert.equal($('p').html(), null); + assert.equal($('span').html(), 'New content!!'); }); it('should return a new response that is a 500', async () => { const request = new Request('http://example.com/broken-500'); const response = await app.render(request); - expect(response.status).to.equal(500); + assert.equal(response.status, 500); }); it('should successfully render a page if the middleware calls only next() and returns nothing', async () => { @@ -224,7 +228,7 @@ describe('Middleware API in PROD mode, SSR', () => { const response = await app.render(request); const html = await response.text(); const $ = cheerio.load(html); - expect($('p').html()).to.equal('Not interested'); + assert.equal($('p').html(), 'Not interested'); }); it("should throw an error when the middleware doesn't call next or doesn't return a response", async () => { @@ -232,21 +236,21 @@ describe('Middleware API in PROD mode, SSR', () => { const response = await app.render(request); const html = await response.text(); const $ = cheerio.load(html); - expect($('title').html()).to.not.equal('MiddlewareNoDataReturned'); + assert.notEqual($('title').html(), 'MiddlewareNoDataReturned'); }); it('should correctly work for API endpoints that return a Response object', async () => { const request = new Request('http://example.com/api/endpoint'); const response = await app.render(request); - expect(response.status).to.equal(200); - expect(response.headers.get('Content-Type')).to.equal('application/json'); + assert.equal(response.status, 200); + assert.equal(response.headers.get('Content-Type'), 'application/json'); }); it('should correctly manipulate the response coming from API endpoints (not simple)', async () => { const request = new Request('http://example.com/api/endpoint'); const response = await app.render(request); const text = await response.text(); - expect(text.includes('REDACTED')).to.be.true; + assert.equal(text.includes('REDACTED'), true); }); it('should correctly call the middleware function for 404', async () => { @@ -254,8 +258,8 @@ describe('Middleware API in PROD mode, SSR', () => { const routeData = app.match(request); const response = await app.render(request, { routeData }); const text = await response.text(); - expect(text.includes('Error')).to.be.true; - expect(text.includes('bar')).to.be.true; + assert.equal(text.includes('Error'), true); + assert.equal(text.includes('bar'), true); }); it('should render 500.astro when the middleware throws an error', async () => { @@ -263,10 +267,10 @@ describe('Middleware API in PROD mode, SSR', () => { const routeData = app.match(request); const response = await app.render(request, routeData); - expect(response).to.deep.include({ status: 500 }); + assert.equal(response.status, 500); const text = await response.text(); - expect(text).to.include('

There was an error rendering the page.

'); + assert.equal(text.includes('

There was an error rendering the page.

'), true); }); it('should correctly render the page even when custom headers are set in a middleware', async () => { @@ -274,13 +278,13 @@ describe('Middleware API in PROD mode, SSR', () => { const routeData = app.match(request); const response = await app.render(request, { routeData }); - expect(response).to.deep.include({ status: 404 }); - expect(response.headers.get('content-type')).equal('text/html'); + assert.equal(response.status, 404); + assert.equal(response.headers.get('content-type'), 'text/html'); }); it('can set locals for prerendered pages to use', async () => { const text = await fixture.readFile('/client/prerendered/index.html'); - expect(text.includes('

yes they can!

')).to.be.true; + assert.equal(text.includes('

yes they can!

'), true); }); // keep this last @@ -303,14 +307,14 @@ describe('Middleware API in PROD mode, SSR', () => { }), }); await fixture.build(); - expect(middlewarePath).to.not.be.undefined; + assert.ok(middlewarePath); try { const path = fileURLToPath(middlewarePath); - expect(existsSync(path)).to.be.true; + assert.equal(existsSync(path), true); const content = readFileSync(fileURLToPath(middlewarePath), 'utf-8'); - expect(content.length).to.be.greaterThan(0); + assert.equal(content.length > 0, true); } catch (e) { - throw e; + assert.fail(); } }); }); @@ -333,37 +337,43 @@ describe('Middleware with tailwind', () => { const bundledCSS = (await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/'))) .replace(/\s/g, '') .replace('/n', ''); - expect(bundledCSS.includes('--tw-content')).to.be.true; + assert.equal(bundledCSS.includes('--tw-content'), true); }); }); // `loadTestAdapterApp()` does not understand how to load the page with `functionPerRoute` // since there's no `entry.mjs`. Skip for now. -describe.skip('Middleware supports functionPerRoute feature', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; +describe( + 'Middleware supports functionPerRoute feature', + { + skip: "`loadTestAdapterApp()` does not understand how to load the page with `functionPerRoute` since there's no `entry.mjs`", + }, + () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; - before(async () => { - fixture = await loadFixture({ - root: './fixtures/middleware space/', - output: 'server', - adapter: testAdapter({ - extendAdapter: { - adapterFeatures: { - functionPerRoute: true, + before(async () => { + fixture = await loadFixture({ + root: './fixtures/middleware space/', + output: 'server', + adapter: testAdapter({ + extendAdapter: { + adapterFeatures: { + functionPerRoute: true, + }, }, - }, - }), + }), + }); + await fixture.build(); }); - await fixture.build(); - }); - it('should not render locals data because the page does not export it', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - expect($('p').html()).to.not.equal('bar'); - }); -}); + it('should not render locals data because the page does not export it', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/'); + const response = await app.render(request); + const html = await response.text(); + const $ = cheerio.load(html); + assert.equal($('p').html(), 'bar'); + }); + } +); diff --git a/packages/astro/test/minification-html.test.js b/packages/astro/test/minification-html.nodetest.js similarity index 85% rename from packages/astro/test/minification-html.test.js rename to packages/astro/test/minification-html.nodetest.js index eec388321e..6aefa98a52 100644 --- a/packages/astro/test/minification-html.test.js +++ b/packages/astro/test/minification-html.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, it, before, after } from 'node:test'; import { loadFixture } from './test-utils.js'; import testAdapter from './test-adapter.js'; @@ -37,10 +38,10 @@ describe('HTML minification', () => { }); it('should emit compressed HTML in the emitted file', async () => { - let res = await fixture.fetch(`/`); - expect(res.status).to.equal(200); + let res = await fixture.fetch('/'); + assert.equal(res.status, 200); const html = await res.text(); - expect(NEW_LINES.test(removeDoctypeLineInDev(html))).to.equal(false); + assert.equal(NEW_LINES.test(removeDoctypeLineInDev(html)), false); }); }); @@ -57,7 +58,7 @@ describe('HTML minification', () => { it('should emit compressed HTML in the emitted file', async () => { const html = await fixture.readFile('/index.html'); - expect(NEW_LINES.test(html)).to.equal(false); + assert.equal(NEW_LINES.test(html), false); }); }); @@ -79,7 +80,7 @@ describe('HTML minification', () => { const request = new Request('http://example.com/'); const response = await app.render(request); const html = await response.text(); - expect(NEW_LINES.test(removeDoctypeLine(html))).to.equal(false); + assert.equal(NEW_LINES.test(removeDoctypeLine(html)), false); }); }); }); diff --git a/packages/astro/test/multiple-renderers.test.js b/packages/astro/test/multiple-renderers.nodetest.js similarity index 79% rename from packages/astro/test/multiple-renderers.test.js rename to packages/astro/test/multiple-renderers.nodetest.js index 3b542aab8c..ba55ac8470 100644 --- a/packages/astro/test/multiple-renderers.test.js +++ b/packages/astro/test/multiple-renderers.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, it, before } from 'node:test'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; @@ -16,6 +17,6 @@ describe('Multiple renderers', () => { it('when the first throws but the second does not, use the second renderer', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); - expect($('#component')).to.have.a.lengthOf(1); + assert.equal($('#component').length, 1); }); }); diff --git a/packages/astro/test/non-ascii-path.test.js b/packages/astro/test/non-ascii-path.nodetest.js similarity index 76% rename from packages/astro/test/non-ascii-path.test.js rename to packages/astro/test/non-ascii-path.nodetest.js index 5fb947e9e0..ada3749a85 100644 --- a/packages/astro/test/non-ascii-path.test.js +++ b/packages/astro/test/non-ascii-path.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, it, before } from 'node:test'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; @@ -15,7 +16,7 @@ describe('Non-ASCII Path Test', () => { const html = await fixture.readFile(`/index.html`); const $ = cheerio.load(html); - expect($('h1').text()).to.equal('测试 OK'); + assert.equal($('h1').text(), '测试 OK'); }); }); }); diff --git a/packages/astro/test/non-html-pages.test.js b/packages/astro/test/non-html-pages.nodetest.js similarity index 82% rename from packages/astro/test/non-html-pages.test.js rename to packages/astro/test/non-html-pages.nodetest.js index 9f050ae96f..f27787ef96 100644 --- a/packages/astro/test/non-html-pages.test.js +++ b/packages/astro/test/non-html-pages.nodetest.js @@ -1,4 +1,5 @@ -import { expect } from 'chai'; +import assert from 'node:assert/strict'; +import { describe, it, before } from 'node:test'; import { loadFixture } from './test-utils.js'; describe('Non-HTML Pages', () => { @@ -12,8 +13,8 @@ describe('Non-HTML Pages', () => { describe('json', () => { it('should match contents', async () => { const json = JSON.parse(await fixture.readFile('/about.json')); - expect(json).to.have.property('name', 'Astro'); - expect(json).to.have.property('url', 'https://astro.build/'); + assert.equal(json.name, 'Astro'); + assert.equal(json.url, 'https://astro.build/'); }); }); @@ -25,12 +26,13 @@ describe('Non-HTML Pages', () => { const hex = Buffer.from(buffer, 'base64').toString('hex'); const firstHexByte = hex.slice(0, 2); // If we accidentally utf8 encode the png, the first byte (in hex) will be 'c2' - expect(firstHexByte).to.not.equal('c2'); + assert.notEqual(firstHexByte, 'c2'); // and if correctly encoded in binary, it should be '89' - expect(firstHexByte).to.equal('89'); + assert.equal(firstHexByte, '89'); // Make sure the whole buffer (in base64) matches this snapshot - expect(buffer).to.equal( + assert.equal( + buffer, 'iVBORw0KGgoAAAANSUhEUgAAAGQAAACWCAMAAAAfZt10AAAABlBMVEXd3d3+/v7B/CFgAAAA3UlEQVR42u3ZMQ7DIBQFQeb+l06bNgUbG/5eYApLFjzWNE3TNE3TNE035av9AhAQEBBQGAQEFAaFQWFQGBQGhUGCKAwKgwQpDJ6JECgCRYIEikH8YAyCRyEGyRCDvBWRIPNNBpm/8G6kUM45EhXKlQfuFSHFpbFH+jt2j/S7xwqUYvBaCRIozZy6X2km7v1K8uwQIIWBwkBAQEBg3Tyj3z4LnzRBKgwKg8KgMEgQhaEwSBCFQWBEiMIgQQqDBCkMEqQw+APixYgcsa0TERs7D/F6xGmIAxCD/Iw4AvEB92Ec3ZAPdlMAAAAASUVORK5CYII=' ); });