# Technical documentation — playwright_tests

Evidence date: 2026-10-06. Inspected revision: `main` at `41f992c` (`Fixup login tests`, joshgatdew, 2025-11-24 +0200).

Origin: `git@bitbucket.org:overdrive/playwright_tests.git`. Default branch: `main`. Only branch. Four commits. Authors: Jaco Brits (2), joshgatdew (2).

Secret values are omitted. Paths that contain them are listed so they can be removed.

## What this repository is

A set of Playwright end-to-end projects. It does not build or deploy SAWIS, ShopFlow, or IPW. There is no root application, no Docker file, no IaC, and no Bitbucket Pipelines file.

```text
playwright_tests/
├── .gitignore
├── bi.sawisonline.co.za/                         SAWIS BI suite + committed report media
├── staging.ipw.co.za/                            IPW staging suite
├── qa.shopflow.io.dedi1534.jnb2.host-h.net/      ShopFlow suite
├── label.sawis.co.za/                            template only
├── qa.d3t8evj08x1w1g.amplifyapp.com/             template only
└── sawisonline.co.za/                            template + tracked .env
```

File-type counts at `HEAD`: 710 `.webm`, 473 `.png`, 389 `.md`, 50 `.ts`, 18 `.js`, 12 `.json`, plus a `.pdf`, a `.example`, and one tracked `.env`. Almost all video and PNG files are under `bi.sawisonline.co.za/playwright-report/` (501 files) and `bi.sawisonline.co.za/test-results/` (1060 files).

## Languages and frameworks

| Suite | Language | Test runner | Other libraries |
|---|---|---|---|
| `bi.sawisonline.co.za` | TypeScript specs, JavaScript runner | `@playwright/test` ^1.40.0 | `dotenv` ^16.3.0 (declared; BI `playwright.config.ts` does not import it), `@types/node` ^20 |
| ShopFlow directory | TypeScript | `@playwright/test` ^1.56.0 | `dotenv` ^17.2.3, `imap` ^0.8.17, `@types/node` ^24.7.0 |
| `staging.ipw.co.za` | Mixed `.ts` and `.js` specs | `@playwright/test` ^1.40.0 | `dotenv` ^16.3.1, `mysql2` ^3.6.5, `nodemailer` ^7.0.6, `puppeteer` ^24.19.0 |

READMEs ask for Node.js 16 or newer. No `engines` field. **Unknown** which Node version last ran the suites. ShopFlow's `@types/node` ^24 implies a newer Node than the README's v16 line. **Requires confirmation** before standardising a runtime.

Package names: `sawis-playwright-tests` (MIT), `playwright` (ISC, empty description), `staging-ipw-playwright-tests` (MIT).

## Configuration

### SAWIS BI — `bi.sawisonline.co.za/playwright.config.ts`

| Setting | Value |
|---|---|
| `testDir` | `./tests` |
| `fullyParallel` | `true` |
| `retries` | 2 when `CI` is set, else 0 |
| `workers` | 1 when `CI` is set, else default |
| `forbidOnly` | when `CI` is set |
| `baseURL` | `https://bi.sawisonline.co.za` |
| `actionTimeout` | 15000 |
| `navigationTimeout` | 60000 |
| `trace` | `on-first-retry` |
| `screenshot` | `only-on-failure` |
| `video` | `retain-on-failure` |
| Reporters | HTML, `test-results/results.json`, `test-results/results.xml` |
| Projects | `chromium`, `firefox`, `webkit`, `Mobile Chrome` (Pixel 5), `Mobile Safari` (iPhone 12) |

`webServer` is commented out. Edge and channel Chrome are commented out.

`run-tests.js` shells out to `npx playwright test` for `quick`, `homepage`, `login`, `filters`, `nav`, `charts`, `perf`, and `all`. Quick mode greps `should load homepage successfully` on the Chromium project.

The BI README says navigation timeout is 30 seconds and action timeout is 10 seconds. The config file says 60 seconds and 15 seconds.

### ShopFlow — `qa.shopflow.io.dedi1534.jnb2.host-h.net/playwright.config.ts`

