import { describe, it, expect } from 'vitest';
import { composePageMeta, detectSchemaType } from '../../seo/page-meta.js';
function makeCollection(overrides = {}) {
    return {
        slug: 'pages',
        labels: { singular: 'Page', plural: 'Pages' },
        fields: {},
        ...overrides,
    };
}
function makeConfig(overrides = {}) {
    return {
        seo: {
            siteUrl: 'https://example.com',
            siteName: 'Example',
            ...overrides,
        },
    };
}
describe('detectSchemaType', () => {
    it('maps known collection slugs', () => {
        expect(detectSchemaType('posts')).toBe('BlogPosting');
        expect(detectSchemaType('blog')).toBe('BlogPosting');
        expect(detectSchemaType('articles')).toBe('Article');
        expect(detectSchemaType('news')).toBe('NewsArticle');
        expect(detectSchemaType('case-studies')).toBe('Article');
        expect(detectSchemaType('faq')).toBe('FAQPage');
        expect(detectSchemaType('services')).toBe('Service');
        expect(detectSchemaType('locations')).toBe('LocalBusiness');
        expect(detectSchemaType('jobs')).toBe('JobPosting');
        expect(detectSchemaType('team')).toBe('Person');
        expect(detectSchemaType('portfolios')).toBe('CreativeWork');
    });
    it('soft-matches via includes', () => {
        expect(detectSchemaType('blog-posts')).toBe('BlogPosting');
        expect(detectSchemaType('our-services')).toBe('Service');
    });
    it('falls back to WebPage for unknown slugs', () => {
        expect(detectSchemaType('xyz-unknown')).toBe('WebPage');
    });
});
describe('composePageMeta', () => {
    it('builds canonical URL from site URL + collection prefix + slug', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'posts', slug: 'hello-world', data: { title: 'Hello World' } },
            collection: makeCollection({ slug: 'posts', urlPrefix: 'blog', type: 'post' }),
            config: makeConfig(),
        });
        expect(result.url).toBe('https://example.com/blog/hello-world');
        expect(result.canonical).toBe('https://example.com/blog/hello-world');
    });
    it('treats slug "home" as the site root', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'home', data: { title: 'Home' } },
            collection: makeCollection({ slug: 'pages', urlPrefix: '', type: 'page' }),
            config: makeConfig(),
        });
        expect(result.url).toBe('https://example.com');
    });
    it('prefers explicit pageSettings.metaTitle over data.title', () => {
        const result = composePageMeta({
            doc: {
                id: '1',
                collection: 'pages',
                slug: 'about',
                data: { title: 'Plain Title' },
                pageSettings: { metaTitle: 'SEO Title' },
            },
            collection: makeCollection(),
            config: makeConfig(),
        });
        expect(result.title).toBe('SEO Title');
    });
    it('composes BlogPosting JSON-LD for posts with author + publisher', () => {
        const result = composePageMeta({
            doc: {
                id: '1',
                collection: 'posts',
                slug: 'first-post',
                data: { title: 'First Post', metaDescription: 'Hello', authorName: 'Jane Doe' },
                publishedAt: '2026-01-01T00:00:00.000Z',
            },
            collection: makeCollection({ slug: 'posts', urlPrefix: 'blog', type: 'post' }),
            config: makeConfig({
                organization: { name: 'Example Inc', logo: 'https://example.com/logo.png' },
            }),
        });
        expect(result.jsonLd).toMatchObject({
            '@context': 'https://schema.org',
            '@type': 'BlogPosting',
            name: 'First Post',
            description: 'Hello',
            url: 'https://example.com/blog/first-post',
            datePublished: '2026-01-01T00:00:00.000Z',
            author: { '@type': 'Person', name: 'Jane Doe' },
            publisher: {
                '@type': 'Organization',
                name: 'Example Inc',
                logo: { '@type': 'ImageObject', url: 'https://example.com/logo.png' },
            },
        });
    });
    it('respects per-collection defaultSchemaType', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'locations', slug: 'nyc', data: { title: 'NYC' } },
            collection: makeCollection({
                slug: 'locations',
                seo: { defaultSchemaType: 'LocalBusiness' },
            }),
            config: makeConfig(),
        });
        expect(result.jsonLd?.['@type']).toBe('LocalBusiness');
    });
    it('honors doc-level structuredData verbatim when set', () => {
        const result = composePageMeta({
            doc: {
                id: '1',
                collection: 'pages',
                slug: 'special',
                data: { title: 'Special' },
                structuredData: { '@type': 'FAQPage', mainEntity: [] },
            },
            collection: makeCollection(),
            config: makeConfig(),
        });
        expect(result.jsonLd).toEqual({
            '@context': 'https://schema.org',
            '@type': 'FAQPage',
            mainEntity: [],
        });
    });
    it('inherits robots defaults from CollectionSEOConfig', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'drafts', slug: 'x', data: { title: 'X' } },
            collection: makeCollection({
                slug: 'drafts',
                seo: { defaultRobots: { noIndex: true } },
            }),
            config: makeConfig(),
        });
        expect(result.meta['robots']).toContain('noindex');
    });
    it('honors the robotsPolicy select field (regression: was ignored)', () => {
        const result = composePageMeta({
            doc: {
                id: '1',
                collection: 'pages',
                slug: 'secret',
                data: { title: 'Secret', robotsPolicy: 'noindex-nofollow' },
            },
            collection: makeCollection(),
            config: makeConfig(),
        });
        expect(result.meta['robots']).toContain('noindex');
        expect(result.meta['robots']).toContain('nofollow');
    });
    it('forces noindex outside production when seo.robots.noIndexNonProduction is set', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'home', data: { title: 'Home' } },
            collection: makeCollection(),
            config: makeConfig({ robots: { noIndexNonProduction: true } }),
            environment: 'preview',
        });
        expect(result.meta['robots']).toContain('noindex');
    });
    it('does NOT force noindex in production even with noIndexNonProduction set', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'home', data: { title: 'Home' } },
            collection: makeCollection(),
            config: makeConfig({ robots: { noIndexNonProduction: true } }),
            environment: 'production',
        });
        expect(result.meta['robots'] ?? '').not.toContain('noindex');
    });
    it('emits og:image, og:url, og:title, twitter:card', () => {
        const result = composePageMeta({
            doc: {
                id: '1',
                collection: 'pages',
                slug: 'home',
                data: { title: 'Hi', metaDescription: 'A page', ogImage: 'https://example.com/cover.png' },
            },
            collection: makeCollection(),
            config: makeConfig({ twitterHandle: '@example' }),
        });
        expect(result.meta['og:image']).toBe('https://example.com/cover.png');
        expect(result.meta['og:url']).toBe('https://example.com');
        expect(result.meta['og:title']).toBe('Hi');
        expect(result.meta['twitter:card']).toBe('summary_large_image');
        expect(result.meta['twitter:site']).toBe('@example');
    });
    it('auto-builds og:image URL pointing at the CMS /api/cms/og.png endpoint when none configured', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'about', data: { title: 'About Us' } },
            collection: makeCollection(),
            config: makeConfig(),
        });
        expect(result.meta['og:image']).toBe('https://example.com/api/cms/og.png?title=' + encodeURIComponent('About Us'));
    });
    it('escapes < in JSON-LD HTML so it cannot break out of <script>', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'x', data: { title: '</script><img src=x>' } },
            collection: makeCollection(),
            config: makeConfig(),
        });
        // The wrapping `<script>...</script>` legitimately contains the closing
        // tag, so we strip it off and assert no closing `<` survives in the body.
        const body = result.jsonLdHtml
            .replace(/^<script type="application\/ld\+json">/, '')
            .replace(/<\/script>$/, '');
        expect(body).not.toContain('</script>');
        expect(body).not.toContain('<img');
        expect(body).toContain('\\u003c');
    });
    it('exposes Next.js-compatible metadata object', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'home', data: { title: 'Home' } },
            collection: makeCollection(),
            config: makeConfig(),
        });
        const m = result.metadata;
        expect(m.title).toBe('Home');
        expect(m.openGraph.siteName).toBe('Example');
        expect(m.alternates.canonical).toBe('https://example.com');
    });
    it('overrides siteUrl when input.siteUrl is provided (preview deploys)', () => {
        const result = composePageMeta({
            doc: { id: '1', collection: 'pages', slug: 'about', data: { title: 'About' } },
            collection: makeCollection(),
            config: makeConfig(),
            siteUrl: 'https://preview-abc.vercel.app',
        });
        expect(result.url).toBe('https://preview-abc.vercel.app/about');
    });
});
//# sourceMappingURL=page-meta.test.js.map