Building a UI suite that survives its own frontend
85 end-to-end test cases and 48 page-object classes on a multi-tenant admin platform, built to survive two frontend migrations.

- end-to-end test cases
- 85
- page-object classes
- 48
- files, organised in layers
- 46
Store-operations features were shipping faster than they were being automated. Bulk wizards, operating hours and shutdowns, order-type settings, dayparts, item availability, store groups and promotions were covered mostly by manual regression. The specs that did exist were tightly coupled to the interface. They waited on arbitrary timeouts, built their test data inline, and broke every time the frontend moved to a new forms library or data-grid version. Each nightly run produced a mixture of genuine defects and test-side timing failures, and somebody had to sort one from the other by hand every morning.
We owned automation for the store-operations, store-groups, devices, customer-support and user-management areas of the application.
What we built
Eighty-five end-to-end test cases and forty-eight page-object classes across forty-six files, organised in layers: a base page, drawer and wizard classes, each with a GraphQL-aware variant. Fluent data builders for schedules, item availability, delivery providers, order-type settings and store groups, used both to seed data through the API and to fill the interface. A refactor of the shared parameterised drawer framework, which runs one generic CRUD suite against many entity drawers, moving it off inline random-data helpers and onto the builder pattern with each entity's metadata declared on the drawer class itself.
The decision that mattered
Every create, update and delete waits on the named GraphQL operation and its refetch, never on a sleep. Save actions wait for three things in order: the mutation, the success notification, and the refetch query.
The trade-off is real and we took it deliberately. Page objects have to know operation names, so a frontend engineer renaming a query breaks the tests loudly. We prefer that. A loud break takes an hour to fix. A silent flake costs a team its trust in the suite, and that trust does not come back easily.
What it produced
Eighty-five test cases and forty-eight page-object classes remain in use on the integration branch. When a forms-library migration removed the old store-list query and its element identifiers, four bulk-wizard tests broke; scoping the affected step by its ARIA region name rather than its identifiers brought all four back, and survived the migration after that one too.