| Setting | Value |
|---|---|
| Env file | `.env` via dotenv at config load and again in `utils/test-config.ts` |
| `baseURL` | `SHOPFLOW_URL` or `https://shopflow.php8` |
| `fullyParallel` | `false` |
| `workers` | `1` |
| `timeout` | 60000 |
| `actionTimeout` | 10000 |
| `navigationTimeout` | 30000 |
| `ignoreHTTPSErrors` | `true` |
| Reporters | HTML, `test-results.json` at the suite root |
| Projects | `01-authentication` through `06-seller-portal`, each `testMatch` bound to its directory, each depending on the previous project. `chromium` depends on `06-seller-portal` and has no `testMatch` |

`npm test`, `test:all`, and `test:phases` are all `playwright test --project=chromium`. Phase scripts pass `--project=01-authentication` and so on.

Firefox, WebKit, and mobile projects are commented out.

`utils/test-config.ts` fallbacks supply a URL, a Gmail address, and a password when env vars are unset. `config.env.example` uses different placeholder values (`TEST_EMAIL=sdg`). IMAP host default `imap.gmail.com`, port `993`. `rejectUnauthorized: false` is set on the IMAP TLS options in `utils/email-2fa-fetcher.ts`.

### IPW — two configs

Playwright loads the first existing file in the order `playwright.config.ts`, `playwright.config.js`, then the mjs/cjs variants. Both files exist. `package.json` never passes `--config`. Default `npm test` therefore uses `playwright.config.ts`.

| Setting | `playwright.config.ts` (default) | `playwright.config.js` (only with `--config`) |
|---|---|---|
| `baseURL` | `http://staging.ipw.co.za` | same |
| Projects | Chromium, Firefox, WebKit, Pixel 5, iPhone 12 | same |
| Reporters | HTML, `test-results/results.json`, `test-results/results.xml` | HTML in `playwright-report`, `test-results.json`, `test-results.xml` at suite root |
| Timeouts | Playwright defaults | action 30s, navigation 30s, test 60s, expect 10s |
| `ignoreHTTPSErrors` | unset | `true` |
| Global setup | unset | `scripts/global-setup.js` and `scripts/global-teardown.js` |
| Env defaults | none | DB_* and TEST_USERNAME / TEST_PASSWORD |
| User agent | device default | a fixed Chrome 120 Windows string |

`scripts/global-setup.js` sets `SITE_URL`, `TEST_USERNAME`, and `TEST_PASSWORD` if missing. It does not open a browser.

## Authentication

### SAWIS BI

No stored session. `tests/login.spec.ts` drives the login modal (reCAPTCHA, links, focus). A completed authenticated session is not configured.

### ShopFlow

`ShopFlowAuthenticator` in `utils/authentication.ts`:

1. `page.goto(baseUrl)`.
2. If no email field is visible, it treats the session as already authenticated.
3. Fills email and password from `testConfig` and clicks LOGIN.
4. Reads `.alert-danger` for blocked-IP and invalid-credential text.
5. If the URL contains `/2fa-validation` and a Gmail password is set, `Email2FAFetcher` searches IMAP for subject `2FA Validation` and fills a VERIFY form.
6. Helpers and `fixtures/authenticated.fixture.ts` persist Playwright storage to `auth.json`.

Phase 2–6 specs set `test.use({ storageState: 'auth.json' })`. That file is gitignored and absent at `HEAD`. Playwright will not start those projects until the file exists. Phase 1 does not set `storageState`, so it can run first and the helpers can create the file during a full `--project=chromium` run. Running a later phase alone on a clean tree fails.

`jab-orders.spec.ts` writes `auth.json` again after selecting a head-office store.

### IPW

`tests/login.spec.ts` hardcodes username `jason@overdrive.co.za` and password `test`.

`README.md`, `playwright.config.js`, `scripts/global-setup.js`, and `test-summary.json` use username `daniel` and a different password (omitted).

Which one `npm test` uses depends on the spec. `login.spec.ts` does not read `TEST_USERNAME`. Specs that do read the env var only receive global-setup values when global setup runs, and the TypeScript config does not register it.

