mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
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.
172 lines
6.1 KiB
TypeScript
172 lines
6.1 KiB
TypeScript
/**
|
|
* The states onboarding must refuse, and the one it must undo.
|
|
*
|
|
* Two halves. The API guards are cheap `cy.request` checks against the seeded
|
|
* demo customer — combinations the portal never offers, which is exactly why
|
|
* they have to be refused server-side rather than merely hidden. The second
|
|
* half is the expensive one and the reason this spec exists at all: going back
|
|
* in the wizard and un-ticking the investment licence has to cost what the
|
|
* settings switch costs, or a company finishes onboarding on registration data
|
|
* nobody verified, with no flag left to say so.
|
|
*/
|
|
|
|
import {
|
|
apiRequest,
|
|
companyByEmail,
|
|
fillAria,
|
|
portalToken,
|
|
signupCustomer,
|
|
signupIdentity,
|
|
typeRegistration,
|
|
noLicenceTin,
|
|
vatNumber,
|
|
wizardClick,
|
|
} from "./onboarding-utils";
|
|
|
|
const stamp = Date.now();
|
|
const who = signupIdentity("toggle", stamp);
|
|
|
|
/** The seeded demo customer: an ordinary company that came through eTrade. */
|
|
const DEMO_CUSTOMER = "user@gmail.com";
|
|
const demoPassword = () => Cypress.env("demoPassword") as string;
|
|
|
|
describe("onboarding — refused combinations", { retries: 0 }, () => {
|
|
it("refuses an investment licence for an Ethiopian company", () => {
|
|
portalToken(DEMO_CUSTOMER, demoPassword()).then((token) =>
|
|
apiRequest(
|
|
token,
|
|
"POST",
|
|
"/api/companies/onboarding/start",
|
|
{
|
|
companyType: "customer",
|
|
roles: ["importer"],
|
|
nationality: "ethiopian",
|
|
investorLicence: true,
|
|
},
|
|
false,
|
|
).then((res) => {
|
|
expect(res.status).to.eq(400);
|
|
expect(JSON.stringify(res.body)).to.contain(
|
|
"Only a foreign company can onboard on an investment licence",
|
|
);
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("refuses a co-operative that also claims an investment licence", () => {
|
|
// Ethiopian on purpose: a co-op sent as foreign is refused by the older
|
|
// co-operative guard, which would pass this test without the new one ever
|
|
// running. Ethiopian gets past that guard and lands on this one.
|
|
portalToken(DEMO_CUSTOMER, demoPassword()).then((token) =>
|
|
apiRequest(
|
|
token,
|
|
"POST",
|
|
"/api/companies/onboarding/start",
|
|
{
|
|
companyType: "customer",
|
|
roles: ["importer"],
|
|
nationality: "ethiopian",
|
|
cooperative: true,
|
|
investorLicence: true,
|
|
},
|
|
false,
|
|
).then((res) => {
|
|
expect(res.status).to.eq(400);
|
|
expect(JSON.stringify(res.body)).to.contain(
|
|
"it cannot also onboard on a foreign investment licence",
|
|
);
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("refuses to switch a company that never took the route", () => {
|
|
portalToken(DEMO_CUSTOMER, demoPassword()).then((token) =>
|
|
apiRequest(
|
|
token,
|
|
"POST",
|
|
"/api/companies/onboarding/revert-to-etrade",
|
|
undefined,
|
|
false,
|
|
).then((res) => {
|
|
expect(res.status).to.eq(400);
|
|
expect(JSON.stringify(res.body)).to.contain(
|
|
"already registered through eTrade",
|
|
);
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("onboarding — un-ticking the box mid-wizard", { retries: 0 }, () => {
|
|
it("clears the typed registration and reopens on the company step", () => {
|
|
signupCustomer(who, "Toggle");
|
|
|
|
cy.contains("button", "Foreign Company").click();
|
|
cy.contains("We operate on a foreign investment licence").click();
|
|
cy.contains("button", "Importer").click();
|
|
wizardClick("Continue");
|
|
|
|
cy.contains("Confirm your VAT number", { timeout: 20000 }).should(
|
|
"be.visible",
|
|
);
|
|
|
|
// A TIN eTrade knows but which holds no trade licence — the manual route's
|
|
// own shape. (A TIN eTrade has never heard of surfaces as an outage rather
|
|
// than as "nothing on file": the API wraps its 404 as "Failed to fetch",
|
|
// which ETradeInfo reads as unreachable. Different message, different
|
|
// test.)
|
|
fillAria('[aria-label^="TIN Number"]', noLicenceTin(stamp));
|
|
cy.contains("Nothing on file at eTrade for this TIN", {
|
|
timeout: 20000,
|
|
}).should("be.visible");
|
|
typeRegistration(`E2E Toggle Trading ${stamp}`);
|
|
fillAria('[aria-label="VAT Number"]', vatNumber(stamp));
|
|
wizardClick("Continue");
|
|
|
|
// The typed registration is now on file.
|
|
cy.contains("Company Owner", { timeout: 20000 }).should("be.visible");
|
|
companyByEmail(who.email).then((company) => {
|
|
expect(company.region, "typed address saved").to.eq("Addis Ababa");
|
|
expect((company.attributes ?? {})["investorLicence"]).to.eq(true);
|
|
});
|
|
|
|
// Back to the company step, then back again to the nationality phase.
|
|
wizardClick("Back");
|
|
cy.contains("Confirm your VAT number", { timeout: 20000 }).should(
|
|
"be.visible",
|
|
);
|
|
wizardClick("Back");
|
|
// `exist`, not `visible`: the heading scrolls under the modal's sticky
|
|
// header, and where the dialog happens to be scrolled says nothing about
|
|
// whether we are back on the nationality phase. The checkbox below is the
|
|
// thing this test actually needs to reach.
|
|
cy.contains("Where is your company registered?", { timeout: 20000 }).should(
|
|
"exist",
|
|
);
|
|
|
|
// Change of mind: this company is an ordinary foreign company after all.
|
|
cy.contains("We operate on a foreign investment licence").click();
|
|
wizardClick("Continue");
|
|
|
|
// Whatever was typed under the flag is gone, and the resume target is the
|
|
// company step — not the furthest step reached, which would skip the
|
|
// eTrade lookup the customer has just opted back into.
|
|
companyByEmail(who.email).then((company) => {
|
|
expect((company.attributes ?? {})["investorLicence"]).to.eq(false);
|
|
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).to.eq("company");
|
|
});
|
|
|
|
cy.contains("Confirm your VAT number", { timeout: 20000 }).should(
|
|
"be.visible",
|
|
);
|
|
// No typed-registration block any more: eTrade owns these fields again.
|
|
cy.contains("Nothing on file at eTrade for this TIN").should("not.exist");
|
|
cy.contains("Registration details").should("not.exist");
|
|
});
|
|
});
|
|
|
|
export {};
|