mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
115 lines
4.8 KiB
TypeScript
115 lines
4.8 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).
|
|
await expect(page.getByText('Nenhuma demanda por aqui')).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}`
|
|
|
|
// The responsible manages the list: add the peer through the search dialog.
|
|
await campaign.sessionFor(context, responsible)
|
|
await page.goto(demandURL)
|
|
await expect(page.getByText('Só quem é responsável vê esta demanda.')).toBeVisible()
|
|
|
|
// The trigger announces the current selection (e.g. "…: 1 responsável").
|
|
await page.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 page.getByRole('button', { name: 'Salvar responsáveis' }).click()
|
|
await expect(page.getByText('Responsáveis atualizados.')).toBeVisible()
|
|
await expect(page.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 page.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),
|
|
page.getByRole('button', { name: 'Salvar responsáveis' }).click(),
|
|
])
|
|
await expect(page.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()
|
|
})
|
|
})
|