diff options
Diffstat (limited to 'packages/integrations/sitemap/test')
32 files changed, 821 insertions, 0 deletions
diff --git a/packages/integrations/sitemap/test/base-path.test.js b/packages/integrations/sitemap/test/base-path.test.js new file mode 100644 index 000000000..fee031ff4 --- /dev/null +++ b/packages/integrations/sitemap/test/base-path.test.js @@ -0,0 +1,52 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('URLs with base path', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + describe('using node adapter', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr/', + base: '/base', + }); + await fixture.build(); + }); + + it('Base path is concatenated correctly', async () => { + const [sitemapZero, sitemapIndex] = await Promise.all([ + readXML(fixture.readFile('/client/sitemap-0.xml')), + readXML(fixture.readFile('/client/sitemap-index.xml')), + ]); + assert.equal(sitemapZero.urlset.url[0].loc[0], 'http://example.com/base/one/'); + assert.equal( + sitemapIndex.sitemapindex.sitemap[0].loc[0], + 'http://example.com/base/sitemap-0.xml', + ); + }); + }); + + describe('static', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + base: '/base', + }); + await fixture.build(); + }); + + it('Base path is concatenated correctly', async () => { + const [sitemapZero, sitemapIndex] = await Promise.all([ + readXML(fixture.readFile('/sitemap-0.xml')), + readXML(fixture.readFile('/sitemap-index.xml')), + ]); + assert.equal(sitemapZero.urlset.url[0].loc[0], 'http://example.com/base/123/'); + assert.equal( + sitemapIndex.sitemapindex.sitemap[0].loc[0], + 'http://example.com/base/sitemap-0.xml', + ); + }); + }); +}); diff --git a/packages/integrations/sitemap/test/config.test.js b/packages/integrations/sitemap/test/config.test.js new file mode 100644 index 000000000..f95333876 --- /dev/null +++ b/packages/integrations/sitemap/test/config.test.js @@ -0,0 +1,125 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { sitemap } from './fixtures/static/deps.mjs'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('Config', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + describe('Static', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + integrations: [ + sitemap({ + filter: (page) => page === 'http://example.com/one/', + xslURL: '/sitemap.xsl', + }), + ], + }); + await fixture.build(); + }); + + it('filter: Just one page is added', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls.length, 1); + }); + + it('xslURL: Includes xml-stylesheet', async () => { + const indexXml = await fixture.readFile('/sitemap-index.xml'); + assert.ok( + indexXml.includes( + '<?xml-stylesheet type="text/xsl" href="http://example.com/sitemap.xsl"?>', + ), + indexXml, + ); + + const xml = await fixture.readFile('/sitemap-0.xml'); + assert.ok( + xml.includes('<?xml-stylesheet type="text/xsl" href="http://example.com/sitemap.xsl"?>'), + xml, + ); + }); + }); + + describe('SSR', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr/', + integrations: [ + sitemap({ + filter: (page) => page === 'http://example.com/one/', + xslURL: '/sitemap.xsl', + }), + ], + }); + await fixture.build(); + }); + + it('filter: Just one page is added', async () => { + const data = await readXML(fixture.readFile('/client/sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls.length, 1); + }); + + it('xslURL: Includes xml-stylesheet', async () => { + const indexXml = await fixture.readFile('/client/sitemap-index.xml'); + assert.ok( + indexXml.includes( + '<?xml-stylesheet type="text/xsl" href="http://example.com/sitemap.xsl"?>', + ), + indexXml, + ); + + const xml = await fixture.readFile('/client/sitemap-0.xml'); + assert.ok( + xml.includes('<?xml-stylesheet type="text/xsl" href="http://example.com/sitemap.xsl"?>'), + xml, + ); + }); + }); + + describe('Configuring the filename', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + integrations: [ + sitemap({ + filter: (page) => page === 'http://example.com/one/', + filenameBase: 'my-sitemap', + }), + ], + }); + await fixture.build(); + }); + + it('filenameBase: Sets the generated sitemap filename', async () => { + const data = await readXML(fixture.readFile('/my-sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls.length, 1); + + const indexData = await readXML(fixture.readFile('/my-sitemap-index.xml')); + const sitemapUrls = indexData.sitemapindex.sitemap; + assert.equal(sitemapUrls.length, 1); + assert.equal(sitemapUrls[0].loc[0], 'http://example.com/my-sitemap-0.xml'); + }); + }); + + describe('Filtering pages - error handling', () => { + it('filter: uncaught errors are thrown', async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + integrations: [ + sitemap({ + filter: () => { + throw new Error('filter error'); + }, + }), + ], + }); + await assert.rejects(fixture.build(), /^Error: filter error$/); + }); + }); +}); diff --git a/packages/integrations/sitemap/test/dynamic-path.test.js b/packages/integrations/sitemap/test/dynamic-path.test.js new file mode 100644 index 000000000..eab3b912c --- /dev/null +++ b/packages/integrations/sitemap/test/dynamic-path.test.js @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('Dynamic with rest parameter', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/dynamic', + }); + await fixture.build(); + }); + + it('Should generate correct urls', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url.map((url) => url.loc[0]); + + assert.ok(urls.includes('http://example.com/')); + assert.ok(urls.includes('http://example.com/blog/')); + assert.ok(urls.includes('http://example.com/test/')); + }); +}); diff --git a/packages/integrations/sitemap/test/fixtures/dynamic/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/dynamic/astro.config.mjs new file mode 100644 index 000000000..82d25b854 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/dynamic/astro.config.mjs @@ -0,0 +1,7 @@ +import sitemap from '@astrojs/sitemap'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [sitemap()], + site: 'http://example.com' +}) diff --git a/packages/integrations/sitemap/test/fixtures/dynamic/package.json b/packages/integrations/sitemap/test/fixtures/dynamic/package.json new file mode 100644 index 000000000..1eac19a1b --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/dynamic/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/sitemap-dynamic", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/packages/integrations/sitemap/test/fixtures/dynamic/src/pages/[...slug].astro b/packages/integrations/sitemap/test/fixtures/dynamic/src/pages/[...slug].astro new file mode 100644 index 000000000..9622cb374 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/dynamic/src/pages/[...slug].astro @@ -0,0 +1,21 @@ +--- +export async function getStaticPaths() { + return [ + { + params: { + slug: undefined, + } + }, + { + params: { + slug: '/blog' + } + }, + { + params: { + slug: '/test' + } + } + ]; +} +--- diff --git a/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs new file mode 100644 index 000000000..ce84944bf --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs @@ -0,0 +1,12 @@ +import nodeServer from '@astrojs/node' +import sitemap from '@astrojs/sitemap'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [sitemap()], + site: 'http://example.com', + output: 'server', + adapter: nodeServer({ + mode: "standalone" + }) +}) diff --git a/packages/integrations/sitemap/test/fixtures/ssr/package.json b/packages/integrations/sitemap/test/fixtures/ssr/package.json new file mode 100644 index 000000000..4b5e6848d --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/package.json @@ -0,0 +1,10 @@ +{ + "name": "@test/sitemap-ssr", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/node": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>One</title> + </head> + <body> + <h1>One</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>Two</title> + </head> + <body> + <h1>Two</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs new file mode 100644 index 000000000..ae53a9342 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs @@ -0,0 +1,18 @@ +import sitemap from '@astrojs/sitemap'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [sitemap({ + i18n: { + defaultLocale: 'it', + locales: { + it: 'it-IT', + de: 'de-DE', + } + } + })], + site: 'http://example.com', + redirects: { + '/redirect': '/' + }, +}) diff --git a/packages/integrations/sitemap/test/fixtures/static/deps.mjs b/packages/integrations/sitemap/test/fixtures/static/deps.mjs new file mode 100644 index 000000000..b24f26189 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/deps.mjs @@ -0,0 +1 @@ +export { default as sitemap } from '@astrojs/sitemap'; diff --git a/packages/integrations/sitemap/test/fixtures/static/package.json b/packages/integrations/sitemap/test/fixtures/static/package.json new file mode 100644 index 000000000..ed5f3670b --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/sitemap-static", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/123.astro b/packages/integrations/sitemap/test/fixtures/static/src/pages/123.astro new file mode 100644 index 000000000..115292de9 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/123.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>123</title> + </head> + <body> + <h1>123</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/404.astro b/packages/integrations/sitemap/test/fixtures/static/src/pages/404.astro new file mode 100644 index 000000000..9e307c5c2 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/404.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>404</title> + </head> + <body> + <h1>404</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/[lang]/manifest.ts b/packages/integrations/sitemap/test/fixtures/static/src/pages/[lang]/manifest.ts new file mode 100644 index 000000000..907b94a21 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/[lang]/manifest.ts @@ -0,0 +1,15 @@ +export const GET: APIRoute = async ({ params }) => { + const { lang } = params; + + return new Response(`I'm a route in the "${lang}" language.`); +}; + +export async function getStaticPaths() { + return ['it', 'en'].map((language) => { + return { + params: { + lang: language, + }, + }; + }); +} diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/[slug].astro b/packages/integrations/sitemap/test/fixtures/static/src/pages/[slug].astro new file mode 100644 index 000000000..205633c76 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/[slug].astro @@ -0,0 +1,17 @@ +--- +export function getStaticPaths() { + return [ + { params: { slug: 'one' }, props: { title: 'One' } }, + { params: { slug: 'two' }, props: { title: 'Two' } }, + ] +} +--- + +<html> + <head> + <title>{Astro.props.title}</title> + </head> + <body> + <h1>{Astro.props.title}</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/de/404.astro b/packages/integrations/sitemap/test/fixtures/static/src/pages/de/404.astro new file mode 100644 index 000000000..9e307c5c2 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/de/404.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>404</title> + </head> + <body> + <h1>404</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/endpoint.json.ts b/packages/integrations/sitemap/test/fixtures/static/src/pages/endpoint.json.ts new file mode 100644 index 000000000..2e088376f --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/endpoint.json.ts @@ -0,0 +1,6 @@ +export async function GET({}) { + return Response.json({ + name: 'Astro', + url: 'https://astro.build/', + }); +} diff --git a/packages/integrations/sitemap/test/fixtures/static/src/pages/products-by-id/[id].astro b/packages/integrations/sitemap/test/fixtures/static/src/pages/products-by-id/[id].astro new file mode 100644 index 000000000..b10438a68 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/static/src/pages/products-by-id/[id].astro @@ -0,0 +1,11 @@ +--- +export async function getStaticPaths() { + return [ + { params: { id: '404' } }, + { params: { id: '405' } }, + ] +} + +const { id } = Astro.params +--- +<!DOCTYPE html><html> <head><title>Product #{id}</title></head> <body> <h1>Product #404</h1> <p>This is a product that just happens to have an ID of {id}. It is found!</p></body></html>
\ No newline at end of file diff --git a/packages/integrations/sitemap/test/fixtures/trailing-slash/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/trailing-slash/astro.config.mjs new file mode 100644 index 000000000..82d25b854 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/trailing-slash/astro.config.mjs @@ -0,0 +1,7 @@ +import sitemap from '@astrojs/sitemap'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [sitemap()], + site: 'http://example.com' +}) diff --git a/packages/integrations/sitemap/test/fixtures/trailing-slash/package.json b/packages/integrations/sitemap/test/fixtures/trailing-slash/package.json new file mode 100644 index 000000000..980e02e73 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/trailing-slash/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/sitemap-trailing-slash", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/index.astro b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/index.astro new file mode 100644 index 000000000..5a29cbdbe --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/index.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>Index</title> + </head> + <body> + <h1>Index</h1> + </body> +</html>
\ No newline at end of file diff --git a/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/one.astro b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/one.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>One</title> + </head> + <body> + <h1>One</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/two.astro b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/trailing-slash/src/pages/two.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>Two</title> + </head> + <body> + <h1>Two</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/routes.test.js b/packages/integrations/sitemap/test/routes.test.js new file mode 100644 index 000000000..00d6ccde3 --- /dev/null +++ b/packages/integrations/sitemap/test/routes.test.js @@ -0,0 +1,27 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('routes', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + /** @type {string[]} */ + let urls; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + }); + await fixture.build(); + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + urls = data.urlset.url.map((url) => url.loc[0]); + }); + + it('does not include endpoints', async () => { + assert.equal(urls.includes('http://example.com/endpoint.json'), false); + }); + + it('does not include redirects', async () => { + assert.equal(urls.includes('http://example.com/redirect'), false); + }); +}); diff --git a/packages/integrations/sitemap/test/smoke.test.js b/packages/integrations/sitemap/test/smoke.test.js new file mode 100644 index 000000000..d24c191ec --- /dev/null +++ b/packages/integrations/sitemap/test/smoke.test.js @@ -0,0 +1,3 @@ +import '../dist/index.js'; + +// Just a smoke test, this would fail if there's a problem. diff --git a/packages/integrations/sitemap/test/ssr.test.js b/packages/integrations/sitemap/test/ssr.test.js new file mode 100644 index 000000000..b5c92698b --- /dev/null +++ b/packages/integrations/sitemap/test/ssr.test.js @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('SSR support', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr/', + }); + await fixture.build(); + }); + + it('SSR pages require zero config', async () => { + const data = await readXML(fixture.readFile('/client/sitemap-0.xml')); + const urls = data.urlset.url; + + assert.equal(urls[0].loc[0], 'http://example.com/one/'); + assert.equal(urls[1].loc[0], 'http://example.com/two/'); + }); +}); diff --git a/packages/integrations/sitemap/test/staticPaths.test.js b/packages/integrations/sitemap/test/staticPaths.test.js new file mode 100644 index 000000000..7df9d5cb6 --- /dev/null +++ b/packages/integrations/sitemap/test/staticPaths.test.js @@ -0,0 +1,48 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('getStaticPaths support', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + /** @type {string[]} */ + let urls; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/static/', + trailingSlash: 'always', + }); + await fixture.build(); + + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + urls = data.urlset.url.map((url) => url.loc[0]); + }); + + it('requires zero config for getStaticPaths', async () => { + assert.equal(urls.includes('http://example.com/one/'), true); + assert.equal(urls.includes('http://example.com/two/'), true); + }); + + it('does not include 404 pages', () => { + assert.equal(urls.includes('http://example.com/404/'), false); + }); + + it('does not include nested 404 pages', () => { + assert.equal(urls.includes('http://example.com/de/404/'), false); + }); + + it('includes numerical pages', () => { + assert.equal(urls.includes('http://example.com/123/'), true); + }); + + it('includes numerical 404 pages if not for i18n', () => { + assert.equal(urls.includes('http://example.com/products-by-id/405/'), true); + assert.equal(urls.includes('http://example.com/products-by-id/404/'), true); + }); + + it('should render the endpoint', async () => { + const page = await fixture.readFile('./it/manifest'); + assert.match(page, /I'm a route in the "it" language./); + }); +}); diff --git a/packages/integrations/sitemap/test/test-utils.js b/packages/integrations/sitemap/test/test-utils.js new file mode 100644 index 000000000..74bba6a44 --- /dev/null +++ b/packages/integrations/sitemap/test/test-utils.js @@ -0,0 +1,29 @@ +import * as xml2js from 'xml2js'; +import { loadFixture as baseLoadFixture } from '../../../astro/test/test-utils.js'; + +/** + * @typedef {import('../../../astro/test/test-utils').Fixture} Fixture + */ + +export function loadFixture(inlineConfig) { + if (!inlineConfig?.root) throw new Error("Must provide { root: './fixtures/...' }"); + + // resolve the relative root (i.e. "./fixtures/tailwindcss") to a full filepath + // without this, the main `loadFixture` helper will resolve relative to `packages/astro/test` + return baseLoadFixture({ + ...inlineConfig, + root: new URL(inlineConfig.root, import.meta.url).toString(), + }); +} + +export function readXML(fileOrPromise) { + const parseString = xml2js.parseString; + return Promise.resolve(fileOrPromise).then((xml) => { + return new Promise((resolve, reject) => { + parseString(xml, function (err, result) { + if (err) return reject(err); + resolve(result); + }); + }); + }); +} diff --git a/packages/integrations/sitemap/test/trailing-slash.test.js b/packages/integrations/sitemap/test/trailing-slash.test.js new file mode 100644 index 000000000..181f0def5 --- /dev/null +++ b/packages/integrations/sitemap/test/trailing-slash.test.js @@ -0,0 +1,127 @@ +import assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture, readXML } from './test-utils.js'; + +describe('Trailing slash', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + describe('trailingSlash: ignore', () => { + describe('build.format: directory', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'ignore', + build: { + format: 'directory', + }, + }); + await fixture.build(); + }); + + it('URLs end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + + assert.equal(urls[0].loc[0], 'http://example.com/'); + assert.equal(urls[1].loc[0], 'http://example.com/one/'); + assert.equal(urls[2].loc[0], 'http://example.com/two/'); + }); + }); + + describe('build.format: file', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'ignore', + build: { + format: 'file', + }, + }); + await fixture.build(); + }); + + it('URLs do not end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + + assert.equal(urls[0].loc[0], 'http://example.com'); + assert.equal(urls[1].loc[0], 'http://example.com/one'); + assert.equal(urls[2].loc[0], 'http://example.com/two'); + }); + }); + }); + + describe('trailingSlash: never', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'never', + }); + await fixture.build(); + }); + + it('URLs do not end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + + assert.equal(urls[0].loc[0], 'http://example.com'); + assert.equal(urls[1].loc[0], 'http://example.com/one'); + assert.equal(urls[2].loc[0], 'http://example.com/two'); + }); + describe('with base path', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'never', + base: '/base', + }); + await fixture.build(); + }); + + it('URLs do not end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls[0].loc[0], 'http://example.com/base'); + assert.equal(urls[1].loc[0], 'http://example.com/base/one'); + assert.equal(urls[2].loc[0], 'http://example.com/base/two'); + }); + }); + }); + + describe('trailingSlash: always', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'always', + }); + await fixture.build(); + }); + + it('URLs end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls[0].loc[0], 'http://example.com/'); + assert.equal(urls[1].loc[0], 'http://example.com/one/'); + assert.equal(urls[2].loc[0], 'http://example.com/two/'); + }); + describe('with base path', () => { + before(async () => { + fixture = await loadFixture({ + root: './fixtures/trailing-slash/', + trailingSlash: 'always', + base: '/base', + }); + await fixture.build(); + }); + + it('URLs end with trailing slash', async () => { + const data = await readXML(fixture.readFile('/sitemap-0.xml')); + const urls = data.urlset.url; + assert.equal(urls[0].loc[0], 'http://example.com/base/'); + assert.equal(urls[1].loc[0], 'http://example.com/base/one/'); + assert.equal(urls[2].loc[0], 'http://example.com/base/two/'); + }); + }); + }); +}); diff --git a/packages/integrations/sitemap/test/units/generate-sitemap.test.js b/packages/integrations/sitemap/test/units/generate-sitemap.test.js new file mode 100644 index 000000000..fbf4e7858 --- /dev/null +++ b/packages/integrations/sitemap/test/units/generate-sitemap.test.js @@ -0,0 +1,147 @@ +import assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; +import { generateSitemap } from '../../dist/generate-sitemap.js'; + +const site = 'http://example.com'; + +describe('generateSitemap', () => { + describe('basic', () => { + it('works', () => { + const items = generateSitemap( + [ + // All pages + `${site}/a`, + `${site}/b`, + `${site}/c`, + ], + site, + ); + assert.equal(items.length, 3); + assert.equal(items[0].url, `${site}/a`); + assert.equal(items[1].url, `${site}/b`); + assert.equal(items[2].url, `${site}/c`); + }); + + it('sorts the items', () => { + const items = generateSitemap( + [ + // All pages + `${site}/c`, + `${site}/a`, + `${site}/b`, + ], + site, + ); + assert.equal(items.length, 3); + assert.equal(items[0].url, `${site}/a`); + assert.equal(items[1].url, `${site}/b`); + assert.equal(items[2].url, `${site}/c`); + }); + + it('sitemap props are passed to items', () => { + const now = new Date(); + const items = generateSitemap( + [ + // All pages + `${site}/a`, + `${site}/b`, + `${site}/c`, + ], + site, + { + changefreq: 'monthly', + lastmod: now, + priority: 0.5, + }, + ); + + assert.equal(items.length, 3); + + assert.equal(items[0].url, `${site}/a`); + assert.equal(items[0].changefreq, 'monthly'); + assert.equal(items[0].lastmod, now.toISOString()); + assert.equal(items[0].priority, 0.5); + + assert.equal(items[1].url, `${site}/b`); + assert.equal(items[1].changefreq, 'monthly'); + assert.equal(items[1].lastmod, now.toISOString()); + assert.equal(items[1].priority, 0.5); + + assert.equal(items[2].url, `${site}/c`); + assert.equal(items[2].changefreq, 'monthly'); + assert.equal(items[2].lastmod, now.toISOString()); + assert.equal(items[2].priority, 0.5); + }); + }); + + describe('i18n', () => { + it('works', () => { + const items = generateSitemap( + [ + // All pages + `${site}/a`, + `${site}/b`, + `${site}/c`, + `${site}/es/a`, + `${site}/es/b`, + `${site}/es/c`, + `${site}/fr/a`, + `${site}/fr/b`, + // `${site}/fr-CA/c`, (intentionally missing for testing) + ], + site, + { + i18n: { + defaultLocale: 'en', + locales: { + en: 'en-US', + es: 'es-ES', + fr: 'fr-CA', + }, + }, + }, + ); + + assert.equal(items.length, 8); + + const aLinks = [ + { url: `${site}/a`, lang: 'en-US' }, + { url: `${site}/es/a`, lang: 'es-ES' }, + { url: `${site}/fr/a`, lang: 'fr-CA' }, + ]; + const bLinks = [ + { url: `${site}/b`, lang: 'en-US' }, + { url: `${site}/es/b`, lang: 'es-ES' }, + { url: `${site}/fr/b`, lang: 'fr-CA' }, + ]; + const cLinks = [ + { url: `${site}/c`, lang: 'en-US' }, + { url: `${site}/es/c`, lang: 'es-ES' }, + ]; + + assert.equal(items[0].url, `${site}/a`); + assert.deepEqual(items[0].links, aLinks); + + assert.equal(items[1].url, `${site}/b`); + assert.deepEqual(items[1].links, bLinks); + + assert.equal(items[2].url, `${site}/c`); + assert.deepEqual(items[2].links, cLinks); + + assert.equal(items[3].url, `${site}/es/a`); + assert.deepEqual(items[3].links, aLinks); + + assert.equal(items[4].url, `${site}/es/b`); + assert.deepEqual(items[4].links, bLinks); + + assert.equal(items[5].url, `${site}/es/c`); + assert.deepEqual(items[5].links, cLinks); + + assert.equal(items[6].url, `${site}/fr/a`); + assert.deepEqual(items[6].links, aLinks); + + assert.equal(items[7].url, `${site}/fr/b`); + assert.deepEqual(items[7].links, bLinks); + }); + }); +}); |