mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:53:05 +00:00
B62+: flatten adversary signal to boolean and harden leader redirect e2e.
The simplify pass dropped the vestigial object wrapper on E11 input and aligned the leader home test with the retrying toHaveURL idiom used elsewhere.
This commit is contained in:
parent
120ed8d9b5
commit
a8cb771303
4 changed files with 13 additions and 15 deletions
|
|
@ -95,8 +95,8 @@ export type MunicipalityTriggerInput = {
|
|||
coverageRatio: number | null
|
||||
coverageDeficit: number
|
||||
|
||||
/** Adversary signal within the window, if any (P1 variant) — presence reads as confirmed. */
|
||||
adversarySignal: { present: true } | null
|
||||
/** Adversary signal within the window (P1 variant) — presence reads as confirmed. */
|
||||
hasAdversarySignal: boolean
|
||||
/** Any non-draft activity recently held or upcoming (the "agenda" leg of P1). */
|
||||
hasRecentOrUpcomingActivity: boolean
|
||||
/** Activities `realizado` within the effort window (K-A's "esforço no ciclo"). */
|
||||
|
|
@ -314,7 +314,7 @@ const patternP1: SuggestionPattern = {
|
|||
evaluate: (input) => {
|
||||
if (input.territorialClass !== 'reduto' || !input.inCoreBlock) return null
|
||||
|
||||
const threatened = input.adversarySignal !== null
|
||||
const threatened = input.hasAdversarySignal
|
||||
const own2018 = input.ownVotesByYear[YEAR_2018] ?? 0
|
||||
const own2022 = input.ownVotesByYear[YEAR_2022] ?? 0
|
||||
const dropped = own2018 > 0 && own2022 <= own2018 * SUGGESTION_ANCHORS.voteDropRatio
|
||||
|
|
@ -339,7 +339,7 @@ const patternP1: SuggestionPattern = {
|
|||
}
|
||||
if (dormant) factors.push(`${signalAgeFactor(input.lastSignalAgeDays)}, sem agenda no período`)
|
||||
|
||||
const triageLevel: SuggestionTriageLevel = input.adversarySignal ? 1 : 3
|
||||
const triageLevel: SuggestionTriageLevel = input.hasAdversarySignal ? 1 : 3
|
||||
return { patternId: 'P1', triageLevel, factors }
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,11 +284,11 @@ export const loadMunicipalitySuggestions = async (
|
|||
])
|
||||
|
||||
// Any adversary signal in the window reads as confirmed (B62: sinal = tipo + texto).
|
||||
const adversarySignalByMunicipality = new Map<number, { present: true }>()
|
||||
const adversarySignalMunicipalityIDs = new Set<number>()
|
||||
for (const signal of signals.docs) {
|
||||
const id = relationshipId(signal.municipality)
|
||||
if (id === null) continue
|
||||
adversarySignalByMunicipality.set(id, { present: true })
|
||||
adversarySignalMunicipalityIDs.add(id)
|
||||
}
|
||||
|
||||
const agendaByMunicipality = new Map<number, { hasAgenda: boolean; completedCount: number }>()
|
||||
|
|
@ -369,7 +369,7 @@ export const loadMunicipalitySuggestions = async (
|
|||
lastPledgeAgeDays: municipalitySignalAgeInDays(pledgeAggregate.lastPledgeAt, now),
|
||||
coverageRatio: coverage.coverageRatio,
|
||||
coverageDeficit: coverage.deficit,
|
||||
adversarySignal: adversarySignalByMunicipality.get(municipality.id) ?? null,
|
||||
hasAdversarySignal: adversarySignalMunicipalityIDs.has(municipality.id),
|
||||
hasRecentOrUpcomingActivity: agenda?.hasAgenda ?? false,
|
||||
completedActivityCount: agenda?.completedCount ?? 0,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,11 +301,9 @@ test.describe('Municípios — jornadas por papel', () => {
|
|||
await expect(page.getByText('Cadastre apoiadores pelo celular.')).toBeVisible()
|
||||
|
||||
// The leader redirect aborts `goto`'s load event (ERR_ABORTED); the
|
||||
// redirect itself is the assertion, so navigate and wait for the target.
|
||||
await Promise.all([
|
||||
page.waitForURL(`${campaign.baseURL}/campanha/contatos`),
|
||||
page.goto(`${campaign.baseURL}/campanha/municipios`).catch(() => {}),
|
||||
])
|
||||
// redirect itself is the assertion, and `toHaveURL` retries onto it.
|
||||
await page.goto(`${campaign.baseURL}/campanha/municipios`).catch(() => {})
|
||||
await expect(page).toHaveURL(`${campaign.baseURL}/campanha/contatos`)
|
||||
|
||||
const supporterName = fixtures.value('Apoiador Liderança')
|
||||
const supporterPhone = fixtures.phone()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const input = (overrides: Partial<MunicipalityTriggerInput> = {}): MunicipalityT
|
|||
lastPledgeAgeDays: 3,
|
||||
coverageRatio: 0.6,
|
||||
coverageDeficit: 400,
|
||||
adversarySignal: null,
|
||||
hasAdversarySignal: false,
|
||||
hasRecentOrUpcomingActivity: false,
|
||||
completedActivityCount: 0,
|
||||
...overrides,
|
||||
|
|
@ -93,7 +93,7 @@ describe('P1 — reduto dormente ou ameaçado', () => {
|
|||
})
|
||||
|
||||
it('escalates to level 1 on any adversary signal — presence reads as confirmed', () => {
|
||||
expect(evaluate('P1', reduto({ adversarySignal: { present: true } }))?.triageLevel).toBe(1)
|
||||
expect(evaluate('P1', reduto({ hasAdversarySignal: true }))?.triageLevel).toBe(1)
|
||||
})
|
||||
|
||||
it('fires on a 2018→2022 vote drop even with a fresh signal', () => {
|
||||
|
|
@ -315,7 +315,7 @@ describe('evaluateMunicipalityTriggers — ordering and silence', () => {
|
|||
territorialClass: 'reduto',
|
||||
inCoreBlock: true,
|
||||
lqByYear: { 2014: 2.5, 2018: 2.6, 2022: 2.4 },
|
||||
adversarySignal: { present: true },
|
||||
hasAdversarySignal: true,
|
||||
coverageRatio: 1.2,
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue