mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
test(e2e): unificar logins do usuário de teste no helper adminHeaders com advisory lock (Closes #767)
This commit is contained in:
parent
a180721e11
commit
d0161f6d69
6 changed files with 150 additions and 43 deletions
1
docs/changelog/2026-08-24-e2e-admin-login-lock.md
Normal file
1
docs/changelog/2026-08-24-e2e-admin-login-lock.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
**E2E-ADMIN-LOGIN-LOCK — unificar logins do usuário de teste no helper com advisory lock (2026-08-24):** fechamento do débito restante do S10 (#767, orig. do simplify do S10 #94). O e2e full mantinha logins do usuário compartilhado `dev@payloadcms.com` fora do ponto único de serialização: o shadow local `adminHeaders` sem lock em `frontend.e2e.spec.ts` (11 call sites, 10 `seedTestUser` por teste) e o `cleanupTestUser` que ainda **deletava** o usuário no `afterAll` do `admin.e2e.spec.ts` no meio da suíte paralela — janela de usuário ausente contra seeds concorrentes e sessão read-modify-write perdida (token perdedor → 403). A entrega removeu o shadow e roteou os 11 logins pelo helper `tests/helpers/adminApi.ts` (`adminHeaders(request, baseURL)`) com `pg_advisory_lock(727001)` — o mesmo lock do `login()` UI — e removeu `cleanupTestUser` (helper morto + afterAll), convergindo o registro do OPS73-FOLLOWUP que já o declarava removido. Verificação local: admin.e2e (5/5) e frontend.e2e (20/20) verdes; corrida exercitada em run com cadeia completa (falhas colaterais da família campaign isoladas como pré-existentes via `git stash` em main limpo — 5 reprodutíveis + 5 irmãos 1×). Dívida capturada: **#882** (`E2E-FLAKE-CAST-ROTATIVA-POS-OPS83`, depends #767) — cast rotativa de flakes da família campaign.
|
||||||
92
docs/plans/e2e-admin-login-lock-impl.md
Normal file
92
docs/plans/e2e-admin-login-lock-impl.md
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Impl: E2E-ADMIN-LOGIN-LOCK — Unificar os logins do usuário de teste no helper `adminHeaders` com advisory lock
|
||||||
|
|
||||||
|
Status: rascunho
|
||||||
|
Atualizado em: 2026-08-24
|
||||||
|
Issue: #767
|
||||||
|
Intenção: body da Issue #767 (dívida restante do S10, fechamento parcial no #805)
|
||||||
|
Appetite restante: herdado (dívida de teste) — ~0,25 dia, mudança mecânica em 2 arquivos
|
||||||
|
|
||||||
|
## Leitura da intenção
|
||||||
|
|
||||||
|
- **Outcome:** todos os logins do usuário de teste (`dev@payloadcms.com`) no e2e — REST e UI — passam pelo mesmo ponto de serialização (`adminHeaders` com `pg_advisory_lock(727001)`), e o usuário compartilhado nunca é apagado no meio da suíte paralela. A corrida read-modify-write de sessão (token perdedor → 403 em toda requisição admin) deixa de existir entre os specs restantes.
|
||||||
|
- **O que NÃO negociar:** nenhum spec deixa de ser autossuficiente; nenhum projeto/worker é serializado (a serialização é por-lock, não por topologia); o login UI do admin (`login.ts`) continua testando o formulário genuinamente (não vira API login).
|
||||||
|
- **O que reavaliar:** o changelog `docs/changelog/2026-08-23-ops73-followup.md` registra `cleanupTestUser` como já removido — mas o código o mantém vivo (`seedUser.ts:42-54`, chamado em `admin.e2e.spec.ts:20`). Esta entrega converge código e registro documental.
|
||||||
|
|
||||||
|
## Abordagem recomendada
|
||||||
|
|
||||||
|
**Remover o shadow local de `adminHeaders` em `frontend.e2e.spec.ts` e rotear os 11 call sites pelo helper com lock; remover `cleanupTestUser` (helper + afterAll do admin).**
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph helpers["tests/helpers (owners)"]
|
||||||
|
advisoryLock["advisoryLock.ts<br/>ADMIN_LOGIN_LOCK_KEY = 727_001<br/>withAdvisoryLock()"]
|
||||||
|
adminApi["adminApi.ts<br/>adminHeaders(request, baseURL) + lock"]
|
||||||
|
seedUser["seedUser.ts<br/>seedTestUser() create-if-missing<br/>cleanupTestUser() → REMOVIDO"]
|
||||||
|
end
|
||||||
|
subgraph specs
|
||||||
|
frontend["frontend.e2e.spec.ts<br/>shadow adminHeaders (613-620) → REMOVIDO<br/>11 call sites → adminHeaders(request, baseURL)"]
|
||||||
|
admin["admin.e2e.spec.ts<br/>login() UI + lock (mantém)<br/>afterAll cleanupTestUser → REMOVIDO"]
|
||||||
|
locked["campaignNewsletter / campaignHomePixel<br/>já via adminHeaders + lock (intocados)"]
|
||||||
|
end
|
||||||
|
advisoryLock --> adminApi
|
||||||
|
adminApi --> frontend
|
||||||
|
adminApi --> locked
|
||||||
|
seedUser --> frontend
|
||||||
|
seedUser --> admin
|
||||||
|
```
|
||||||
|
|
||||||
|
**Opções consideradas:** A (remover o shadow e importar o helper com lock + remover cleanup) | B (envolver o shadow existente com `withAdvisoryLock`, mantendo o bloco de login no spec) | C (lock inline em cada call site do frontend) | D (remover só o cleanup, deixar o shadow) | E (manter cleanup, mas envolver o delete em lock + re-seed)
|
||||||
|
|
||||||
|
**Recomendação:** A — porque o helper `adminHeaders` já é o owner do concern (mesma chave do `login()` UI, throw em login não-ok, unlock no `finally`); o shadow de `frontend.e2e.spec.ts:613-620` é o mesmo bloco pré-lock que `adminApi.ts` refatorou no #805 — mantê-lo seria twin com conhecimento vazando em 2 módulos. E remover `cleanupTestUser`: com credenciais constantes + `seedTestUser` create-if-missing, o delete não cumpre nenhum propósito (o usuário é idêntico a cada run, sem estado por-teste) e só cria a janela de ausência que a intenção quer fechar — além de convergir o registro do OPS73-FOLLOWUP.
|
||||||
|
|
||||||
|
**Rejeitadas:** B (mantém o bloco de login duplicado e o conhecimento espalhado — depth check: o módulo profundo já existe e é `adminApi.ts`; DRY); C (espalha `withAdvisoryLock` em 11 pontos — pass-through raso que o helper já encapsula); D (deixa a corrida que a intenção pede para fechar); E (o lock não fecha a janela: o `seedTestUser` concorrente roda fora do lock, e o delete invalida tokens vivos de workers em voo; adicionar lock a um delete que não precisa existir é custo puro).
|
||||||
|
|
||||||
|
### Componentes / mudanças
|
||||||
|
|
||||||
|
- **`tests/e2e/frontend.e2e.spec.ts`**: importar `adminHeaders` de `../helpers/adminApi`; remover o shadow local (linhas 613-620); trocar os 11 call sites `adminHeaders(request)` → `adminHeaders(request, baseURL)` (linhas 608, 827, 985, 1018, 1099, 1152, 1216, 1306, 1366, 1437, 1505 — `baseURL` já está no escopo do describe, linha 593); remover `testUser` do import da linha 3 (fica órfão — só o shadow o usava). `APIRequestContext` permanece (outros helpers locais: `createTag`, `resetSocialFeedSettings`, `bustSocialFeed`, `cleanupS2Fixtures`, …).
|
||||||
|
- **`tests/e2e/admin.e2e.spec.ts`**: remover `cleanupTestUser` do import (linha 3) e o `test.afterAll` (linhas 19-21). Resto intocado — REST já via `adminHeaders` (51, 148) e UI via `login()` com lock (16).
|
||||||
|
- **`tests/helpers/seedUser.ts`**: remover `cleanupTestUser` (linhas 39-54). `seedTestUser` fica como está.
|
||||||
|
- **Migration:** sem migration (mudança de helpers de teste).
|
||||||
|
- **Access / Consent:** n/a (teste).
|
||||||
|
- **UI:** n/a (teste).
|
||||||
|
|
||||||
|
## Fases verificáveis
|
||||||
|
|
||||||
|
1. **Fase 1 — Unificar os logins do frontend** (`tests/e2e/frontend.e2e.spec.ts`): novo import `adminHeaders`; remover shadow; atualizar os 11 call sites; limpar import `testUser`. → `pnpm lint`, `pnpm typecheck` (e `pnpm knip` — pega o export morto se algo escapar).
|
||||||
|
2. **Fase 2 — Remover `cleanupTestUser`** (`admin.e2e.spec.ts` + `seedUser.ts`): remover afterAll/import e a função. → `pnpm lint`, `pnpm knip`.
|
||||||
|
3. **Fase 3 — Gates e verificação da serialização:** `pnpm gate:fast`; e2e alvo `pnpm test:e2e --no-deps --project=frontend` e `pnpm test:e2e --no-deps --project=admin` (ou por arquivo); rodada full local com `PLAYWRIGHT_WORKERS=4` (a corrida só se demonstra com projetos em paralelo — mesma topologia do deploy `verify`); registrar entrada em `docs/changelog/<data>-e2e-admin-login-lock.md` (converge a discrepância do OPS73-FOLLOWUP); push via `pnpm push`.
|
||||||
|
|
||||||
|
## Rabbit holes / Não escopo (engenharia)
|
||||||
|
|
||||||
|
- Auth `campaignUser` (`campaignE2EFixtures`, `campaignHttpTest.ts:56`) — coleção de auth separada, sem sessão read-modify-write compartilhada; fora do escopo.
|
||||||
|
- `playwright.config.ts` (fullyParallel, workers, cadeia de projetos) — é a topologia que expõe a corrida; NÃO serializar projetos nem subir workers.
|
||||||
|
- `seedTestUser()` espalhado (10 no frontend + admin/newsletter/pixel): manter — create-if-missing é idempotente com credenciais constantes (o perdedor do unique-conflict procede); NÃO envolver em lock (não é write read-modify-write). Gatilho de revisitação: se o usuário de teste ganhar credenciais não-constantes, virar fixture de projeto em vez de seed por teste.
|
||||||
|
- NÃO trocar o login UI do admin por API login (o spec testa o formulário).
|
||||||
|
- NÃO promover o advisory lock a mecanismo de produção (comentário do próprio `advisoryLock.ts`).
|
||||||
|
|
||||||
|
## Riscos e mitigação
|
||||||
|
|
||||||
|
- **Corrida do afterAll cleanup vs seeds concorrentes:** eliminada pela remoção do delete. Gate de review: nunca reintroduzir delete do usuário compartilhado (o changelog já documenta a remoção como intenção).
|
||||||
|
- **Janela de usuário ausente:** some junto (sem delete, sem janela; create-if-missing é idempotente).
|
||||||
|
- **Custo de serialização:** 11 logins do frontend agora passam pelo lock; cada lock é ~ms e o describe já é `serial` — impacto negligenciável contra o custo de 403 retries.
|
||||||
|
- **Mudança de semântica de falha:** o shadow usava `expect(login.ok()).toBeTruthy()` (asserção Playwright); o helper lança `Error` — ambos rejeitam a promise, então `.catch(() => undefined)` (linha 985) e os `try/finally` dos specs seguem válidos.
|
||||||
|
- **Import órfão `testUser`:** removido na Fase 1; knip/lint pegam se escapar.
|
||||||
|
- **Flake pré-existente não relacionado no verify full:** classe conhecida (timeouts de `locator.check`, C142) — não bloqueia esta entrega; o PR roda o conjunto curado.
|
||||||
|
|
||||||
|
## Aceite de engenharia
|
||||||
|
|
||||||
|
- [ ] Aceite de produto da intenção ainda coberto (todos os logins do usuário de teste serializam no mesmo lock; cleanup não apaga o usuário compartilhado)
|
||||||
|
- [ ] Invariantes AGENTS/engineering-standards (reusa o owner existente `adminApi.ts` — sem twin; zero schema/access/UI tocados)
|
||||||
|
- [ ] Testes de domínio previstos: e2e alvo (frontend + admin) e full-4-workers local / verify CI (sem unit/int — mudança confinada a helpers de teste)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-score decision-quality (gate ≥4)
|
||||||
|
|
||||||
|
1. **Decisões caras têm rejeitadas?** Sim — D1 (remover shadow vs envolver vs lock nos call sites) e D2 (remover cleanup vs lock+re-seed vs manter) com opções e motivos registrados. 1/1
|
||||||
|
2. **Abordagem cabe no appetite?** Sim — ~0,25 dia, mecânico, 2 arquivos, reusa 100% da infra do #805. 1/1
|
||||||
|
3. **Rabbit holes nomeados?** Sim — auth campaignUser, topologia do config, seedTestUser sem lock (com gatilho de revisitação), login UI genuíno. 1/1
|
||||||
|
4. **Depth check: reusa shells/helpers existentes?** Sim — zero helper novo; `adminHeaders`/`advisoryLock` já são o módulo profundo; removemos o twin (shadow) em vez de criar mais um. 1/1
|
||||||
|
5. **Intenção permanece satisfeita?** Sim — a engenharia (lock no helper + sem delete) é exatamente a ação pedida no body da Issue, sem reescrever o outcome. 1/1
|
||||||
|
|
||||||
|
**Score: 5/5.** Ponto único de fragilidade: D2 depende de "nenhum outro consumidor de `cleanupTestUser`" — verificado por grep (único call site: `admin.e2e.spec.ts:20`) e coberto pelo `pnpm knip` da Fase 2.
|
||||||
43
docs/plans/e2e-flake-cast-rotativa-pos-ops83-impl.md
Normal file
43
docs/plans/e2e-flake-cast-rotativa-pos-ops83-impl.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Plano curto: E2E-FLAKE-CAST-ROTATIVA — flakes reprodutíveis da família campaign pós-OPS83
|
||||||
|
|
||||||
|
Status: rascunho · Issue: (registrada via agent:register) · Débito capturado na entrega #767 (2026-08-24)
|
||||||
|
|
||||||
|
## Problema
|
||||||
|
|
||||||
|
O e2e full (deploy `verify`) e runs locais encontram uma cast rotativa de flakes na família `campaign`: no rerun do #767, 5 testes falharam consistentemente em **main limpo** (não relacionados àquela entrega) e 5 irmãos flakearam 1×:
|
||||||
|
|
||||||
|
**Reprodutíveis em main limpo:**
|
||||||
|
- `campaignPeople.e2e.spec.ts:180` (C131) — `campaignPeople.e2e.spec.ts:212`: opção `Todas as zonas` do aggregate Salvador não aparece (stream/aggregate).
|
||||||
|
- `campaignMunicipalities.e2e.spec.ts:387` (B176) — filtro por Dobradinha/Liderança/Partido no omnibox; tocado 2× pelo OPS83 (#824) e ainda vermelho.
|
||||||
|
- `campaignColumnPicker.e2e.spec.ts:146` (B197) — assessor ganha o picker com e-mail oculto.
|
||||||
|
- `campaignConcepts.e2e.spec.ts:15` — staff chega na página de conceitos via tooltip/popover.
|
||||||
|
- `campaignActivity.e2e.spec.ts:51` — cria compromisso com demandas vinculadas pelo overlay.
|
||||||
|
|
||||||
|
**Flakes 1× (passaram no rerun):** `campaignHomeActions:435`, `campaignHomePixel:78`, `campaignMunicipalities:650`, `campaignNearestMunicipality:178`, `campaignPeopleHttp:88/115`.
|
||||||
|
|
||||||
|
## Já resolvido — não reabrir
|
||||||
|
|
||||||
|
- C142 / `campaignMunicipalities:115` (`locator.check` timeouts) — curado pelo #808 (`e2e-full-flake-c142mun`, 21/21 no battle-test).
|
||||||
|
- Discrepância do `cleanupTestUser`/shadow `adminHeaders` — curada pela própria #767.
|
||||||
|
|
||||||
|
## Abordagem
|
||||||
|
|
||||||
|
Linha spec-only (padrão provado pela casa de flakes): settle/poll com `waitForStreamSettled`/`expect.poll`/`expectPostResponse`, reuso do owner existente. Sem migration, sem mudança de app.
|
||||||
|
|
||||||
|
Fases por ROI:
|
||||||
|
1. B176 `campaignMunicipalities:387` (pista mais quente — 2× tocado pelo OPS83 e ainda vermelho)
|
||||||
|
2. C131 `campaignPeople:180` (aggregate/stream)
|
||||||
|
3. `campaignConcepts:15`
|
||||||
|
4. `campaignActivity:51`
|
||||||
|
5. B197 `campaignColumnPicker:146`
|
||||||
|
6. Re-rodar família + aceite de 2 runs limpos
|
||||||
|
|
||||||
|
## Explicitamente fora
|
||||||
|
|
||||||
|
- `seedTestUser` fora do lock (create-if-missing idempotente) — gatilho: usuário de teste ganhar credenciais não-constantes → virar fixture de projeto (anotado no `e2e-admin-login-lock-impl.md`).
|
||||||
|
- #763 (C113) e #790 (OPS46-S3) — pais/superfícies distintos.
|
||||||
|
|
||||||
|
## Riscos
|
||||||
|
|
||||||
|
- Cast rotativa pode girar entre o plano e a execução — fase 6 (re-run da família) é o aceite.
|
||||||
|
- Cada fase é independente; a cast não bloqueia entregas individuais (PR roda blast radius, full fica no verify manual).
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { adminHeaders } from '../helpers/adminApi'
|
import { adminHeaders } from '../helpers/adminApi'
|
||||||
import { login } from '../helpers/login'
|
import { login } from '../helpers/login'
|
||||||
import { cleanupTestUser, seedTestUser, testUser } from '../helpers/seedUser'
|
import { seedTestUser, testUser } from '../helpers/seedUser'
|
||||||
import { instagramStubUrlFor } from '../helpers/socialStub'
|
import { instagramStubUrlFor } from '../helpers/socialStub'
|
||||||
import { expect, test } from './fixtures/e2eTest'
|
import { expect, test } from './fixtures/e2eTest'
|
||||||
|
|
||||||
|
|
@ -16,10 +16,6 @@ test.describe('Admin Panel', () => {
|
||||||
await login({ page, serverURL: baseURL, user: testUser })
|
await login({ page, serverURL: baseURL, user: testUser })
|
||||||
})
|
})
|
||||||
|
|
||||||
test.afterAll(async () => {
|
|
||||||
await cleanupTestUser()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('can navigate to dashboard', async ({ page }) => {
|
test('can navigate to dashboard', async ({ page }) => {
|
||||||
await page.goto(`${baseURL}/admin`)
|
await page.goto(`${baseURL}/admin`)
|
||||||
await expect(page).toHaveURL(`${baseURL}/admin`)
|
await expect(page).toHaveURL(`${baseURL}/admin`)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import type { APIRequestContext, Locator, Page } from '@playwright/test'
|
import type { APIRequestContext, Locator, Page } from '@playwright/test'
|
||||||
|
|
||||||
import { seedTestUser, testUser } from '../helpers/seedUser'
|
import { adminHeaders } from '../helpers/adminApi'
|
||||||
|
import { seedTestUser } from '../helpers/seedUser'
|
||||||
import { instagramStubUrlFor, youtubeStubUrlFor } from '../helpers/socialStub'
|
import { instagramStubUrlFor, youtubeStubUrlFor } from '../helpers/socialStub'
|
||||||
import { expect, test } from './fixtures/e2eTest'
|
import { expect, test } from './fixtures/e2eTest'
|
||||||
|
|
||||||
|
|
@ -605,20 +606,11 @@ test.describe('Campaign home content section', () => {
|
||||||
// Start every run with the social feed unconfigured so the empty-state
|
// Start every run with the social feed unconfigured so the empty-state
|
||||||
// test stays deterministic even when a previous S2 run left settings or a
|
// test stays deterministic even when a previous S2 run left settings or a
|
||||||
// persisted snapshot behind (same reasoning as the `posts` bust below).
|
// persisted snapshot behind (same reasoning as the `posts` bust below).
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await resetSocialFeedSettings(request, headers)
|
await resetSocialFeedSettings(request, headers)
|
||||||
await bustSocialFeed(request)
|
await bustSocialFeed(request)
|
||||||
})
|
})
|
||||||
|
|
||||||
const adminHeaders = async (request: APIRequestContext): Promise<Record<string, string>> => {
|
|
||||||
const login = await request.post(`${baseURL}/api/users/login`, {
|
|
||||||
data: { email: testUser.email, password: testUser.password },
|
|
||||||
})
|
|
||||||
expect(login.ok()).toBeTruthy()
|
|
||||||
const { token } = await login.json()
|
|
||||||
return { cookie: `payload-token=${token}` }
|
|
||||||
}
|
|
||||||
|
|
||||||
const createTag = async (
|
const createTag = async (
|
||||||
request: APIRequestContext,
|
request: APIRequestContext,
|
||||||
headers: Record<string, string>,
|
headers: Record<string, string>,
|
||||||
|
|
@ -824,7 +816,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
|
|
||||||
const visibleTag = await createTag(request, headers, categoryName, categorySlug)
|
const visibleTag = await createTag(request, headers, categoryName, categorySlug)
|
||||||
const hiddenTag = await createTag(request, headers, hiddenTagName, hiddenTagSlug, true)
|
const hiddenTag = await createTag(request, headers, hiddenTagName, hiddenTagSlug, true)
|
||||||
|
|
@ -982,7 +974,7 @@ test.describe('Campaign home content section', () => {
|
||||||
await page.goto('about:blank')
|
await page.goto('about:blank')
|
||||||
await expect(page).toHaveURL(/about:blank/)
|
await expect(page).toHaveURL(/about:blank/)
|
||||||
} finally {
|
} finally {
|
||||||
const headers2 = await adminHeaders(request).catch(() => undefined)
|
const headers2 = await adminHeaders(request, baseURL).catch(() => undefined)
|
||||||
if (headers2) {
|
if (headers2) {
|
||||||
for (const id of createdPosts) {
|
for (const id of createdPosts) {
|
||||||
await request
|
await request
|
||||||
|
|
@ -1015,7 +1007,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'ok')
|
await setYouTubeStubState(request, 'ok')
|
||||||
|
|
||||||
const mixTag = await createTag(request, headers, `E2e Mix ${runSuffix}`, `e2e-mix-${runSuffix}`)
|
const mixTag = await createTag(request, headers, `E2e Mix ${runSuffix}`, `e2e-mix-${runSuffix}`)
|
||||||
|
|
@ -1096,7 +1088,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'fail')
|
await setYouTubeStubState(request, 'fail')
|
||||||
|
|
||||||
const fallbackTag = await createTag(
|
const fallbackTag = await createTag(
|
||||||
|
|
@ -1149,7 +1141,7 @@ test.describe('Campaign home content section', () => {
|
||||||
|
|
||||||
test('keeps the last snapshot while the API is down', async ({ page, request }) => {
|
test('keeps the last snapshot while the API is down', async ({ page, request }) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'ok')
|
await setYouTubeStubState(request, 'ok')
|
||||||
const baseSettings = {
|
const baseSettings = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -1213,7 +1205,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'ok')
|
await setYouTubeStubState(request, 'ok')
|
||||||
await setInstagramStubState(request, 'ok')
|
await setInstagramStubState(request, 'ok')
|
||||||
|
|
||||||
|
|
@ -1303,7 +1295,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setInstagramStubState(request, 'fail')
|
await setInstagramStubState(request, 'fail')
|
||||||
|
|
||||||
const fallbackTag = await createTag(
|
const fallbackTag = await createTag(
|
||||||
|
|
@ -1363,7 +1355,7 @@ test.describe('Campaign home content section', () => {
|
||||||
|
|
||||||
test('keeps the last Instagram snapshot while the API is down', async ({ page, request }) => {
|
test('keeps the last Instagram snapshot while the API is down', async ({ page, request }) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setInstagramStubState(request, 'ok')
|
await setInstagramStubState(request, 'ok')
|
||||||
const baseSettings = {
|
const baseSettings = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -1434,7 +1426,7 @@ test.describe('Campaign home content section', () => {
|
||||||
request,
|
request,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'ok')
|
await setYouTubeStubState(request, 'ok')
|
||||||
await setInstagramStubState(request, 'ok')
|
await setInstagramStubState(request, 'ok')
|
||||||
|
|
||||||
|
|
@ -1502,7 +1494,7 @@ test.describe('Campaign home content section', () => {
|
||||||
context,
|
context,
|
||||||
}) => {
|
}) => {
|
||||||
await seedTestUser()
|
await seedTestUser()
|
||||||
const headers = await adminHeaders(request)
|
const headers = await adminHeaders(request, baseURL)
|
||||||
await setYouTubeStubState(request, 'ok')
|
await setYouTubeStubState(request, 'ok')
|
||||||
await setInstagramStubState(request, 'ok')
|
await setInstagramStubState(request, 'ok')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,20 +35,3 @@ export async function seedTestUser(): Promise<void> {
|
||||||
// A parallel worker already seeded the shared user; nothing to reset.
|
// A parallel worker already seeded the shared user; nothing to reset.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up test user after tests
|
|
||||||
*/
|
|
||||||
export async function cleanupTestUser(): Promise<void> {
|
|
||||||
assertTestDatabase(process.env.DATABASE_URL)
|
|
||||||
const payload = await getPayload({ config })
|
|
||||||
|
|
||||||
await payload.delete({
|
|
||||||
collection: 'users',
|
|
||||||
where: {
|
|
||||||
email: {
|
|
||||||
equals: testUser.email,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue