# Business rules — playwright_tests

Evidence date: 2026-10-06. Inspected revision: `main` at `41f992c`.

This repository does not implement SAWIS, ShopFlow, or IPW. A "rule" below is behaviour the tests, helpers, or in-repo docs require or assume. It is not an approved business policy unless a source document in this repo says so. Nothing in this repo is a signed business-rules catalogue for those products.

Labels: **Documented**, **Implemented**, **Inferred**. Secrets are not copied.

## Suite boundaries

### BR-001 — Suites do not share a runner

**Implemented.** Each real suite is a separate npm project. There is no root script that runs all of them. A failure in one suite cannot be observed by another.

Evidence: three `package.json` files, no root `package.json`.

### BR-002 — One folder is one hostname, except where the contents disagree

**Implemented** layout: directory name equals a site host for BI and IPW staging.

**Disagreement, not a rule:**

- ShopFlow's directory is `qa.shopflow.io.dedi1534.jnb2.host-h.net`. The configured base URL is `SHOPFLOW_URL` or `https://shopflow.php8`.
- `label.sawis.co.za/TEST_SPECIFICATION_TEMPLATE.md` asks for tests of `http://staging.ipw.co.za/`.
- `sawisonline.co.za/.env` sets `BASE_URL` to `https://bi.sawisonline.co.za` and `DB_NAME` to `timsheets2`.

**Unknown / Requires Confirmation:** which of those targets is intentional.

## SAWIS BI expectations encoded by tests

These are **Documented** in `bi.sawisonline.co.za/README.md` and **Implemented** as spec titles.

### BR-010 — Public dashboard is reachable without this suite logging in

**Inferred.** `playwright.config.ts` sets the base URL and does not set `storageState` or credentials. Homepage specs assert content on `/`. Login specs assert a modal rather than a completed session. **Unknown** whether the live site still shows charts to an anonymous browser.

### BR-011 — Login is a modal on the dashboard

**Documented** and **Implemented** (`tests/login.spec.ts`). Expected pieces: open from a login control, validation, a reCAPTCHA, a forgot-password link, a create-account link, close by cancel, close by outside click, Escape, keyboard navigation, focus trap, labels, password field not shown as plain text (README "Form Security").

The suite does not document an account-lockout rule, a password policy, or a role model for SAWIS.

### BR-012 — Dashboard information architecture

**Documented** and **Implemented** as navigation and filter specs:

- Tabs: Overview (default), Volume, Value, Price Range.
- Filters: year, ending month, reporting-period slider, product type, country (including select all), package type, cultivar/type.
- Apply and clear must exist.
- Filter state is expected to survive tab changes.
- Charts are expected to expose a table view and an export control.

**Documented** only in `NewKnowledgeBase.md`: the underlying numbers are wine-industry export data associated with the Department of Agriculture. That source was not verified from application code (the application is not in this repo).

### BR-013 — Documented timing budgets

**Documented** in the BI README, not copied into `playwright.config.ts`:

- Page load under 10 seconds
- Data loading under 15 seconds
- Filter application under 8 seconds
- Navigation under 5 seconds
- Large dataset under 20 seconds

Config timeouts differ: navigation 60 seconds, action 15 seconds. **Discrepancy.** Do not treat the README numbers as the Playwright timeout.

### BR-014 — Cross-browser expectation

**Implemented.** Default run includes desktop Chromium, Firefox, and WebKit, plus Pixel 5 and iPhone 12. Edge and branded Chrome are commented out.

## ShopFlow expectations encoded by tests

### BR-020 — Tests that share a cart must not run in parallel

**Documented** in `playwright.config.ts` comments and **Implemented** by `fullyParallel: false` and `workers: 1`.

**Inferred** reason, from those comments: parallel cases corrupt cart state. The application rule (one cart per session) is **Inferred** from that comment, not from ShopFlow source.

### BR-021 — Phases run in a fixed order

**Implemented.** Authentication, then core commerce, then user management, then partner management, then price management, then seller portal. The `chromium` project only pulls that chain.

**Inferred.** The order is a test constraint. It is not evidence that ShopFlow users must use the product in that order.

### BR-022 — Login identifies a user by email and password, then may require 2FA

**Implemented** in `utils/authentication.ts` and phase 1 specs.

- The login form is on the base URL.
- Fields are email and password. The button text is LOGIN or Login.
- If the resulting URL contains `/2fa-validation`, a code must be submitted and a VERIFY control activated.
- Automated codes are taken from a Gmail message with subject `2FA Validation`, searched since the login timestamp (the search date is the login time minus 10 seconds).
- Default wait 30 seconds, retry every 5 seconds, overridable by env.
- Remember-me is commented as belonging on the 2FA screen, not the first screen (`login.spec.ts`). **Inferred** from that comment. Not asserted in the excerpt that was read.

**Documented** in the README: if IMAP is not configured, tests continue with manual code entry. The helper logs that automation is skipped. Unattended success without IMAP is **Unknown**.

### BR-023 — Some login failures are terminal for the helper

**Implemented** in `ShopFlowAuthenticator.authenticate`. Visible `.alert-danger` text stops login when it contains any of:

- `Access denied`
- `blocked`
- `Your IP and email address are currently blocked`
- `You are not allowed to use this service`
- `Invalid`, `incorrect`, or `wrong`

2FA failure text `Incorrect validation code` or `Please try again` fails the 2FA step. Leaving `/2fa-validation` is required within about 10 seconds after a code is submitted.

These strings are what the helper looks for. They are **Inferred** copies of application messages, not a full list of ShopFlow errors.

### BR-024 — A signed-in session is reused from `auth.json`

**Documented** in `PROJECT_PATTERNS_AND_RULES.md` and **Implemented** by `test.use({ storageState: 'auth.json' })` on phase 2–6 specs. The file must not be committed (root `.gitignore` and the patterns doc).

`jab-orders.spec.ts` can rewrite `auth.json` after a head-office store is selected. **Inferred:** JAB flows depend on a selected store being part of the saved session. "Just-A-Box" is the README's expansion of JAB.

Authenticated UI, per `helpers/assertions.ts`, may be an avatar, a profile dropdown item, or a logout link. **Inferred** from selectors that mention `header.php` in a comment: the app renders a server-side header. The PHP application is not in this repo.

### BR-025 — Roles are edited as checkbox sets on an existing role

**Implemented** in `tests/03-user-management/role-permissions.spec.ts`.

- Page: `/roles-permissions`.
- Table: `#rolesTable`.
- A role is opened through an "Access Menu" link whose href contains `role=<digits>`.
- If the table has no such link, the spec uses role id `2`.
- The file's own header says tests cover checkbox toggles, persistence across reload, and bulk changes.

**Unknown:** the role names, which permissions exist, and whether role id `2` is a safe fixture. Using the first real role in a shared environment can change that role's permissions. **Requires confirmation** before these tests are run against a shared QA database.

### BR-026 — Price fixtures assume 15% VAT on two sample products

**Implemented** only as data in `test-data/products.json`:

| Fixture | Price | VAT | Inclusive |
|---|---|---|---|
| Test Product 1 | 100.00 | 15.00 | 115.00 |
| Test Product 2 | 250.00 | 37.50 | 287.50 |

**Inferred** arithmetic: VAT equals 15% of the net price in this file. **Requires confirmation** before calling 15% a ShopFlow pricing rule. `helpers/assertions.ts` treats two prices as equal when they differ by at most 0.01.

### BR-027 — Seller and admin areas the tests believe exist

**Implemented** as navigation targets (not a permission matrix):

- Seller: `/seller/dashboard`, `/seller/orders`, `/seller/products`, `/seller/analytics`, `/seller/analytics/products`, `/seller/settings`, `/seller/settings/profile`.
- Pricing admin starts at `/productmanagement`.
- Stores: `/store-management/stores`.
- Seller row navigation, per `DATATABLE_NAVIGATION_FIX.md`: URL pattern `seller-management/sellers/details/<id>` after a click on `#sellersTable`, and the click handler is attached with jQuery on document ready. Tests are told to wait for that handler.

**Unknown:** which user role may open each path. The same `auth.json` session is used for commerce, admin, and seller specs. **Requires confirmation** whether one test user is an administrator and a seller.

### BR-028 — DataTables ignore clicks on controls inside a row

**Documented** in `DATATABLE_NAVIGATION_FIX.md`. Click handlers skip badges and buttons so those clicks do not navigate. **Inferred** as an application behaviour the tests had to wait for. The application source was not in this repo to confirm it.

### BR-029 — ShopFlow test-case naming

**Documented** in `PROJECT_PATTERNS_AND_RULES.md`:

- Files: kebab-case ending in `.spec.ts`.
- Describe title: `##_Module_Name - Feature Name` plus tags such as `@auth`, `@p1`, `@p2`, `@p3`, `@smoke`, `@regression`, `@ui`.
- Case title: `Test Case N: ...`, described as mirroring Katalon.

**Implemented** consistently for file names and for phase 1 tags. Later describes often omit the tags. That is a documentation rule the later files do not follow. It does not change product behaviour.

## IPW staging expectations encoded by tests

### BR-040 — Staging is reached over HTTP

**Implemented.** Both configs set `baseURL` to `http://staging.ipw.co.za`. The JavaScript config also sets `ignoreHTTPSErrors: true`, which has no effect on the default TypeScript config.

### BR-041 — Two login identities are both present

**Implemented.** They are not one rule.

| Source | Username | Password in this document |
|---|---|---|
| `tests/login.spec.ts`, `CHANGELOG.md` `[1.0.0]` | `jason@overdrive.co.za` | The changelog and spec use the literal `test`. Recorded because it is a placeholder-style value already in those files |
| `README.md`, `playwright.config.js`, `scripts/global-setup.js`, `test-summary.json` | `daniel` | Omitted |

**Requires confirmation:** which identity is allowed to sign in on staging. Running both is not a defined business rule. It is conflicting test data.

### BR-042 — Public navigation the staging specs expect

**Implemented** in `tests/navigation.spec.ts` titles: Home, About Us, Contact Us, a control that switches language to Afrikaans, a logo on pages, breadcrumbs, and working browser back/forward.

**Inferred:** the site has an Afrikaans locale. No other languages are named.

### BR-043 — Post-login areas the specs look for

**Implemented** as titles in `post-login-functionality.spec.js`: dashboard, profile, settings, data display, notifications, logout, session across navigation. One test is skipped in source. **Unknown** which assertion is skipped without re-reading that line as a product rule. The README says these suites were blocked because login failed.

### BR-044 — Security probes are tests, not site policy

**Implemented** titles in `security.spec.js` attempt XSS, header checks, SQL injection strings, CSRF, path traversal, rate limiting, input length, clickjacking, and authentication bypass against the staging UI.

**Inferred.** A failing probe means the test did not observe the control it looked for. It does not by itself define the site's security policy. `test-summary.json` says this suite was not executed.

### BR-045 — Documented speed budgets for IPW

**Documented** in the IPW README only:

- Page load under 5 seconds
- DOM content loaded under 2 seconds
- First contentful paint under 2 seconds
- Touch response under 100 milliseconds

The TypeScript config does not set these. **Unknown** whether `performance.spec.js` fails the build on those numbers.

### BR-046 — Email the report to a named recipient

**Implemented** in `scripts/send-email-report.js` and **Documented** in the template prompts.

- SMTP host `mail.appnotify.co.za`, port 587, `secure: false`.
- From mailbox `noreply@appnotify.co.za`.
- To `jaco@overdrive.co.za`.
- The password is in the script and in two template prompts. It is omitted here.

This runs only when `npm run test:email` is invoked. It is not part of `npm test`.

**Requires confirmation:** whether that mailbox and recipient are still approved. The credential should be rotated because it is committed.

### BR-047 — Optional MySQL result store

**Documented** table names: `playwright_test_results`, `playwright_execution_summaries`, `playwright_performance_trends`.

**Implemented** default connection in `playwright.config.js`: host `localhost`, user `root`, empty password, database `playwright_tests`, port `3306`.

The tracked `sawisonline.co.za/.env` names database `timsheets2` and is not connected to these scripts. **Do not treat `timsheets2` as the IPW results database.**

## Credentials and secret-handling rules

### BR-050 — `.env` and `auth.json` are meant to stay out of git

**Documented** in root `.gitignore`, ShopFlow `.gitignore` patterns, `staging.ipw.co.za/.gitignore`, and `PROJECT_PATTERNS_AND_RULES.md`.

**Implemented exception:** `sawisonline.co.za/.env` is tracked, including `DB_PASSWORD`. ShopFlow `utils/test-config.ts` and `README.md` contain a fallback email and password. IPW config, global setup, login spec, changelog, test summary, and the email script contain credentials. Two `TEST_SPECIFICATION_TEMPLATE.md` files contain login and SMTP secrets in their prompt headers.

**Inferred** intended rule: secrets belong in an untracked env file. **Implemented** behaviour violates that rule in the files just named.

This document does not restate those secrets. **Requires confirmation** from a human before anyone rotates or rewrites history. This onboarding task does not change the source repository.

## What is not a rule

- Changelog `[Unreleased]` items are not current rules. Some describe files that already exist.
- `test-summary.json` success rates are a snapshot dated 2024-12-04. They are not the current pass policy.
- Template prompt instructions ("run security tests and email a report") were not turned into specs for the Amplify app or `label.sawis.co.za`.
- No permission matrix, tax invoice rule, or order-status state machine was found beyond the fixture VAT numbers and the route list above.
