aboutsummaryrefslogtreecommitdiff
path: root/packages/astro/test/legacy-content-collections.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/astro/test/legacy-content-collections.test.js')
-rw-r--r--packages/astro/test/legacy-content-collections.test.js450
1 files changed, 450 insertions, 0 deletions
diff --git a/packages/astro/test/legacy-content-collections.test.js b/packages/astro/test/legacy-content-collections.test.js
new file mode 100644
index 000000000..6c5335dde
--- /dev/null
+++ b/packages/astro/test/legacy-content-collections.test.js
@@ -0,0 +1,450 @@
+import assert from 'node:assert/strict';
+import { before, describe, it } from 'node:test';
+import * as cheerio from 'cheerio';
+import * as devalue from 'devalue';
+import testAdapter from './test-adapter.js';
+import { preventNodeBuiltinDependencyPlugin } from './test-plugins.js';
+import { loadFixture } from './test-utils.js';
+
+describe('Legacy Content Collections', () => {
+ describe('Query', () => {
+ let fixture;
+ before(async () => {
+ fixture = await loadFixture({ root: './fixtures/legacy-content-collections/' });
+ await fixture.build();
+ });
+
+ describe('Collection', () => {
+ let json;
+ before(async () => {
+ const rawJson = await fixture.readFile('/collections.json');
+ json = devalue.parse(rawJson);
+ });
+
+ it('Returns `without config` collection', async () => {
+ assert.ok(json.hasOwnProperty('withoutConfig'));
+ assert.equal(Array.isArray(json.withoutConfig), true);
+
+ const ids = json.withoutConfig.map((item) => item.id);
+ assert.deepEqual(
+ ids.sort(),
+ [
+ 'columbia.md',
+ 'endeavour.md',
+ 'enterprise.md',
+ // Spaces allowed in IDs
+ 'promo/launch week.mdx',
+ ].sort(),
+ );
+ });
+
+ it('Handles spaces in `without config` slugs', async () => {
+ assert.ok(json.hasOwnProperty('withoutConfig'));
+ assert.equal(Array.isArray(json.withoutConfig), true);
+
+ const slugs = json.withoutConfig.map((item) => item.slug);
+ assert.deepEqual(
+ slugs.sort(),
+ [
+ 'columbia',
+ 'endeavour',
+ 'enterprise',
+ // "launch week.mdx" is converted to "launch-week.mdx"
+ 'promo/launch-week',
+ ].sort(),
+ );
+ });
+
+ it('Returns `with schema` collection', async () => {
+ assert.ok(json.hasOwnProperty('withSchemaConfig'));
+ assert.equal(Array.isArray(json.withSchemaConfig), true);
+
+ const ids = json.withSchemaConfig.map((item) => item.id);
+ const publishedDates = json.withSchemaConfig.map((item) => item.data.publishedAt);
+ assert.deepEqual(ids.sort(), ['four%.md', 'one.md', 'three.md', 'two.md'].sort());
+ assert.equal(
+ publishedDates.every((date) => date instanceof Date),
+ true,
+ 'Not all publishedAt dates are Date objects',
+ );
+ assert.deepEqual(
+ publishedDates.map((date) => date.toISOString()),
+ [
+ '2021-01-01T00:00:00.000Z',
+ '2021-01-01T00:00:00.000Z',
+ '2021-01-03T00:00:00.000Z',
+ '2021-01-02T00:00:00.000Z',
+ ],
+ );
+ });
+
+ it('Returns `with custom slugs` collection', async () => {
+ assert.ok(json.hasOwnProperty('withSlugConfig'));
+ assert.equal(Array.isArray(json.withSlugConfig), true);
+
+ const slugs = json.withSlugConfig.map((item) => item.slug);
+ assert.deepEqual(slugs, ['fancy-one', 'excellent-three', 'interesting-two']);
+ });
+
+ it('Returns `with union schema` collection', async () => {
+ assert.ok(json.hasOwnProperty('withUnionSchema'));
+ assert.equal(Array.isArray(json.withUnionSchema), true);
+
+ const post = json.withUnionSchema.find((item) => item.id === 'post.md');
+ assert.notEqual(post, undefined);
+ assert.deepEqual(post.data, {
+ type: 'post',
+ title: 'My Post',
+ description: 'This is my post',
+ });
+ const newsletter = json.withUnionSchema.find((item) => item.id === 'newsletter.md');
+ assert.notEqual(newsletter, undefined);
+ assert.deepEqual(newsletter.data, {
+ type: 'newsletter',
+ subject: 'My Newsletter',
+ });
+ });
+
+ it('Handles symlinked content', async () => {
+ assert.ok(json.hasOwnProperty('withSymlinkedContent'));
+ assert.equal(Array.isArray(json.withSymlinkedContent), true);
+ const ids = json.withSymlinkedContent.map((item) => item.id);
+ assert.deepEqual(ids.sort(), ['first.md', 'second.md', 'third.md'].sort());
+ assert.equal(
+ json.withSymlinkedContent.find(({ id }) => id === 'first.md').data.title,
+ 'First Blog',
+ );
+ });
+
+ it('Handles symlinked data', async () => {
+ assert.ok(json.hasOwnProperty('withSymlinkedData'));
+ assert.equal(Array.isArray(json.withSymlinkedData), true);
+
+ const ids = json.withSymlinkedData.map((item) => item.id);
+ assert.deepEqual(ids, ['welcome']);
+ assert.equal(
+ json.withSymlinkedData[0].data.alt,
+ 'Futuristic landscape with chrome buildings and blue skies',
+ );
+ assert.notEqual(json.withSymlinkedData[0].data.src.src, undefined);
+ });
+ });
+
+ describe('Propagation', () => {
+ it('Applies styles', async () => {
+ const html = await fixture.readFile('/propagation/index.html');
+ const $ = cheerio.load(html);
+ assert.equal($('style').text().includes('content:"works!"'), true);
+ });
+ });
+
+ describe('Entry', () => {
+ let json;
+ before(async () => {
+ const rawJson = await fixture.readFile('/entries.json');
+ json = devalue.parse(rawJson);
+ });
+
+ it('Returns `without config` collection entry', async () => {
+ assert.ok(json.hasOwnProperty('columbiaWithoutConfig'));
+ assert.equal(json.columbiaWithoutConfig.id, 'columbia.md');
+ });
+
+ it('Returns `with schema` collection entry', async () => {
+ assert.ok(json.hasOwnProperty('oneWithSchemaConfig'));
+ assert.equal(json.oneWithSchemaConfig.id, 'one.md');
+ assert.equal(json.oneWithSchemaConfig.data.publishedAt instanceof Date, true);
+ assert.equal(
+ json.oneWithSchemaConfig.data.publishedAt.toISOString(),
+ '2021-01-01T00:00:00.000Z',
+ );
+ });
+
+ it('Returns `with custom slugs` collection entry', async () => {
+ assert.ok(json.hasOwnProperty('twoWithSlugConfig'));
+ assert.equal(json.twoWithSlugConfig.slug, 'interesting-two');
+ });
+
+ it('Returns `with union schema` collection entry', async () => {
+ assert.ok(json.hasOwnProperty('postWithUnionSchema'));
+ assert.equal(json.postWithUnionSchema.id, 'post.md');
+ assert.deepEqual(json.postWithUnionSchema.data, {
+ type: 'post',
+ title: 'My Post',
+ description: 'This is my post',
+ });
+ });
+ });
+
+ describe('Scripts', () => {
+ it('Contains all the scripts imported by components', async () => {
+ const html = await fixture.readFile('/with-scripts/one/index.html');
+ const $ = cheerio.load(html);
+ assert.equal($('script').length, 2);
+ // Read the scripts' content
+ const scriptsCode = $('script')
+ .map((_, el) => $(el).text())
+ .toArray()
+ .join('\n');
+ assert.match(scriptsCode, /ScriptCompA/);
+ assert.match(scriptsCode, /ScriptCompB/);
+ });
+ });
+ });
+
+ const blogSlugToContents = {
+ 'first-post': {
+ title: 'First post',
+ element: 'blockquote',
+ content: 'First post loaded: yes!',
+ },
+ 'second-post': {
+ title: 'Second post',
+ element: 'blockquote',
+ content: 'Second post loaded: yes!',
+ },
+ 'third-post': {
+ title: 'Third post',
+ element: 'blockquote',
+ content: 'Third post loaded: yes!',
+ },
+ 'using-mdx': {
+ title: 'Using MDX',
+ element: 'a[href="#"]',
+ content: 'Embedded component in MDX',
+ },
+ };
+
+ describe('Static paths integration', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/content-static-paths-integration/',
+ legacy: {
+ collections: true,
+ },
+ });
+ await fixture.build();
+ });
+
+ it('Generates expected pages', async () => {
+ for (const slug in blogSlugToContents) {
+ assert.equal(fixture.pathExists(`/posts/${slug}`), true);
+ }
+ });
+
+ it('Renders titles', async () => {
+ for (const slug in blogSlugToContents) {
+ const post = await fixture.readFile(`/posts/${slug}/index.html`);
+ const $ = cheerio.load(post);
+ assert.equal($('h1').text(), blogSlugToContents[slug].title);
+ }
+ });
+
+ it('Renders content', async () => {
+ for (const slug in blogSlugToContents) {
+ const post = await fixture.readFile(`/posts/${slug}/index.html`);
+ const $ = cheerio.load(post);
+ assert.equal(
+ $(blogSlugToContents[slug].element).text().trim(),
+ blogSlugToContents[slug].content,
+ );
+ }
+ });
+ });
+
+ describe('With spaces in path', () => {
+ it('Does not throw', async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content with spaces in folder name/',
+ legacy: {
+ collections: true,
+ },
+ });
+ let error = null;
+ try {
+ await fixture.build({ force: true });
+ } catch (e) {
+ error = e.message;
+ }
+ assert.equal(error, null);
+ });
+ });
+ describe('With config.mjs', () => {
+ it("Errors when frontmatter doesn't match schema", async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content-collections-with-config-mjs/',
+ legacy: {
+ collections: true,
+ },
+ });
+ let error;
+ try {
+ await fixture.build();
+ } catch (e) {
+ error = e.message;
+ }
+ assert.equal(error.includes('**title**: Expected type `"string"`, received "number"'), true);
+ });
+ });
+ describe('With config.mts', () => {
+ it("Errors when frontmatter doesn't match schema", async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content-collections-with-config-mts/',
+ legacy: {
+ collections: true,
+ },
+ });
+ let error;
+ try {
+ await fixture.build();
+ } catch (e) {
+ error = e.message;
+ }
+ assert.equal(error.includes('**title**: Expected type `"string"`, received "number"'), true);
+ });
+ });
+
+ describe('With empty markdown file', () => {
+ it('Throws the right error', async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content-collections-empty-md-file/',
+ legacy: {
+ collections: true,
+ },
+ });
+ let error;
+ try {
+ await fixture.build();
+ } catch (e) {
+ error = e.message;
+ }
+ assert.equal(error.includes('**title**: Required'), true);
+ });
+ });
+
+ describe('With empty collections directory', () => {
+ it('Handles the empty directory correctly', async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content-collections-empty-dir/',
+ legacy: {
+ collections: true,
+ },
+ });
+ let error;
+ try {
+ await fixture.build();
+ } catch (e) {
+ error = e.message;
+ }
+ assert.equal(error, undefined);
+
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
+ const h1 = $('h1');
+ assert.equal(h1.text(), 'Entries length: 0');
+ assert.equal(h1.attr('data-entries'), '[]');
+ });
+ });
+
+ describe('SSR integration', () => {
+ let app;
+
+ before(async () => {
+ const fixture = await loadFixture({
+ root: './fixtures/content-ssr-integration/',
+ output: 'server',
+ adapter: testAdapter(),
+ vite: {
+ plugins: [preventNodeBuiltinDependencyPlugin()],
+ },
+ legacy: {
+ collections: true,
+ },
+ });
+ await fixture.build();
+ app = await fixture.loadTestAdapterApp();
+ });
+
+ it('Responds 200 for expected pages', async () => {
+ for (const slug in blogSlugToContents) {
+ const request = new Request('http://example.com/posts/' + slug);
+ const response = await app.render(request);
+ assert.equal(response.status, 200);
+ }
+ });
+
+ it('Renders titles', async () => {
+ for (const slug in blogSlugToContents) {
+ const request = new Request('http://example.com/posts/' + slug);
+ const response = await app.render(request);
+ const body = await response.text();
+ const $ = cheerio.load(body);
+ assert.equal($('h1').text(), blogSlugToContents[slug].title);
+ }
+ });
+
+ it('Renders content', async () => {
+ for (const slug in blogSlugToContents) {
+ const request = new Request('http://example.com/posts/' + slug);
+ const response = await app.render(request);
+ const body = await response.text();
+ const $ = cheerio.load(body);
+ assert.equal(
+ $(blogSlugToContents[slug].element).text().trim(),
+ blogSlugToContents[slug].content,
+ );
+ }
+ });
+ });
+
+ describe('Base configuration', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/content-collections-base/',
+ legacy: {
+ collections: true,
+ },
+ });
+ await fixture.build();
+ });
+
+ it('Includes base in links', async () => {
+ const html = await fixture.readFile('/docs/index.html');
+ const $ = cheerio.load(html);
+ assert.equal($('link').attr('href').startsWith('/docs'), true);
+ });
+
+ it('Includes base in scripts', async () => {
+ const html = await fixture.readFile('/docs/index.html');
+ const $ = cheerio.load(html);
+ assert.equal($('script').attr('src').startsWith('/docs'), true);
+ });
+ });
+
+ describe('Mutation', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/content-collections-mutation/',
+ legacy: {
+ collections: true,
+ },
+ });
+ await fixture.build();
+ });
+
+ it('Does not mutate cached collection', async () => {
+ const html = await fixture.readFile('/index.html');
+ const index = cheerio.load(html)('h2:first').text();
+ const html2 = await fixture.readFile('/another_page/index.html');
+ const anotherPage = cheerio.load(html2)('h2:first').text();
+
+ assert.equal(index, anotherPage);
+ });
+ });
+});