Этап 1b: сайт
- Страницы обоих брендов из блоков Payload (D-029): главная, цены, локации, поддержка, 4 юридические, 404 и 500. Коллекции pages (черновики и версии) и faq с местами показа, 12 типов блоков; поля sites — почта и Telegram поддержки, часы работы, SEO по умолчанию. - Карта и глобус рисуются на сервере (d3-geo), контуры во внешнем SVG через <use>; выбор локации синхронизирован между картой и сеткой. - Тексты сайта и юридические черновики на 5 языках: de, fr, es — перевод с глоссарием; seed создаёт страницы и FAQ, только если их нет, SEED_CONTENT=reset пересоздаёт. - SEO: title и описания, canonical, hreflang с x-default, sitemap.xml и robots.txt на каждый домен, картинки для соцсетей. - Статическая сборка и пересборка через revalidatePath из хуков Payload (D-030); /svc/internal/revalidate для проверки. - 404 — статичная страница со статусом 404 через proxy; на сайте только опубликованные страницы. - Производительность: Client Hints темы Payload только в админке, предзагрузка 2 файлов шрифтов вместо 6; Lighthouse mobile 97–99. - Контраст --ink-3 по WCAG AA, радиокнопки вместо div role=button. - Документация: итоги 1b, глоссарий de/fr/es, трактовки юридических черновиков подтверждены, переносимые вопросы — в этапах 3e–3h. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
515acfb69d
commit
20491d1ba4
134 files changed
+11232
-212
No files matched your search
@@ -0,0 +1,44 @@
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import type { PayloadRequest } from 'payload'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { revalidateAfterChange, revalidateAfterDelete, SKIP_REVALIDATE } from './revalidateSite'
|
||||
|
||||
vi.mock('next/cache', () => ({ revalidatePath: vi.fn() }))
|
||||
|
||||
const req = { payload: { logger: { debug: vi.fn() } } } as unknown as PayloadRequest
|
||||
|
||||
// хукам нужны только doc, previousDoc, req и context
|
||||
const change = (doc: object, previousDoc: object = {}, context: object = {}) =>
|
||||
revalidateAfterChange({ doc, previousDoc, req, context } as never)
|
||||
|
||||
describe('пересборка маркетинговых страниц', () => {
|
||||
beforeEach(() => vi.mocked(revalidatePath).mockReset())
|
||||
|
||||
it('правка без черновиков пересобирает layout всех маркетинговых страниц', () => {
|
||||
change({ id: '1' })
|
||||
expect(revalidatePath).toHaveBeenCalledWith('/(front)/m/[host]/[locale]/[currency]', 'layout')
|
||||
})
|
||||
|
||||
it('черновик страницы не пересобирает, публикация и снятие с публикации — да', () => {
|
||||
change({ _status: 'draft' }, { _status: 'draft' })
|
||||
expect(revalidatePath).not.toHaveBeenCalled()
|
||||
change({ _status: 'published' }, { _status: 'draft' })
|
||||
change({ _status: 'draft' }, { _status: 'published' })
|
||||
expect(revalidatePath).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('seed и пакетные правки пропускают пересборку', () => {
|
||||
change({ id: '1' }, {}, { [SKIP_REVALIDATE]: true })
|
||||
revalidateAfterDelete({ doc: { id: '1' }, req, context: { [SKIP_REVALIDATE]: true } } as never)
|
||||
expect(revalidatePath).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('вне запроса Next ошибка пересборки не мешает сохранению', () => {
|
||||
vi.mocked(revalidatePath).mockImplementationOnce(() => {
|
||||
throw new Error('static generation store missing')
|
||||
})
|
||||
expect(() => change({ id: '1' })).not.toThrow()
|
||||
expect(req.payload.logger.debug).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user