// usePagination (D-40 to D-42, UI-SPEC L2) with the Nuxt composables it // calls stubbed on globalThis: the page hrefs in the form the resolve // answer, the site answer or the layer option names; the prev and next // head links at the ends; the number of pages handed to the CMS head, // whose %pages% seoFillPages replaces. import assert from 'node:assert/strict' import test from 'node:test' import { computed, ref, toValue, watch } from 'vue' import { seoFillPages } from '../app/utils/seo.ts' interface Stubs { fullPath: string answer: unknown site: unknown option?: unknown } const g = globalThis as Record let heads: Array<() => { link: Array<{ rel: string; href: string }> }> = [] const states = new Map>() function stub(s: Stubs) { heads = [] states.clear() Object.assign(g, { computed, toValue, watch, useRoute: () => ({ fullPath: s.fullPath }), useSeoAnswer: () => ref(s.answer), useRuntimeConfig: () => ({ public: { seo: s.option === undefined ? {} : { pagination: s.option } } }), useNuxtData: () => ({ data: ref(s.site) }), useState: (key: string, init: () => unknown) => { if (!states.has(key)) states.set(key, ref(init())) return states.get(key) }, useHead: (input: { value: { link: Array<{ rel: string; href: string }> } }) => heads.push(() => input.value), }) } const { usePagination, useSeoPages } = await import('../app/composables/usePagination.ts') test('the query form from the resolve answer: page 1 unnumbered, other parameters kept', () => { stub({ fullPath: '/blog?sort=new&page=2', answer: { locale: 'pl', pagination: { form: 'query', param: 'page', segment: '' } }, site: null }) const p = usePagination({ current: 2, last: 4 }) assert.equal(p.href(1), '/blog?sort=new') assert.equal(p.href(3), '/blog?sort=new&page=3') assert.deepEqual(p.form.value, { form: 'query', param: 'page', segment: '' }) }) test('the path form from the site answer with the locale segment', () => { stub({ fullPath: '/en/blog/page/2', answer: { locale: 'en' }, site: { default_locale: 'pl', pagination: { form: 'path', param: 'page', segments: { pl: 'strona', en: 'page' } } }, }) const p = usePagination({ current: 2, last: 3 }) assert.equal(p.href(1), '/en/blog') assert.equal(p.href(3), '/en/blog/page/3') stub({ fullPath: '/blog', answer: null, site: { default_locale: 'pl', pagination: { form: 'path', segments: { pl: 'strona' } } }, }) assert.equal(usePagination({ current: 1, last: 3 }).href(2), '/blog/strona/2') }) test('the layer option without a CMS answer, with the given locale', () => { stub({ fullPath: '/de/blog', answer: null, site: null, option: { form: 'path', segments: { de: 'seite' } } }) const p = usePagination({ current: 1, last: 2, locale: 'de' }) assert.equal(p.href(2), '/de/blog/seite/2') }) test('prev and next head links: none on a single page, only next on the first, only prev on the last', () => { const links = (current: number, last: number) => { stub({ fullPath: '/blog', answer: { pagination: { form: 'query', param: 'page' } }, site: null }) usePagination({ current, last }) return heads[0]!().link.map((l) => `${l.rel} ${l.href}`) } assert.deepEqual(links(1, 1), []) assert.deepEqual(links(1, 3), ['next /blog?page=2']) assert.deepEqual(links(2, 3), ['prev /blog', 'next /blog?page=3']) assert.deepEqual(links(3, 3), ['prev /blog?page=2']) assert.deepEqual(links(5, 3), []) }) test('the number of pages for %pages%: set from last, null without pages', () => { stub({ fullPath: '/blog', answer: null, site: null }) usePagination({ current: 1, last: 7 }) assert.equal(useSeoPages().value, 7) const head = seoFillPages({ title: 'Blog – strona 1 z %pages%', meta: [{ content: 'Wpisy (%pages% stron)' }, { content: 'x' }] }, useSeoPages().value as number) assert.equal(head.title, 'Blog – strona 1 z 7') assert.equal(head.meta[0]!.content, 'Wpisy (7 stron)') stub({ fullPath: '/blog', answer: null, site: null }) usePagination({ current: 1, last: 0 }) assert.equal(useSeoPages().value, null) assert.equal(seoFillPages({ title: '%pages%', meta: [] }, null).title, '%pages%') }) test('current and last are whole numbers: current at least 1, last at least 0', () => { stub({ fullPath: '/blog', answer: null, site: null }) const p = usePagination({ current: 0, last: -2.5 }) assert.equal(p.current.value, 1) assert.equal(p.last.value, 0) assert.equal(usePagination({ current: 2.9, last: '4' as unknown as number }).current.value, 2) })