diff --git a/packages/integrations/netlify/test/functions/cookies.test.js b/packages/integrations/netlify/test/functions/cookies.test.js
index 6ef16763ed5d..2e5bd03dc1ef 100644
--- a/packages/integrations/netlify/test/functions/cookies.test.js
+++ b/packages/integrations/netlify/test/functions/cookies.test.js
@@ -2,64 +2,58 @@ import * as assert from 'node:assert/strict';
import { before, describe, it } from 'node:test';
import { loadFixture } from '../../../../astro/test/test-utils.js';
-describe(
- 'Cookies',
- () => {
- let fixture;
+describe('Cookies', { timeout: 120000 }, () => {
+ let fixture;
- before(async () => {
- fixture = await loadFixture({ root: new URL('./fixtures/cookies/', import.meta.url) });
- await fixture.build();
- });
+ before(async () => {
+ fixture = await loadFixture({ root: new URL('./fixtures/cookies/', import.meta.url) });
+ await fixture.build();
+ });
- it('Can set multiple', async () => {
- const entryURL = new URL(
- './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(
- new Request('http://example.com/login', { method: 'POST', body: '{}' }),
- {},
- );
- assert.equal(resp.status, 301);
- assert.equal(resp.headers.get('location'), '/');
- assert.deepEqual(resp.headers.getSetCookie(), ['foo=foo; HttpOnly', 'bar=bar; HttpOnly']);
- });
+ it('Can set multiple', async () => {
+ const entryURL = new URL(
+ './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(
+ new Request('http://example.com/login', { method: 'POST', body: '{}' }),
+ {},
+ );
+ assert.equal(resp.status, 301);
+ assert.equal(resp.headers.get('location'), '/');
+ assert.deepEqual(resp.headers.getSetCookie(), ['foo=foo; HttpOnly', 'bar=bar; HttpOnly']);
+ });
- it('Can set partitioned cookie', async () => {
- const entryURL = new URL(
- './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(new Request('http://example.com/partitioned'), {});
- assert.equal(resp.status, 200);
- const cookie = resp.headers.getSetCookie()[0];
- assert.ok(cookie.includes('Partitioned'), 'Cookie should include Partitioned attribute');
- });
+ it('Can set partitioned cookie', async () => {
+ const entryURL = new URL(
+ './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(new Request('http://example.com/partitioned'), {});
+ assert.equal(resp.status, 200);
+ const cookie = resp.headers.getSetCookie()[0];
+ assert.ok(cookie.includes('Partitioned'), 'Cookie should include Partitioned attribute');
+ });
- it('renders dynamic 404 page', async () => {
- const entryURL = new URL(
- './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(
- new Request('http://example.com/nonexistant-page', {
- headers: {
- 'x-test': 'bar',
- },
- }),
- {},
- );
- assert.equal(resp.status, 404);
- const text = await resp.text();
- assert.equal(text.includes('This is my custom 404 page'), true);
- assert.equal(text.includes('x-test: bar'), true);
- });
- },
- {
- timeout: 120000,
- },
-);
+ it('renders dynamic 404 page', async () => {
+ const entryURL = new URL(
+ './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(
+ new Request('http://example.com/nonexistant-page', {
+ headers: {
+ 'x-test': 'bar',
+ },
+ }),
+ {},
+ );
+ assert.equal(resp.status, 404);
+ const text = await resp.text();
+ assert.equal(text.includes('This is my custom 404 page'), true);
+ assert.equal(text.includes('x-test: bar'), true);
+ });
+});
diff --git a/packages/integrations/netlify/test/functions/edge-middleware.test.js b/packages/integrations/netlify/test/functions/edge-middleware.test.js
index 6d255f4dc7f9..2e84d3048028 100644
--- a/packages/integrations/netlify/test/functions/edge-middleware.test.js
+++ b/packages/integrations/netlify/test/functions/edge-middleware.test.js
@@ -2,65 +2,59 @@ import * as assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { loadFixture } from '../../../../astro/test/test-utils.js';
-describe(
- 'Middleware',
- () => {
- const root = new URL('./fixtures/middleware/', import.meta.url);
-
- describe('middlewareMode: classic', () => {
- let fixture;
- before(async () => {
- process.env.EDGE_MIDDLEWARE = 'false';
- fixture = await loadFixture({ root });
- await fixture.build();
- });
-
- it('emits no edge function', async () => {
- assert.equal(
- fixture.pathExists('../.netlify/v1/edge-functions/middleware/middleware.mjs'),
- false,
- );
- });
+describe('Middleware', { timeout: 120000 }, () => {
+ const root = new URL('./fixtures/middleware/', import.meta.url);
+
+ describe('middlewareMode: classic', () => {
+ let fixture;
+ before(async () => {
+ process.env.EDGE_MIDDLEWARE = 'false';
+ fixture = await loadFixture({ root });
+ await fixture.build();
+ });
- it('applies middleware to static files at build-time', async () => {
- // prerendered page has middleware applied at build time
- const prerenderedPage = await fixture.readFile('prerender/index.html');
- assert.equal(prerenderedPage.includes('
Middleware'), true);
- });
+ it('emits no edge function', async () => {
+ assert.equal(
+ fixture.pathExists('../.netlify/v1/edge-functions/middleware/middleware.mjs'),
+ false,
+ );
+ });
- after(async () => {
- process.env.EDGE_MIDDLEWARE = undefined;
- await fixture.clean();
- });
+ it('applies middleware to static files at build-time', async () => {
+ // prerendered page has middleware applied at build time
+ const prerenderedPage = await fixture.readFile('prerender/index.html');
+ assert.equal(prerenderedPage.includes('Middleware'), true);
});
- describe('middlewareMode: edge', () => {
- let fixture;
- before(async () => {
- process.env.EDGE_MIDDLEWARE = 'true';
- fixture = await loadFixture({ root });
- await fixture.build();
- });
+ after(async () => {
+ process.env.EDGE_MIDDLEWARE = undefined;
+ await fixture.clean();
+ });
+ });
+
+ describe('middlewareMode: edge', () => {
+ let fixture;
+ before(async () => {
+ process.env.EDGE_MIDDLEWARE = 'true';
+ fixture = await loadFixture({ root });
+ await fixture.build();
+ });
- it('emits an edge function', async () => {
- const contents = await fixture.readFile(
- '../.netlify/v1/edge-functions/middleware/middleware.mjs',
- );
- assert.equal(contents.includes('"Hello world"'), false);
- });
+ it('emits an edge function', async () => {
+ const contents = await fixture.readFile(
+ '../.netlify/v1/edge-functions/middleware/middleware.mjs',
+ );
+ assert.equal(contents.includes('"Hello world"'), false);
+ });
- it.skip('does not apply middleware during prerendering', async () => {
- const prerenderedPage = await fixture.readFile('prerender/index.html');
- assert.equal(prerenderedPage.includes(''), true);
- });
+ it.skip('does not apply middleware during prerendering', async () => {
+ const prerenderedPage = await fixture.readFile('prerender/index.html');
+ assert.equal(prerenderedPage.includes(''), true);
+ });
- after(async () => {
- process.env.EDGE_MIDDLEWARE = undefined;
- await fixture.clean();
- });
+ after(async () => {
+ process.env.EDGE_MIDDLEWARE = undefined;
+ await fixture.clean();
});
- },
- {
- timeout: 120000,
- },
-);
+ });
+});
diff --git a/packages/integrations/netlify/test/functions/image-cdn.test.js b/packages/integrations/netlify/test/functions/image-cdn.test.js
index 8d6196817607..c398130366a2 100644
--- a/packages/integrations/netlify/test/functions/image-cdn.test.js
+++ b/packages/integrations/netlify/test/functions/image-cdn.test.js
@@ -4,179 +4,169 @@ import { remotePatternToRegex } from '@astrojs/netlify';
import { loadFixture } from '../../../../astro/test/test-utils.js';
import imageService from '../../dist/image-service.js';
-describe(
- 'Image CDN',
- () => {
- const root = new URL('./fixtures/middleware/', import.meta.url);
-
- describe('configuration', () => {
- after(() => {
- process.env.DISABLE_IMAGE_CDN = undefined;
- });
-
- it('enables Netlify Image CDN', async () => {
- const fixture = await loadFixture({ root });
- await fixture.build();
+describe('Image CDN', { timeout: 120000 }, () => {
+ const root = new URL('./fixtures/middleware/', import.meta.url);
- const astronautPage = await fixture.readFile('astronaut/index.html');
- assert.equal(astronautPage.includes(`src="/.netlify/image`), true);
- });
+ describe('configuration', () => {
+ after(() => {
+ process.env.DISABLE_IMAGE_CDN = undefined;
+ });
- it('respects image CDN opt-out', async () => {
- process.env.DISABLE_IMAGE_CDN = 'true';
- const fixture = await loadFixture({ root });
- await fixture.build();
+ it('enables Netlify Image CDN', async () => {
+ const fixture = await loadFixture({ root });
+ await fixture.build();
- const astronautPage = await fixture.readFile('astronaut/index.html');
- assert.equal(astronautPage.includes(`src="/_astro/astronaut.`), true);
- });
+ const astronautPage = await fixture.readFile('astronaut/index.html');
+ assert.equal(astronautPage.includes(`src="/.netlify/image`), true);
});
- describe('remote image config', () => {
- let regexes;
+ it('respects image CDN opt-out', async () => {
+ process.env.DISABLE_IMAGE_CDN = 'true';
+ const fixture = await loadFixture({ root });
+ await fixture.build();
- before(async () => {
- const fixture = await loadFixture({ root });
- await fixture.build();
+ const astronautPage = await fixture.readFile('astronaut/index.html');
+ assert.equal(astronautPage.includes(`src="/_astro/astronaut.`), true);
+ });
+ });
- const config = await fixture.readFile('../.netlify/v1/config.json');
- if (config) {
- regexes = JSON.parse(config).images.remote_images.map((pattern) => new RegExp(pattern));
- }
- });
+ describe('remote image config', () => {
+ let regexes;
- it('generates remote image config patterns', async () => {
- assert.equal(regexes?.length, 3);
- });
+ before(async () => {
+ const fixture = await loadFixture({ root });
+ await fixture.build();
- it('generates correct config for domains', async () => {
- const domain = regexes[0];
- assert.equal(domain.test('https://example.net/image.jpg'), true);
- assert.equal(
- domain.test('https://www.example.net/image.jpg'),
- false,
- 'subdomain should not match',
- );
- assert.equal(domain.test('http://example.net/image.jpg'), true, 'http should match');
- assert.equal(
- domain.test('https://example.net/subdomain/image.jpg'),
- true,
- 'subpath should match',
- );
- const subdomain = regexes[1];
- assert.equal(
- subdomain.test('https://secret.example.edu/image.jpg'),
- true,
- 'should match subdomains',
- );
- assert.equal(
- subdomain.test('https://secretxexample.edu/image.jpg'),
- false,
- 'should not use dots in domains as wildcards',
- );
- });
+ const config = await fixture.readFile('../.netlify/v1/config.json');
+ if (config) {
+ regexes = JSON.parse(config).images.remote_images.map((pattern) => new RegExp(pattern));
+ }
+ });
- it('generates correct config for remotePatterns', async () => {
- const patterns = regexes[2];
- assert.equal(
- patterns.test('https://example.org/images/1.jpg'),
- true,
- 'should match domain',
- );
- assert.equal(
- patterns.test('https://www.example.org/images/2.jpg'),
- true,
- 'www subdomain should match',
- );
- assert.equal(
- patterns.test('https://www.subdomain.example.org/images/2.jpg'),
- false,
- 'second level subdomain should not match',
- );
- assert.equal(
- patterns.test('https://example.org/not-images/2.jpg'),
- false,
- 'wrong path should not match',
- );
- });
+ it('generates remote image config patterns', async () => {
+ assert.equal(regexes?.length, 3);
+ });
- it('warns when remotepatterns generates an invalid regex', async (t) => {
- const logger = {
- warn: t.mock.fn(),
- };
- const regex = remotePatternToRegex(
- {
- hostname: '*.examp[le.org',
- pathname: '/images/*',
- },
- logger,
- );
- assert.strictEqual(regex, undefined);
- const calls = logger.warn.mock.calls;
- assert.strictEqual(calls.length, 1);
- assert.equal(
- calls[0].arguments[0],
- 'Could not generate a valid regex from the remotePattern "{"hostname":"*.examp[le.org","pathname":"/images/*"}". Please check the syntax.',
- );
- });
+ it('generates correct config for domains', async () => {
+ const domain = regexes[0];
+ assert.equal(domain.test('https://example.net/image.jpg'), true);
+ assert.equal(
+ domain.test('https://www.example.net/image.jpg'),
+ false,
+ 'subdomain should not match',
+ );
+ assert.equal(domain.test('http://example.net/image.jpg'), true, 'http should match');
+ assert.equal(
+ domain.test('https://example.net/subdomain/image.jpg'),
+ true,
+ 'subpath should match',
+ );
+ const subdomain = regexes[1];
+ assert.equal(
+ subdomain.test('https://secret.example.edu/image.jpg'),
+ true,
+ 'should match subdomains',
+ );
+ assert.equal(
+ subdomain.test('https://secretxexample.edu/image.jpg'),
+ false,
+ 'should not use dots in domains as wildcards',
+ );
});
- describe('fit parameter', () => {
- it('includes fit parameter in image URL', () => {
- const url = imageService.getURL({
- src: 'images/astronaut.jpg',
- width: 300,
- height: 400,
- fit: 'cover',
- format: 'webp',
- });
- assert.ok(url.includes('fit=cover'), `Expected fit=cover in URL, got: ${url}`);
- });
+ it('generates correct config for remotePatterns', async () => {
+ const patterns = regexes[2];
+ assert.equal(patterns.test('https://example.org/images/1.jpg'), true, 'should match domain');
+ assert.equal(
+ patterns.test('https://www.example.org/images/2.jpg'),
+ true,
+ 'www subdomain should match',
+ );
+ assert.equal(
+ patterns.test('https://www.subdomain.example.org/images/2.jpg'),
+ false,
+ 'second level subdomain should not match',
+ );
+ assert.equal(
+ patterns.test('https://example.org/not-images/2.jpg'),
+ false,
+ 'wrong path should not match',
+ );
+ });
- it('maps Astro fit values to Netlify equivalents', () => {
- const cases = [
- ['contain', 'contain'],
- ['cover', 'cover'],
- ['fill', 'fill'],
- ['inside', 'contain'],
- ['outside', 'cover'],
- ['scale-down', 'contain'],
- ];
- for (const [astroFit, netlifyFit] of cases) {
- const url = imageService.getURL({
- src: 'img.jpg',
- width: 100,
- height: 100,
- fit: astroFit,
- });
- assert.ok(
- url.includes(`fit=${netlifyFit}`),
- `Expected fit=${netlifyFit} for astro fit="${astroFit}", got: ${url}`,
- );
- }
+ it('warns when remotepatterns generates an invalid regex', async (t) => {
+ const logger = {
+ warn: t.mock.fn(),
+ };
+ const regex = remotePatternToRegex(
+ {
+ hostname: '*.examp[le.org',
+ pathname: '/images/*',
+ },
+ logger,
+ );
+ assert.strictEqual(regex, undefined);
+ const calls = logger.warn.mock.calls;
+ assert.strictEqual(calls.length, 1);
+ assert.equal(
+ calls[0].arguments[0],
+ 'Could not generate a valid regex from the remotePattern "{"hostname":"*.examp[le.org","pathname":"/images/*"}". Please check the syntax.',
+ );
+ });
+ });
+
+ describe('fit parameter', () => {
+ it('includes fit parameter in image URL', () => {
+ const url = imageService.getURL({
+ src: 'images/astronaut.jpg',
+ width: 300,
+ height: 400,
+ fit: 'cover',
+ format: 'webp',
});
+ assert.ok(url.includes('fit=cover'), `Expected fit=cover in URL, got: ${url}`);
+ });
- it('omits fit parameter when fit is none or unset', () => {
- const withNone = imageService.getURL({
+ it('maps Astro fit values to Netlify equivalents', () => {
+ const cases = [
+ ['contain', 'contain'],
+ ['cover', 'cover'],
+ ['fill', 'fill'],
+ ['inside', 'contain'],
+ ['outside', 'cover'],
+ ['scale-down', 'contain'],
+ ];
+ for (const [astroFit, netlifyFit] of cases) {
+ const url = imageService.getURL({
src: 'img.jpg',
width: 100,
height: 100,
- fit: 'none',
+ fit: astroFit,
});
assert.ok(
- !withNone.includes('fit='),
- `Expected no fit param for fit="none", got: ${withNone}`,
+ url.includes(`fit=${netlifyFit}`),
+ `Expected fit=${netlifyFit} for astro fit="${astroFit}", got: ${url}`,
);
+ }
+ });
- const withoutFit = imageService.getURL({ src: 'img.jpg', width: 100, height: 100 });
- assert.ok(
- !withoutFit.includes('fit='),
- `Expected no fit param when unset, got: ${withoutFit}`,
- );
+ it('omits fit parameter when fit is none or unset', () => {
+ const withNone = imageService.getURL({
+ src: 'img.jpg',
+ width: 100,
+ height: 100,
+ fit: 'none',
});
+ assert.ok(
+ !withNone.includes('fit='),
+ `Expected no fit param for fit="none", got: ${withNone}`,
+ );
+
+ const withoutFit = imageService.getURL({ src: 'img.jpg', width: 100, height: 100 });
+ assert.ok(
+ !withoutFit.includes('fit='),
+ `Expected no fit param when unset, got: ${withoutFit}`,
+ );
});
- },
- {
- timeout: 120000,
- },
-);
+ });
+});
diff --git a/packages/integrations/netlify/test/functions/include-files.test.js b/packages/integrations/netlify/test/functions/include-files.test.js
index e54e116a78c3..31446785095f 100644
--- a/packages/integrations/netlify/test/functions/include-files.test.js
+++ b/packages/integrations/netlify/test/functions/include-files.test.js
@@ -6,179 +6,161 @@ import * as cheerio from 'cheerio';
import { globSync } from 'tinyglobby';
import { loadFixture } from '../../../../astro/test/test-utils.js';
-describe(
- 'Included vite assets files',
- () => {
- let fixture;
-
- const root = new URL('./fixtures/includes/', import.meta.url);
- const expectedCwd = new URL('.netlify/v1/functions/ssr/packages/integrations/netlify/', root);
-
- const expectedAssetsInclude = ['./*.json'];
- const excludedAssets = ['./files/exclude-asset.json'];
-
- before(async () => {
- fixture = await loadFixture({
- root,
- vite: {
- assetsInclude: expectedAssetsInclude,
- },
- adapter: netlify({
- excludeFiles: excludedAssets,
- }),
- });
- await fixture.build();
- });
+describe('Included vite assets files', { timeout: 120000 }, () => {
+ let fixture;
- it('Emits vite assets files', async () => {
- for (const pattern of expectedAssetsInclude) {
- const files = globSync(pattern);
- for (const file of files) {
- assert.ok(
- existsSync(new URL(file, expectedCwd)),
- `Expected file ${pattern} to exist in build`,
- );
- }
- }
+ const root = new URL('./fixtures/includes/', import.meta.url);
+ const expectedCwd = new URL('.netlify/v1/functions/ssr/packages/integrations/netlify/', root);
+
+ const expectedAssetsInclude = ['./*.json'];
+ const excludedAssets = ['./files/exclude-asset.json'];
+
+ before(async () => {
+ fixture = await loadFixture({
+ root,
+ vite: {
+ assetsInclude: expectedAssetsInclude,
+ },
+ adapter: netlify({
+ excludeFiles: excludedAssets,
+ }),
});
+ await fixture.build();
+ });
- it('Does not include vite assets files when excluded', async () => {
- for (const file of excludedAssets) {
+ it('Emits vite assets files', async () => {
+ for (const pattern of expectedAssetsInclude) {
+ const files = globSync(pattern);
+ for (const file of files) {
assert.ok(
- !existsSync(new URL(file, expectedCwd)),
- `Expected file ${file} to not exist in build`,
+ existsSync(new URL(file, expectedCwd)),
+ `Expected file ${pattern} to exist in build`,
);
}
+ }
+ });
+
+ it('Does not include vite assets files when excluded', async () => {
+ for (const file of excludedAssets) {
+ assert.ok(
+ !existsSync(new URL(file, expectedCwd)),
+ `Expected file ${file} to not exist in build`,
+ );
+ }
+ });
+
+ after(async () => {
+ await fixture.clean();
+ });
+});
+
+describe('Included files', { timeout: 120000 }, () => {
+ let fixture;
+
+ const root = new URL('./fixtures/includes/', import.meta.url);
+ const expectedCwd = new URL(
+ '.netlify/v1/functions/ssr/packages/integrations/netlify/test/functions/fixtures/includes/',
+ root,
+ );
+
+ const expectedFiles = [
+ './files/include-this.txt',
+ './files/also-this.csv',
+ './files/subdirectory/and-this.csv',
+ ];
+
+ before(async () => {
+ fixture = await loadFixture({
+ root,
+ adapter: netlify({
+ includeFiles: expectedFiles,
+ }),
});
-
- after(async () => {
- await fixture.clean();
- });
- },
- {
- timeout: 120000,
- },
-);
-
-describe(
- 'Included files',
- () => {
- let fixture;
-
- const root = new URL('./fixtures/includes/', import.meta.url);
- const expectedCwd = new URL(
- '.netlify/v1/functions/ssr/packages/integrations/netlify/test/functions/fixtures/includes/',
+ await fixture.build();
+ });
+
+ it('Emits include files', async () => {
+ for (const file of expectedFiles) {
+ assert.ok(existsSync(new URL(file, expectedCwd)), `Expected file ${file} to exist`);
+ }
+ });
+
+ it('Can load included files correctly', async () => {
+ const entryURL = new URL(
+ './fixtures/includes/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(new Request('http://example.com/?file=include-this.txt'), {});
+ const html = await resp.text();
+ const $ = cheerio.load(html);
+ assert.equal($('h1').text(), 'hello');
+ });
+
+ it('Includes traced node modules with symlinks', async () => {
+ const expected = new URL(
+ '.netlify/v1/functions/ssr/node_modules/.pnpm/cowsay@1.6.0/node_modules/cowsay/cows/happy-whale.cow',
root,
);
+ assert.ok(existsSync(expected, 'Expected excluded file to exist in default build'));
+ });
- const expectedFiles = [
- './files/include-this.txt',
- './files/also-this.csv',
- './files/subdirectory/and-this.csv',
- ];
-
- before(async () => {
- fixture = await loadFixture({
- root,
- adapter: netlify({
- includeFiles: expectedFiles,
- }),
- });
- await fixture.build();
- });
+ after(async () => {
+ await fixture.clean();
+ });
+});
- it('Emits include files', async () => {
- for (const file of expectedFiles) {
- assert.ok(existsSync(new URL(file, expectedCwd)), `Expected file ${file} to exist`);
- }
- });
+describe('Excluded files', { timeout: 120000 }, () => {
+ let fixture;
- it('Can load included files correctly', async () => {
- const entryURL = new URL(
- './fixtures/includes/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(new Request('http://example.com/?file=include-this.txt'), {});
- const html = await resp.text();
- const $ = cheerio.load(html);
- assert.equal($('h1').text(), 'hello');
- });
+ const root = new URL('./fixtures/includes/', import.meta.url);
+ const expectedCwd = new URL(
+ '.netlify/v1/functions/ssr/packages/integrations/netlify/test/functions/fixtures/includes/',
+ root,
+ );
- it('Includes traced node modules with symlinks', async () => {
- const expected = new URL(
- '.netlify/v1/functions/ssr/node_modules/.pnpm/cowsay@1.6.0/node_modules/cowsay/cows/happy-whale.cow',
- root,
- );
- assert.ok(existsSync(expected, 'Expected excluded file to exist in default build'));
- });
+ const includeFiles = ['./files/**/*.txt'];
+ const excludedTxt = ['./files/subdirectory/not-this.txt', './files/subdirectory/or-this.txt'];
+ const excludeFiles = [...excludedTxt, '../../../../../../../node_modules/.pnpm/cowsay@*/**'];
- after(async () => {
- await fixture.clean();
- });
- },
- {
- timeout: 120000,
- },
-);
-
-describe(
- 'Excluded files',
- () => {
- let fixture;
-
- const root = new URL('./fixtures/includes/', import.meta.url);
- const expectedCwd = new URL(
- '.netlify/v1/functions/ssr/packages/integrations/netlify/test/functions/fixtures/includes/',
+ before(async () => {
+ fixture = await loadFixture({
root,
- );
-
- const includeFiles = ['./files/**/*.txt'];
- const excludedTxt = ['./files/subdirectory/not-this.txt', './files/subdirectory/or-this.txt'];
- const excludeFiles = [...excludedTxt, '../../../../../../../node_modules/.pnpm/cowsay@*/**'];
-
- before(async () => {
- fixture = await loadFixture({
- root,
- adapter: netlify({
- includeFiles: includeFiles,
- excludeFiles: excludeFiles,
- }),
- });
- await fixture.build();
+ adapter: netlify({
+ includeFiles: includeFiles,
+ excludeFiles: excludeFiles,
+ }),
});
+ await fixture.build();
+ });
- it('Excludes traced node modules', async () => {
- const expected = new URL(
- '.netlify/v1/functions/ssr/node_modules/.pnpm/cowsay@1.6.0/node_modules/cowsay/cows/happy-whale.cow',
- root,
- );
- assert.ok(!existsSync(expected), 'Expected excluded file to not exist in build');
- });
+ it('Excludes traced node modules', async () => {
+ const expected = new URL(
+ '.netlify/v1/functions/ssr/node_modules/.pnpm/cowsay@1.6.0/node_modules/cowsay/cows/happy-whale.cow',
+ root,
+ );
+ assert.ok(!existsSync(expected), 'Expected excluded file to not exist in build');
+ });
- it('Does not include files when excluded', async () => {
- for (const pattern of includeFiles) {
- const files = globSync(pattern, { ignore: excludedTxt });
- for (const file of files) {
- assert.ok(
- existsSync(new URL(file, expectedCwd)),
- `Expected file ${pattern} to exist in build`,
- );
- }
- }
- for (const file of excludedTxt) {
+ it('Does not include files when excluded', async () => {
+ for (const pattern of includeFiles) {
+ const files = globSync(pattern, { ignore: excludedTxt });
+ for (const file of files) {
assert.ok(
- !existsSync(new URL(file, expectedCwd)),
- `Expected file ${file} to not exist in build`,
+ existsSync(new URL(file, expectedCwd)),
+ `Expected file ${pattern} to exist in build`,
);
}
- });
+ }
+ for (const file of excludedTxt) {
+ assert.ok(
+ !existsSync(new URL(file, expectedCwd)),
+ `Expected file ${file} to not exist in build`,
+ );
+ }
+ });
- after(async () => {
- await fixture.clean();
- });
- },
- {
- timeout: 120000,
- },
-);
+ after(async () => {
+ await fixture.clean();
+ });
+});
diff --git a/packages/integrations/netlify/test/functions/redirects.test.js b/packages/integrations/netlify/test/functions/redirects.test.js
index 2c55aecb9ec5..93df3f16202f 100644
--- a/packages/integrations/netlify/test/functions/redirects.test.js
+++ b/packages/integrations/netlify/test/functions/redirects.test.js
@@ -3,66 +3,60 @@ import { createServer } from 'node:http';
import { before, describe, it } from 'node:test';
import { loadFixture } from '../../../../astro/test/test-utils.js';
-describe(
- 'SSR - Redirects',
- () => {
- let fixture;
+describe('SSR - Redirects', { timeout: 120000 }, () => {
+ let fixture;
- before(async () => {
- fixture = await loadFixture({ root: new URL('./fixtures/redirects/', import.meta.url) });
- await fixture.build();
- });
+ before(async () => {
+ fixture = await loadFixture({ root: new URL('./fixtures/redirects/', import.meta.url) });
+ await fixture.build();
+ });
- it('Creates a redirects file', async () => {
- const redirects = await fixture.readFile('./_redirects');
- const parts = redirects.split(/\s+/);
- // based on https://github.com/withastro/astro/issues/16030 for the default option `trailingSlash: 'ignore'` both variants should be generated
- assert.deepEqual(parts, ['', '/other/', '/', '301', '/other', '/', '301', '']);
- });
+ it('Creates a redirects file', async () => {
+ const redirects = await fixture.readFile('./_redirects');
+ const parts = redirects.split(/\s+/);
+ // based on https://github.com/withastro/astro/issues/16030 for the default option `trailingSlash: 'ignore'` both variants should be generated
+ assert.deepEqual(parts, ['', '/other/', '/', '301', '/other', '/', '301', '']);
+ });
- it('Does not create .html files', async () => {
- let hasErrored = false;
- try {
- await fixture.readFile('/other/index.html');
- } catch {
- hasErrored = true;
- }
- assert.equal(hasErrored, true, 'this file should not exist');
- });
+ it('Does not create .html files', async () => {
+ let hasErrored = false;
+ try {
+ await fixture.readFile('/other/index.html');
+ } catch {
+ hasErrored = true;
+ }
+ assert.equal(hasErrored, true, 'this file should not exist');
+ });
- it('renders static 404 page', async () => {
- const entryURL = new URL(
- './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(new Request('http://example.com/nonexistant-page'), {});
- assert.equal(resp.status, 404);
- assert.equal(resp.headers.get('content-type'), 'text/html; charset=utf-8');
- const text = await resp.text();
- assert.equal(text.includes('This is my static 404 page'), true);
- });
+ it('renders static 404 page', async () => {
+ const entryURL = new URL(
+ './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(new Request('http://example.com/nonexistant-page'), {});
+ assert.equal(resp.status, 404);
+ assert.equal(resp.headers.get('content-type'), 'text/html; charset=utf-8');
+ const text = await resp.text();
+ assert.equal(text.includes('This is my static 404 page'), true);
+ });
- it('does not pass through 404 request', async () => {
- let testServerCalls = 0;
- const testServer = createServer((_req, res) => {
- testServerCalls++;
- res.writeHead(200);
- res.end();
- });
- testServer.listen(5678);
- const entryURL = new URL(
- './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(new Request('http://localhost:5678/nonexistant-page'), {});
- assert.equal(resp.status, 404);
- assert.equal(testServerCalls, 0);
- testServer.close();
+ it('does not pass through 404 request', async () => {
+ let testServerCalls = 0;
+ const testServer = createServer((_req, res) => {
+ testServerCalls++;
+ res.writeHead(200);
+ res.end();
});
- },
- {
- timeout: 120000,
- },
-);
+ testServer.listen(5678);
+ const entryURL = new URL(
+ './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(new Request('http://localhost:5678/nonexistant-page'), {});
+ assert.equal(resp.status, 404);
+ assert.equal(testServerCalls, 0);
+ testServer.close();
+ });
+});
diff --git a/packages/integrations/netlify/test/functions/skew-protection.test.js b/packages/integrations/netlify/test/functions/skew-protection.test.js
index ee5f8c840689..6d639d83b586 100644
--- a/packages/integrations/netlify/test/functions/skew-protection.test.js
+++ b/packages/integrations/netlify/test/functions/skew-protection.test.js
@@ -3,68 +3,62 @@ import { readFile } from 'node:fs/promises';
import { before, describe, it } from 'node:test';
import { loadFixture } from '../../../../astro/test/test-utils.js';
-describe(
- 'Skew Protection',
- () => {
- let fixture;
+describe('Skew Protection', { timeout: 120000 }, () => {
+ let fixture;
- before(async () => {
- // Set DEPLOY_ID env var for the test
- process.env.DEPLOY_ID = 'test-deploy-123';
+ before(async () => {
+ // Set DEPLOY_ID env var for the test
+ process.env.DEPLOY_ID = 'test-deploy-123';
- fixture = await loadFixture({
- root: new URL('./fixtures/skew-protection/', import.meta.url),
- });
- await fixture.build();
-
- // Clean up
- delete process.env.DEPLOY_ID;
+ fixture = await loadFixture({
+ root: new URL('./fixtures/skew-protection/', import.meta.url),
});
+ await fixture.build();
- it('Server islands inline adapter headers', async () => {
- // Render a page with server islands and check the HTML contains inline headers
- const entryURL = new URL(
- './fixtures/skew-protection/.netlify/v1/functions/ssr/ssr.mjs',
- import.meta.url,
- );
- const { default: handler } = await import(entryURL);
- const resp = await handler(new Request('http://example.com/server-island'), {});
- const html = await resp.text();
+ // Clean up
+ delete process.env.DEPLOY_ID;
+ });
- // Check that the HTML contains the inline headers in the server island script
- // Should have something like: const headers = new Headers({"X-Netlify-Deploy-ID":"test-deploy-123"});
- assert.ok(
- html.includes('test-deploy-123'),
- 'Expected server island HTML to include deploy ID in inline script',
- );
- });
+ it('Server islands inline adapter headers', async () => {
+ // Render a page with server islands and check the HTML contains inline headers
+ const entryURL = new URL(
+ './fixtures/skew-protection/.netlify/v1/functions/ssr/ssr.mjs',
+ import.meta.url,
+ );
+ const { default: handler } = await import(entryURL);
+ const resp = await handler(new Request('http://example.com/server-island'), {});
+ const html = await resp.text();
- it('Manifest contains internalFetchHeaders', async () => {
- // The manifest is embedded in the build output
- // Check the manifest file which contains the serialized manifest
- const manifestURL = new URL(
- './fixtures/skew-protection/.netlify/build/chunks/',
- import.meta.url,
- );
+ // Check that the HTML contains the inline headers in the server island script
+ // Should have something like: const headers = new Headers({"X-Netlify-Deploy-ID":"test-deploy-123"});
+ assert.ok(
+ html.includes('test-deploy-123'),
+ 'Expected server island HTML to include deploy ID in inline script',
+ );
+ });
- // Find the manifest file (it has a hash in the name)
- const { readdir } = await import('node:fs/promises');
- const files = await readdir(manifestURL);
- let found = false;
- for (const file of files) {
- const contents = await readFile(new URL(file, manifestURL), 'utf-8');
- if (contents.includes('"internalFetchHeaders":{"X-Netlify-Deploy-ID":"test-deploy-123"}')) {
- found = true;
- break;
- }
+ it('Manifest contains internalFetchHeaders', async () => {
+ // The manifest is embedded in the build output
+ // Check the manifest file which contains the serialized manifest
+ const manifestURL = new URL(
+ './fixtures/skew-protection/.netlify/build/chunks/',
+ import.meta.url,
+ );
+
+ // Find the manifest file (it has a hash in the name)
+ const { readdir } = await import('node:fs/promises');
+ const files = await readdir(manifestURL);
+ let found = false;
+ for (const file of files) {
+ const contents = await readFile(new URL(file, manifestURL), 'utf-8');
+ if (contents.includes('"internalFetchHeaders":{"X-Netlify-Deploy-ID":"test-deploy-123"}')) {
+ found = true;
+ break;
}
- assert.ok(
- found,
- 'Manifest should include internalFetchHeaders field with the correct deploy ID value',
- );
- });
- },
- {
- timeout: 120000,
- },
-);
+ }
+ assert.ok(
+ found,
+ 'Manifest should include internalFetchHeaders field with the correct deploy ID value',
+ );
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2aba4345a3e3..7867b4d32a99 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1921,18 +1921,6 @@ importers:
specifier: ^5.54.0
version: 5.55.3
- packages/astro/test/fixtures/alias-tsconfig-baseurl-only:
- dependencies:
- '@astrojs/svelte':
- specifier: workspace:*
- version: link:../../../../integrations/svelte
- astro:
- specifier: workspace:*
- version: link:../../..
- svelte:
- specifier: ^5.54.0
- version: 5.55.3
-
packages/astro/test/fixtures/alias-tsconfig-no-baseurl:
dependencies:
astro:
@@ -2447,12 +2435,6 @@ importers:
specifier: ^4.2.2
version: 4.2.2
- packages/astro/test/fixtures/astro-sitemap-rss:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/astro-slot-with-client:
dependencies:
'@astrojs/preact':
@@ -2637,12 +2619,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/config-path:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/config-vite:
dependencies:
astro:
@@ -2730,12 +2706,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/content-collections-cache-invalidation:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/content-collections-empty-dir:
dependencies:
astro:
@@ -2766,12 +2736,6 @@ importers:
specifier: ^4.3.6
version: 4.3.6
- packages/astro/test/fixtures/content-collections-same-contents:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/content-collections-type-inference:
dependencies:
astro:
@@ -3191,12 +3155,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/custom-500-middleware:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/custom-assets-name:
dependencies:
'@astrojs/node':
@@ -3320,12 +3278,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/feature-support-message-suppresion:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/fetch:
dependencies:
'@astrojs/preact':
@@ -3380,12 +3332,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/head-injection:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/hmr-markdown:
dependencies:
astro:
@@ -3597,24 +3543,12 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/middleware-sequence-request-clone:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/middleware-sequence-rewrite:
dependencies:
astro:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/middleware-ssg:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/middleware-tailwind:
dependencies:
'@tailwindcss/vite':
@@ -3627,12 +3561,6 @@ importers:
specifier: ^4.2.2
version: 4.2.2
- packages/astro/test/fixtures/middleware-virtual:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/minification-html:
dependencies:
astro:
@@ -4230,21 +4158,6 @@ importers:
specifier: ^10.29.0
version: 10.29.0
- packages/astro/test/fixtures/ssr-split-manifest:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
- packages/astro/test/fixtures/ssr-trailing-slash:
- dependencies:
- '@astrojs/node':
- specifier: workspace:*
- version: link:../../../../integrations/node
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/static-build:
dependencies:
'@astrojs/preact':
@@ -4448,24 +4361,6 @@ importers:
specifier: ^3.5.30
version: 3.5.30(typescript@5.9.3)
- packages/astro/test/fixtures/with-endpoint-routes:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
- packages/astro/test/fixtures/with-subpath-no-trailing-slash:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
- packages/astro/test/fixtures/without-site-config:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/create-astro:
dependencies:
'@astrojs/cli-kit':