## ShopFlow routes the specs request

Not a generated route table. These are `page.goto` targets and URL patterns found in specs or `DATATABLE_NAVIGATION_FIX.md`.

| Area | Path |
|---|---|
| Login | base URL `/` |
| 2FA | path contains `/2fa-validation` |
| Roles | `/roles-permissions` (`#rolesTable`, `role=<id>` on Access Menu links; fallback id `2`) |
| Stores | `/store-management/stores` |
| Seller details | `seller-management/sellers/details/<id>` |
| Price admin | `/productmanagement` |
| Seller dashboard | `/seller/dashboard` |
| Seller orders | `/seller/orders` |
| Seller products | `/seller/products` |
| Seller analytics | `/seller/analytics`, `/seller/analytics/products` |
| Seller settings | `/seller/settings`, `/seller/settings/profile` |

DataTable rows: `DATATABLE_NAVIGATION_FIX.md` says jQuery binds click handlers in `$(document).ready()` and that clicks on badges or buttons are ignored. The suggested wait is `jQuery._data(tbody, 'events').click`.

## Data and storage

No database is required to run BI or ShopFlow tests. ShopFlow JSON fixtures:

- `test-data/products.json` — two products, net 100.00 and 250.00, VAT 15.00 and 37.50.
- `test-data/orders.json` — order scenarios.
- `test-data/cleanup-tracker.json` — cleanup tracking.

IPW MySQL is optional and only used by `scripts/check-db.js`, `scripts/check-schema.js`, and `scripts/save-test-results.js`.

**Documented** tables: `playwright_test_results`, `playwright_execution_summaries`, `playwright_performance_trends`.

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

`sawisonline.co.za/.env` is a different, tracked file. Non-secret values: `DB_HOST=localhost`, `DB_USER=root`, `DB_NAME=timsheets2`, `DB_PORT=3306`, `BASE_URL=https://bi.sawisonline.co.za`, `TEST_ENV=production`, `TEST_TIMEOUT=30000`, `TEST_RETRIES=2`, `PARALLEL_WORKERS=4`, `HEADLESS=true`, `CAPTCHA_ENABLED=true`, `RATE_LIMIT_ENABLED=true`, `SECURITY_HEADERS_CHECK=true`, `CI=false`. `DB_PASSWORD` is set and omitted. No package in that folder loads the file. It is not the IPW `playwright_tests` database.

There are no migrations, ORM models, or seeders in this repository.

## Reporting and email

| Suite | Default report | Extra |
|---|---|---|
| BI | HTML, JSON, JUnit under `test-results/` | `npm run test:report` runs `playwright show-report`. A full historical report is already in git |
| ShopFlow | HTML, `test-results.json` | `npm run report` |
| IPW | HTML, JSON, JUnit from the TypeScript config | `npm run test:report`, `test:pdf` (Puppeteer prints `playwright-test-report.pdf`), `test:email` |

`scripts/send-email-report.js` uses nodemailer against `mail.appnotify.co.za` port 587, user `noreply@appnotify.co.za`, recipient `jaco@overdrive.co.za`. The password is hardcoded. The message body hardcodes an old scoreline (accessibility 100%, authentication 0%) rather than reading only the latest JSON. Checked-in artefacts: `playwright-test-report.html` and `playwright-test-report.pdf`.

`test-summary.json` timestamp `2024-12-04T21:11:00.000Z` records 93 tests, 20 passed, 73 failed, success rate 21.5, site accessibility passed, authentication failed ("Login form structure differs from expected patterns"), security not executed. Current spec files contain 68 `test()` calls. The JSON is not a description of `HEAD`.

## CI, quality, and deployment

Not present in git:

- `bitbucket-pipelines.yml` or any other CI workflow
- `sonar-project.properties`
- `sonarqube_scan.bat`
- Docker, Kubernetes, serverless, or a hosting config
- A root README

The onboarding issue's scan listing included the Sonar properties file and `sonarqube_scan.bat`. They are not in `bcee2c5`, `1973de1`, `15537a0`, or `41f992c`.

Configs still branch on `process.env.CI` (retries and workers). That is local behaviour if someone exports `CI`. It is not a pipeline.

Changelogs say "CI/CD ready". That claim is documented and not backed by a pipeline file.

Nothing in this repo deploys an environment. The suites call environments that already exist.

## Security findings in the test repository

These are properties of the test repo, not a pentest of the sites. Values are omitted on purpose.

| Location | What is committed |
|---|---|
| `qa.shopflow.io.dedi1534.jnb2.host-h.net/utils/test-config.ts` | Fallback test email and password |
| `qa.shopflow.io.dedi1534.jnb2.host-h.net/README.md` | The same email and password in the configuration section |
| `qa.shopflow.io.dedi1534.jnb2.host-h.net/utils/email-2fa-fetcher.ts` | IMAP TLS `rejectUnauthorized: false` |
| `staging.ipw.co.za/tests/login.spec.ts` and `CHANGELOG.md` | Username `jason@overdrive.co.za`, password `test` |
| `staging.ipw.co.za/README.md`, `playwright.config.js`, `scripts/global-setup.js`, `test-summary.json` | Username `daniel` and a password |
| `staging.ipw.co.za/scripts/send-email-report.js` | SMTP host, user, and password |
| `label.sawis.co.za/TEST_SPECIFICATION_TEMPLATE.md` | Prompt contains a staging login and the same SMTP password |
| `qa.d3t8evj08x1w1g.amplifyapp.com/TEST_SPECIFICATION_TEMPLATE.md` | Prompt contains an Amplify login and the same SMTP password |
| `sawisonline.co.za/.env` | Tracked env file with `DB_PASSWORD` |

Root `.gitignore` ignores `.env` and `auth.json`, and ignores `/playwright-report/` and `/test-results/` only at the repository root. Nested BI media is therefore tracked. A committed `.env` stays tracked until it is removed from the index.

`security.spec.js` sends attack-like strings at `http://staging.ipw.co.za` from a browser test. It is a Playwright spec. The in-repo summary says it was not executed.

**Requires confirmation:** rotate the mailbox, the database password, the ShopFlow test password, and the accounts named above, then remove them from git history. This documentation change does not do that. The source repository was not modified.

## How to run

From the suite directory, not the repository root.

```text
# SAWIS BI
npm install
npm run install:browsers
npm run test:quick

# ShopFlow
npm install
npx playwright install
# create .env from config.env.example — do not rely on the fallbacks in test-config.ts
npm test

# IPW
npm install
npx playwright install
npm test
```

ShopFlow phases 2–6 need `auth.json` on disk before that project starts. IPW `npm run test:email` sends mail with the committed SMTP settings. Do not run it until those settings are replaced.

## Development process actually in git

| Date | Commit | Change |
|---|---|---|
| 2025-08-19 | `bcee2c5` | `.gitignore` only |
| 2025-11-18 | `1973de1` | BI suite including report media, IPW suite, three template folders. 1611 files in the diff from the first commit |
| 2025-11-19 | `15537a0` | ShopFlow suite |
| 2025-11-24 | `41f992c` | ShopFlow login/logout specs, `authentication.ts`, one-line edits to README, `package.json`, and config |

No code review notes, hooks, or formatter config were found. No test of the helpers was found. Specs were not executed during this documentation pass.

## Monitoring and background work

None. No workers, cron, queues, or APM. The email script is a manual npm script. The Gmail fetch is inline during a login test, not a worker.

## Related source documents worth keeping

Do not replace these with this Silicon Ark set. They live in the source repo and disagree with the code in the places the PRD lists.

- `bi.sawisonline.co.za/README.md`, `SETUP_GUIDE.md`, `CHANGELOG.md`, `NewKnowledgeBase.md`
- `staging.ipw.co.za/README.md`, `CHANGELOG.md`, `COMPREHENSIVE_TEST_REPORT.md`, `NewKnowledgeBase.md`
- `qa.shopflow.io.dedi1534.jnb2.host-h.net/README.md`, `PROJECT_PATTERNS_AND_RULES.md`, `DATATABLE_NAVIGATION_FIX.md`
