From 4b3ea0d04d70b49a8c3d9fcc9d203e3293aaa994 Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Sat, 26 Sep 2026 01:43:03 -0300 Subject: [PATCH] test: declara o 404 esperado de /conteudos/*/frame nas specs da home MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O conjunto curado roda specs concorrentes que publicam peças; a home pede o still e /frame responde 404 até a cura (C226). As specs da home passam a usar a mesma declaração que frontend.e2e.spec.ts, fechando o flake do CI. --- docs/changelog/2026-09-25-c230.md | 2 +- tests/e2e/campaignNewsletter.e2e.spec.ts | 6 ++++++ tests/e2e/frontendJingles.e2e.spec.ts | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/changelog/2026-09-25-c230.md b/docs/changelog/2026-09-25-c230.md index f41c0d5b..04f99f0f 100644 --- a/docs/changelog/2026-09-25-c230.md +++ b/docs/changelog/2026-09-25-c230.md @@ -1 +1 @@ -**Importar publicações do perfil oficial na Central de Conteúdos (C230, Issue #1362):** a lista da Central ganha o gesto "Importar do perfil": ele lê a janela recente (12 mídias) de `@depjorgesolla` pela Graph API oficial — o mesmo cliente do board, sem scraping, terceiro ou stories — e cria **Rascunho** apenas para as novidades, cada uma pelo pipeline C211/C220 (mídia baixada do perfil próprio, transcrita e catalogada) ou como **peça-link com motivo honesto** quando a API não oferece arquivo único (carrossel, áudio protegido). O fluxo é em duas fases com progresso real ("Importando X de N…") e o recibo final separa **novas criadas / já estavam / falharam**, com o detalhe das peça-link e a orientação de retentar sem duplicar. O dedupe é pela **identidade do post** (shortcode, em qualquer grafia `p`/`reel`/`tv`), não pela URL: o predicado é um só e passou a valer também para o "Adicionar por link" (C220), então um post já catalogado não gera gêmea em nenhum caminho — sem migration (o índice unique de `sourceUrl` já existia). Sem credencial a ação fica indisponível com a linguagem do board ("Instagram ainda não configurado") e o servidor recusa a chamada direta (**fail-closed** nas duas pontas); o token nunca cruza para o cliente, log ou wire, nenhuma peça é publicada automaticamente, `curatedFields` nunca é sobrescrito e o board/feed da home permanece intocado. Cobertura: unit das regras puras (variantes de identidade e classificação do metadado) e int do importador com feed injetado (candidatos/dedupe por kind/falha de credencial/feed, shape do rascunho e reimportação sem duplicata). +**Importar publicações do perfil oficial na Central de Conteúdos (C230, Issue #1362):** a lista da Central ganha o gesto "Importar do perfil": ele lê a janela recente (12 mídias) de `@depjorgesolla` pela Graph API oficial — o mesmo cliente do board, sem scraping, terceiro ou stories — e cria **Rascunho** apenas para as novidades, cada uma pelo pipeline C211/C220 (mídia baixada do perfil próprio, transcrita e catalogada) ou como **peça-link com motivo honesto** quando a API não oferece arquivo único (carrossel, áudio protegido). O fluxo é em duas fases com progresso real ("Importando X de N…") e o recibo final separa **novas criadas / já estavam / falharam**, com o detalhe das peça-link e a orientação de retentar sem duplicar. O dedupe é pela **identidade do post** (shortcode, em qualquer grafia `p`/`reel`/`tv`), não pela URL: o predicado é um só e passou a valer também para o "Adicionar por link" (C220), então um post já catalogado não gera gêmea em nenhum caminho — sem migration (o índice unique de `sourceUrl` já existia). Sem credencial a ação fica indisponível com a linguagem do board ("Instagram ainda não configurado") e o servidor recusa a chamada direta (**fail-closed** nas duas pontas); o token nunca cruza para o cliente, log ou wire, nenhuma peça é publicada automaticamente, `curatedFields` nunca é sobrescrito e o board/feed da home permanece intocado. Cobertura: unit das regras puras (variantes de identidade e classificação do metadado) e int do importador com feed injetado (candidatos/dedupe por kind/falha de credencial/feed, shape do rascunho e reimportação sem duplicata). No harness de e2e, as specs que renderizam a home (`campaignNewsletter`, `frontendJingles`) passam a declarar o 404 esperado de `/conteudos/*/frame` (C226) — o mesmo dono que `frontend` já usava —, fechando o flake do conjunto curado quando uma spec concorrente publica uma peça sem still. diff --git a/tests/e2e/campaignNewsletter.e2e.spec.ts b/tests/e2e/campaignNewsletter.e2e.spec.ts index f1232cf9..9add3da3 100644 --- a/tests/e2e/campaignNewsletter.e2e.spec.ts +++ b/tests/e2e/campaignNewsletter.e2e.spec.ts @@ -11,7 +11,13 @@ import { expect, test } from './fixtures/e2eTest' * level, and the page confirms in place. Runs the write through the deployed * server (server action + Local API) so the fail-closed consent path and the * transaction are the production ones. + * + * The home renders published content pieces; a concurrent curated spec can + * publish one whose still is not on disk yet, and `/conteudos//frame` + * answers 404 until the self-heal lands (C226) — the same declaration as + * `frontend.e2e.spec.ts`. */ +test.use({ expectedRequestFailurePaths: [/\/conteudos\/.+\/frame$/] }) test.describe('Campaign home novidades capture', () => { const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000' const runSuffix = Date.now() diff --git a/tests/e2e/frontendJingles.e2e.spec.ts b/tests/e2e/frontendJingles.e2e.spec.ts index a5644e65..af233758 100644 --- a/tests/e2e/frontendJingles.e2e.spec.ts +++ b/tests/e2e/frontendJingles.e2e.spec.ts @@ -21,7 +21,13 @@ import { expect, test } from './fixtures/e2eTest' * * The tests are serial: the empty-state assertions need a global window with * zero published jingles, and only this spec owns jingle rows. + * + * The home renders published content pieces; a concurrent curated spec can + * publish one whose still is not on disk yet, and `/conteudos//frame` + * answers 404 until the self-heal lands (C226) — the same declaration as + * `frontend.e2e.spec.ts`. */ +test.use({ expectedRequestFailurePaths: [/\/conteudos\/.+\/frame$/] }) const BASE_URL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000'