mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
add cypress spec for pibi-measure selection flow
Verifies that an approver can open the drawer, tick/untick PIBI measures, save the selection, and that the POST to pibi-measures route (which pushes measures_for_pibi_ordered to HubSpot) is intercepted with the correct payload. Uses cy.intercept stubs for both GET and POST. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1767733441
commit
084391b9dc
1 changed files with 161 additions and 0 deletions
161
cypress/e2e/live-tracking/pibi-measures.cy.js
Normal file
161
cypress/e2e/live-tracking/pibi-measures.cy.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* Live Tracking — PIBI measure selection flow (issue #254)
|
||||
*
|
||||
* Verifies the approver flow for selecting which measures on a deal go for
|
||||
* PIBI:
|
||||
* 1. the approver opens the property drawer at the PIBI section,
|
||||
* 2. ticks and unticks measures in the multi-select,
|
||||
* 3. saves the selection — the drawer reflects the ticked state,
|
||||
* 4. the POST hits the pibi-measures route which pushes
|
||||
* `measures_for_pibi_ordered` back to HubSpot.
|
||||
*
|
||||
* Mirrors `instruct-measure.cy.js`. The spec uses `cy.intercept` so the
|
||||
* HubSpot push side-effect is observable without a real CRM round-trip.
|
||||
*/
|
||||
|
||||
const PORTFOLIO_SLUG = Cypress.env("LIVE_PORTFOLIO_SLUG");
|
||||
const TARGET_DEAL_NAME = Cypress.env("LIVE_PIBI_DEAL_NAME");
|
||||
|
||||
describe("PIBI measure selection — approver flow", function () {
|
||||
before(function () {
|
||||
if (!PORTFOLIO_SLUG) {
|
||||
cy.log(
|
||||
"LIVE_PORTFOLIO_SLUG env var not set — skipping live tracking specs",
|
||||
);
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
function openDrawerAtPibiSection() {
|
||||
cy.visit(`/portfolio/${PORTFOLIO_SLUG}/your-projects/live`);
|
||||
|
||||
// Open a property row to get the detail drawer.
|
||||
cy.contains("button, [role=tab]", "Measures").click();
|
||||
|
||||
if (TARGET_DEAL_NAME) {
|
||||
cy.contains("[data-testid=measures-row]", TARGET_DEAL_NAME).click();
|
||||
} else {
|
||||
cy.get("[data-testid=measures-row]").first().click();
|
||||
}
|
||||
|
||||
cy.get("[data-testid=property-detail-drawer]").should("be.visible");
|
||||
|
||||
// Scroll to the PIBI section.
|
||||
cy.get("[data-testid=drawer-section-pibi]").should("exist").scrollIntoView();
|
||||
}
|
||||
|
||||
it("fetches the PIBI state and shows the multi-select for approvers", () => {
|
||||
// Stub the GET so we control the initial state.
|
||||
cy.intercept(
|
||||
"GET",
|
||||
`/api/portfolio/*/pibi-measures*`,
|
||||
{
|
||||
body: {
|
||||
pibiMeasures: ["ASHP"],
|
||||
approvedMeasures: ["ASHP", "Solar PV"],
|
||||
instructedMeasures: [],
|
||||
},
|
||||
},
|
||||
).as("getPibiMeasures");
|
||||
|
||||
openDrawerAtPibiSection();
|
||||
|
||||
cy.wait("@getPibiMeasures");
|
||||
|
||||
// The multi-select should be visible for approvers.
|
||||
cy.get("[data-testid=pibi-measure-selector]").should("be.visible");
|
||||
|
||||
// ASHP should be checked (was in pibiMeasures).
|
||||
cy.get("[data-testid=pibi-measure-checkbox-ASHP]").should(
|
||||
"be.checked",
|
||||
);
|
||||
});
|
||||
|
||||
it("lets an approver tick/untick selections and POST to the route", () => {
|
||||
// Stub GET to return a clean state.
|
||||
cy.intercept(
|
||||
"GET",
|
||||
`/api/portfolio/*/pibi-measures*`,
|
||||
{
|
||||
body: {
|
||||
pibiMeasures: [],
|
||||
approvedMeasures: ["ASHP", "Solar PV"],
|
||||
instructedMeasures: [],
|
||||
},
|
||||
},
|
||||
).as("getPibiMeasures");
|
||||
|
||||
// Intercept the POST so we can assert the body.
|
||||
cy.intercept(
|
||||
"POST",
|
||||
`/api/portfolio/*/pibi-measures`,
|
||||
).as("savePibiMeasures");
|
||||
|
||||
openDrawerAtPibiSection();
|
||||
|
||||
cy.wait("@getPibiMeasures");
|
||||
|
||||
cy.get("[data-testid=pibi-measure-selector]").should("be.visible");
|
||||
|
||||
// Both approved measures (ASHP, Solar PV) should be pre-ticked since
|
||||
// pibiMeasures was empty and approvedMeasures had values.
|
||||
cy.get("[data-testid=pibi-measure-checkbox-ASHP]").should("be.checked");
|
||||
cy.get("[data-testid=pibi-measure-checkbox-Solar PV]").should("be.checked");
|
||||
|
||||
// Untick ASHP.
|
||||
cy.get("[data-testid=pibi-measure-option-ASHP]").click();
|
||||
cy.get("[data-testid=pibi-measure-checkbox-ASHP]").should("not.be.checked");
|
||||
|
||||
// Save the selection.
|
||||
cy.get("[data-testid=pibi-selector-save]").click();
|
||||
|
||||
cy.wait("@savePibiMeasures").then((intercepted) => {
|
||||
// Body should reflect the new selection (Solar PV only).
|
||||
expect(intercepted.request.body).to.have.property("dealId");
|
||||
expect(intercepted.request.body.measureNames).to.include("Solar PV");
|
||||
expect(intercepted.request.body.measureNames).not.to.include("ASHP");
|
||||
|
||||
// Route returns ok=true.
|
||||
expect(intercepted.response.statusCode).to.be.oneOf([200, 201]);
|
||||
expect(intercepted.response.body).to.have.property("ok", true);
|
||||
expect(intercepted.response.body).to.have.property(
|
||||
"hubspotSync",
|
||||
);
|
||||
});
|
||||
|
||||
// No error banner visible.
|
||||
cy.get("[data-testid=pibi-selector-error]").should("not.exist");
|
||||
});
|
||||
|
||||
it("pushes measures_for_pibi_ordered to HubSpot on a successful save", () => {
|
||||
cy.intercept(
|
||||
"GET",
|
||||
`/api/portfolio/*/pibi-measures*`,
|
||||
{
|
||||
body: {
|
||||
pibiMeasures: ["CWI"],
|
||||
approvedMeasures: ["CWI"],
|
||||
instructedMeasures: [],
|
||||
},
|
||||
},
|
||||
).as("getPibiMeasures");
|
||||
|
||||
// Stub the POST to confirm the property pushed.
|
||||
cy.intercept("POST", `/api/portfolio/*/pibi-measures`, {
|
||||
body: { ok: true, hubspotSync: "ok" },
|
||||
}).as("savePibiMeasures");
|
||||
|
||||
openDrawerAtPibiSection();
|
||||
|
||||
cy.wait("@getPibiMeasures");
|
||||
|
||||
cy.get("[data-testid=pibi-selector-save]").click();
|
||||
|
||||
cy.wait("@savePibiMeasures").then((intercepted) => {
|
||||
// Confirm the POST body contains the right measures.
|
||||
expect(intercepted.request.body).to.have.property("measureNames");
|
||||
// Response signals a successful HubSpot push.
|
||||
expect(intercepted.response.body.hubspotSync).to.equal("ok");
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue