import { describe, it } from 'node:test'; import { strict as assert } from 'node:assert'; import { readFileSync, existsSync } from 'node:fs'; import { resolve } from 'node:path'; const configPath = resolve('src/content.config.ts'); const postsDir = resolve('src/content/posts'); function readConfig() { return readFileSync(configPath, 'utf-8'); } describe('Content collection config', () => { it('should exist at src/content.config.ts', () => { const content = readConfig(); assert.ok(content.length > 0, 'Config file should not be empty'); }); it('should import defineCollection from astro:content', () => { const content = readConfig(); assert.match(content, /import\s+.*defineCollection.*from\s+['"]astro:content['"]/, 'should import defineCollection'); }); it('should import glob from astro/loaders', () => { const content = readConfig(); assert.match(content, /import\s+.*glob.*from\s+['"]astro\/loaders['"]/, 'should import glob loader'); }); it('should import z from astro:content', () => { const content = readConfig(); assert.match(content, /import\s+.*z[,\s}].*from\s+['"]astro:content['"]/, 'should import z from astro:content'); }); it('should use glob loader with md/mdx pattern', () => { const content = readConfig(); assert.match(content, /glob\s*\(/, 'should call glob()'); assert.match(content, /\*\*\/\*\.\{md,mdx\}/, 'should use **/*.{md,mdx} pattern'); }); it('should use ./src/content/posts as base', () => { const content = readConfig(); assert.match(content, /\.\/src\/content\/posts/, 'should use ./src/content/posts as base'); }); describe('Schema fields', () => { it('should define title as z.string()', () => { const content = readConfig(); assert.match(content, /title\s*:\s*z\.string\(\)/, 'should have title: z.string()'); }); it('should define date as z.coerce.date()', () => { const content = readConfig(); assert.match(content, /date\s*:\s*z\.coerce\.date\(\)/, 'should have date: z.coerce.date()'); }); it('should define type as z.enum with post, pattern, lesson and default post', () => { const content = readConfig(); assert.match(content, /type\s*:\s*z\.enum\s*\(\s*\[\s*['"]post['"]/, 'should have type: z.enum starting with post'); assert.match(content, /['"]pattern['"]/, 'should include pattern in enum'); assert.match(content, /['"]lesson['"]/, 'should include lesson in enum'); assert.match(content, /\.default\s*\(\s*['"]post['"]\s*\)/, 'should default to post'); }); it('should define tags as z.array(z.string()).default([])', () => { const content = readConfig(); assert.match(content, /tags\s*:\s*z\.array\s*\(\s*z\.string\(\)\s*\)\.default\s*\(\s*\[\s*\]\s*\)/, 'should have tags: z.array(z.string()).default([])'); }); it('should define summary as z.string().optional()', () => { const content = readConfig(); assert.match(content, /summary\s*:\s*z\.string\(\)\.optional\(\)/, 'should have summary: z.string().optional()'); }); }); it('should use z.object for schema', () => { const content = readConfig(); assert.match(content, /z\.object\s*\(/, 'should use z.object()'); }); it('should use defineCollection', () => { const content = readConfig(); assert.match(content, /defineCollection\s*\(/, 'should call defineCollection()'); }); it('should export collections with posts', () => { const content = readConfig(); assert.match(content, /export\s+const\s+collections\s*=\s*\{\s*posts\s*\}/, 'should export collections = { posts }'); }); }); describe('Content posts directory', () => { it('should exist at src/content/posts/', () => { assert.ok(existsSync(postsDir), 'src/content/posts/ directory should exist'); }); });