Files
edr-platform/e2e/freight/cypress/e2e/flows/onboarding_switch_back.cy.ts
Nathnael 6469c7fa52 test(e2e): cover every onboarding route across portal and backoffice
Five journeys, one file each, every one of them crossing from the portal into
the backoffice and cross-checking the database rather than the screen:

- ethiopian     eTrade verified, Fayda, approved, contract wizard reachable —
                including the dead end a TIN with no trade licence is for an
                ordinary company
- investor      foreign investment licence: nothing on file at eTrade, typed
                registration, passport identity, per-role licence still owed,
                and the backoffice's manual-entry badge and banner
- cooperative   no foreign option, no freight-forwarder role, the co-operative
                document set, no licence cards, its own badge and banner
- switch_back   settings → switch to eTrade → registration cleared, company
                pending, wizard reopened on the company step → re-run through
                eTrade → the flag is gone from the backoffice
- guards        the refused combinations, and the mid-wizard un-tick that has
                to clear the typed registration

Replaces the old onboarding.cy.ts (removed a commit earlier by accident of a
staged deletion): it drove a wizard shape that no longer exists — Fayda before
the company step, a "Personnel" step — so it could only ever have been red.

Notes for whoever edits these next. Attach files to the FIRST empty dropzone,
never by index — SmartFileInput removes the input once a file is on it. Resolve
the company from the database after any cross-origin hop, never from module
state: Cypress re-evaluates the spec bundle and Date.now() with it, which is
what latestJourney's run-stamp cutoff is for. And the deliberate eTrade 400 is
ignored as an uncaught exception — the portal handles that outcome on screen
but leaves the rejected request unhandled at the promise level.
2026-08-18 11:38:37 +00:00

159 lines
6.1 KiB
TypeScript

/**
* Giving the investment-licence route back.
*
* A company that ticked the box by mistake, or that has since been registered
* with the trade registry, switches from Settings → Company. It is a
* re-application rather than a settings edit, and this spec is about proving
* that literally: the typed registration is cleared (nothing on file was ever
* checked against a licence), the company returns to pending, onboarding
* reopens on the company step — and only after a real eTrade lookup does the
* backoffice stop flagging it.
*
* Each test is one leg of a single journey, in order, retries off. The
* portal ↔ backoffice hops re-evaluate the spec bundle, so every leg resolves
* the company from the database rather than from module state.
*/
import {
approveFirstProfile,
companyByEmail,
completeInvestorOnboarding,
etradeTin,
expectProfileActive,
fillAria,
latestJourney,
openCustomer,
signupIdentity,
wizardClick,
SIGNUP_PASSWORD,
} from "./onboarding-utils";
const stamp = Date.now();
const who = signupIdentity("switchback", stamp);
describe("onboarding — switching back to eTrade registration", { retries: 0 }, () => {
it("onboards on an investment licence", () => {
completeInvestorOnboarding(who, stamp, {
companyName: `E2E Switchback Trading ${stamp}`,
});
companyByEmail(who.email).then((company) => {
expect((company.attributes ?? {})["investorLicence"]).to.eq(true);
expect(company.region, "typed address").to.eq("Addis Ababa");
});
});
it("is approved by the backoffice", () => {
cy.loginBackoffice("chief@edr.local");
latestJourney("switchback").then((company) => {
openCustomer(company.name);
cy.contains("Manual entry · investment licence").should("be.visible");
approveFirstProfile();
expectProfileActive(company.name);
});
});
it("switches back from settings, which clears the typed registration", () => {
latestJourney("switchback").then((company) => {
cy.loginPortal(company.email, SIGNUP_PASSWORD);
});
cy.visitPortal("/settings");
cy.contains("Registration source", { timeout: 20000 }).should("be.visible");
cy.contains("button", "Switch to eTrade registration").click();
// The confirmation has to state the cost outright — this is the screen
// that decides whether the customer knows they are re-applying.
cy.contains("Switch to eTrade registration?").should("be.visible");
cy.contains("The registration details you typed are cleared").should(
"be.visible",
);
cy.contains("Your company goes back to pending").should("be.visible");
cy.contains("button", "Switch and re-apply").click();
cy.contains("Registration source", { timeout: 20000 }).should("not.exist");
latestJourney("switchback").then((company) => {
expect((company.attributes ?? {})["investorLicence"]).to.be.undefined;
expect(company.status).to.eq("pending");
expect(company.onboarding_completed).to.eq(false);
// The wizard treats a populated registration as a lookup that already
// passed, so leaving any of it behind would walk the customer straight
// past the eTrade step this switch exists to reach.
expect(company.region, "typed address cleared").to.be.null;
expect(company.licence_number).to.be.null;
expect(company.etrade_phone).to.be.null;
expect(company.onboarding_step, "resume target").to.eq("company");
});
});
it("re-runs onboarding through eTrade and resubmits", () => {
latestJourney("switchback").then((company) => {
cy.loginPortal(company.email, SIGNUP_PASSWORD);
});
cy.visitPortal("/portal");
// Reopened on the company step — not on the furthest step reached before.
cy.contains("Confirm your VAT number", { timeout: 30000 }).should(
"be.visible",
);
// The typed registration section is gone: this is an ordinary company now.
cy.contains("Nothing on file at eTrade for this TIN").should("not.exist");
fillAria('[aria-label^="TIN Number"]', etradeTin(stamp));
cy.contains("Verified with eTrade", { timeout: 20000 }).should("be.visible");
cy.wait(500);
wizardClick("Continue");
// Owner, representation and contact are already satisfied server-side —
// the switch keeps everything except the registration — so each step only
// needs advancing.
cy.contains("Company Owner", { timeout: 20000 }).should("be.visible");
wizardClick("Continue");
cy.contains("The owner acts for the company", { timeout: 20000 }).should(
"be.visible",
);
wizardClick("Continue");
cy.contains("Contact Person", { timeout: 20000 }).should("be.visible");
wizardClick("Continue");
// Documents and the licence were uploaded before the switch and survive
// it, so the step is already satisfied.
cy.contains("Upload Importer Business license file(s)", {
timeout: 20000,
}).should("be.visible");
wizardClick("Submit for review");
cy.contains("You're all set", { timeout: 30000 }).should("be.visible");
latestJourney("switchback").then((company) => {
expect(company.onboarding_completed).to.eq(true);
expect((company.attributes ?? {})["investorLicence"]).to.be.undefined;
// eTrade answered this time, and its licence is on file.
expect(company.licence_number).to.eq("LIC-E2E-0001");
});
});
it("the backoffice no longer flags it", () => {
cy.loginBackoffice("chief@edr.local");
latestJourney("switchback").then((company) => {
openCustomer(company.name);
cy.contains("eTrade trade licence").should("be.visible");
cy.contains("Manual entry").should("not.exist");
cy.contains("Registration entered by hand").should("not.exist");
});
});
it("offers nothing to switch to a customer who came through eTrade", () => {
// The seeded demo customer onboarded the ordinary way, so the card must
// not be on its settings page at all.
cy.loginPortal();
cy.visitPortal("/settings");
cy.contains("Operational Services", { timeout: 20000 }).should("be.visible");
cy.contains("Registration source").should("not.exist");
});
});
export {};