mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
Falha pré-existente reproduzida em origin/main: a página de demanda monta o form de responsáveis duas vezes no DOM (visível + cópia oculta) e campaignDemandVisibility batia nos dois com locator estrito — classe "locator não-escopado" do plano OPS83/#824. O CI curado do PR roda a spec (diff high-risk) e ficaria vermelho; os locators agora miram o elemento visível. Registro no impl plan do C231 e no changelog.
132 lines
5.6 KiB
TypeScript
132 lines
5.6 KiB
TypeScript
import {
|
|
campaignPageChrome,
|
|
expect,
|
|
expectPostResponse,
|
|
test,
|
|
type CampaignE2EFixture,
|
|
} from './fixtures/campaignE2EFixtures.js'
|
|
|
|
test.describe('C143 — demand visibility (explicit responsibles)', () => {
|
|
const setupDemand = async (
|
|
campaign: CampaignE2EFixture,
|
|
fixtures: CampaignE2EFixture['fixtures'],
|
|
) => {
|
|
const municipality = await fixtures.claimMunicipality()
|
|
const coordinator = await fixtures.createCampaignUser('coordinator', {
|
|
name: fixtures.value('Coordenadora C143'),
|
|
})
|
|
const responsible = await fixtures.createCampaignUser('advisor', {
|
|
name: fixtures.value('Assessora Responsável'),
|
|
})
|
|
const peer = await fixtures.createCampaignUser('advisor', {
|
|
name: fixtures.value('Assessor Colega'),
|
|
})
|
|
await campaign.payload.update({
|
|
collection: 'municipality',
|
|
id: municipality.id,
|
|
data: { advisors: [responsible.id, peer.id] },
|
|
depth: 0,
|
|
})
|
|
|
|
const demand = await fixtures.createCampaignDemand({
|
|
municipality: municipality.id,
|
|
createdBy: coordinator.id,
|
|
responsibles: [responsible.id],
|
|
title: fixtures.value('Demanda de acesso restrito'),
|
|
})
|
|
|
|
return { municipality, coordinator, responsible, peer, demand }
|
|
}
|
|
|
|
test('hides the demand from a same-municipality advisor who is not responsible', async ({
|
|
campaign,
|
|
context,
|
|
page,
|
|
}) => {
|
|
const { fixtures } = campaign
|
|
const { peer, demand } = await setupDemand(campaign, fixtures)
|
|
|
|
await campaign.sessionFor(context, peer)
|
|
await page.goto(`${campaign.baseURL}/campanha/demandas`)
|
|
// The list rendered for him: the empty state proves the page settled
|
|
// (and that the demand is absent — the link assertion below is the
|
|
// fail-closed complement).
|
|
// The list mounts the desktop table and the mobile cards together (one
|
|
// hidden) — assert the rendered empty state, not every DOM copy
|
|
// (OPS83/#824, same class).
|
|
await expect(page.getByText('Nenhuma demanda por aqui').filter({ visible: true })).toBeVisible()
|
|
await expect(page.getByRole('link', { name: demand.title })).toHaveCount(0)
|
|
|
|
// The URL does not open either — the demand simply does not exist for him
|
|
// (the default 404 boundary is the root one, no campaign-specific page).
|
|
await page.goto(`${campaign.baseURL}/campanha/demandas/${demand.slug}`)
|
|
await expect(page.getByText('This page could not be found.')).toBeVisible()
|
|
})
|
|
|
|
test('lets a responsible hand access to a peer and revoke it again', async ({
|
|
campaign,
|
|
context,
|
|
page,
|
|
}) => {
|
|
const { fixtures } = campaign
|
|
const { peer, responsible, demand } = await setupDemand(campaign, fixtures)
|
|
const demandURL = `${campaign.baseURL}/campanha/demandas/${demand.slug}`
|
|
|
|
// Pre-existing duplication (OPS83/#824 — the "locator não-escopado" class):
|
|
// the detail page mounts the responsibles form twice in the DOM — the
|
|
// visible one plus a hidden copy with the same markup. Scope every card
|
|
// interaction to the visible form; the search dialog stays page-level (it
|
|
// portals outside).
|
|
const responsiblesCard = page
|
|
.locator('form')
|
|
.filter({ hasText: 'Responsáveis pela demanda' })
|
|
.filter({ visible: true })
|
|
|
|
// The responsible manages the list: add the peer through the search dialog.
|
|
await campaign.sessionFor(context, responsible)
|
|
await page.goto(demandURL)
|
|
await expect(responsiblesCard.getByText('Só quem é responsável vê esta demanda.')).toBeVisible()
|
|
|
|
// The trigger announces the current selection (e.g. "…: 1 responsável").
|
|
await responsiblesCard.getByRole('button', { name: /Responsáveis pela demanda/ }).click()
|
|
await page.getByPlaceholder('Buscar assessor…').fill(peer.name)
|
|
await page.getByRole('option', { name: peer.name }).click()
|
|
// The multi-add dialog stays open (modal) — close it before saving.
|
|
await page.keyboard.press('Escape')
|
|
await responsiblesCard.getByRole('button', { name: 'Salvar responsáveis' }).click()
|
|
await expect(responsiblesCard.getByText('Responsáveis atualizados.')).toBeVisible()
|
|
await expect(
|
|
responsiblesCard.getByRole('button', { name: `Remover ${peer.name}` }),
|
|
).toBeVisible()
|
|
|
|
// The peer now opens the demand.
|
|
await campaign.sessionFor(context, peer)
|
|
await page.goto(demandURL)
|
|
await expect(campaignPageChrome(page, demand.title)).toBeVisible()
|
|
|
|
// Back as the responsible, remove the peer and revoke the access again.
|
|
await campaign.sessionFor(context, responsible)
|
|
await page.goto(demandURL)
|
|
await responsiblesCard.getByRole('button', { name: `Remover ${peer.name}` }).click()
|
|
// The responsibles save is an optimistic server-action write — wait for the
|
|
// POST to land BEFORE swapping to the peer, or the peer's navigation can
|
|
// race the revoke (OPS83 run #16: the accessible demand still served).
|
|
await Promise.all([
|
|
expectPostResponse(page, demandURL),
|
|
responsiblesCard.getByRole('button', { name: 'Salvar responsáveis' }).click(),
|
|
])
|
|
await expect(
|
|
responsiblesCard.getByRole('button', { name: `Remover ${peer.name}` }),
|
|
).toHaveCount(0)
|
|
|
|
// The peer already rendered THIS URL (granted, line 88), so the Next RSC
|
|
// cache can serve the previous payload on a plain goto even after the
|
|
// cookie swap (OPS83 run #15/#16). Break the router context through a
|
|
// blank page so the 404 boundary is fetched fresh from the server.
|
|
await campaign.sessionFor(context, peer)
|
|
await page.goto('about:blank')
|
|
await expect(page).toHaveURL(/about:blank/)
|
|
await page.goto(demandURL)
|
|
await expect(page.getByText('This page could not be found.')).toBeVisible()
|
|
})
|
|
})
|