# Technical documentation — katalon_tests

Evidence date: 2026-10-11.

Source: `git@bitbucket.org:overdrive/katalon_tests.git`, `main` at `7fa8653` (2025-08-21, joshgatdew). Full history is seven commits from 2025-08-19. Secret values are omitted.

## What this repository is

A single Katalon Studio project. It does not build or serve ShopFlow. It drives a browser, and one case also sends HTTP requests, against a host stored in the default execution profile.

```text
katalon_tests/
├── .gitignore
└── ShopFlow/
    ├── ShopFlow.prj
    ├── README.md
    ├── TEST_COVERAGE.md
    ├── TAG_STRATEGY.md
    ├── DYNAMIC_TEST_SUITES.md
    ├── ADD_TO_CART_TEST_FIXES.md
    ├── build.gradle
    ├── console.properties
    ├── run_smoke_tests.sh
    ├── run_regression_tests.sh
    ├── Profiles/default.glbl
    ├── Test Cases/          24 .tc files in numbered module folders
    ├── Scripts/             matching Groovy, plus .groovy.backup copies
    ├── Test Suites/
    │   ├── suites/          dynamic smoke and regression
    │   └── main/            one suite collection
    ├── Object Repository/   528 .rs files
    ├── TestData/            csv, txt, jpg fixtures
    ├── Include/config/log.properties
    └── settings/internal/   Katalon execution and Chrome properties
```

There is no `Keywords/` directory, no `Drivers/` directory, no `Libs/` directory, no `bitbucket-pipelines.yml`, no `package.json`, and no database migration. `.gitignore` is a generic template (Node, Java, Python, logs, IDE). It does not ignore `*.backup`, Reports, or `Profiles`.

`ShopFlow.prj` `projectFileLocation` is the absolute path `/home/josh/work/katalon_tests/ShopFlow/ShopFlow.prj`. That path is the author's machine. Katalon may rewrite it on open.

## Platform

| Item | Value | Evidence |
|---|---|---|
| Tool | Katalon Studio, edition ENTERPRISE | `ShopFlow.prj` |
| Project version stamps | created 10.3.0, modified 10.3.0, migrated from 5.9.0 | `ShopFlow.prj` |
| Project type | `WEBUI` | `ShopFlow.prj` |
| Free licence flag | `false` | `ShopFlow.prj` |
| UUID | `8ded9462-6a1b-41c5-9b06-d03a3be0fbe5` | `ShopFlow.prj` |
| Page-load timeout on the project | `0` | `ShopFlow.prj` |
| Source folder declared | `Include/scripts/groovy` | `ShopFlow.prj`. That directory is not in the tree. Custom Groovy that exists is under `Scripts/` and `Include/config/` |
| Language of tests | Groovy | `Scripts/**/*.groovy` |
| Build helper | Gradle plugin `com.katalon.gradle-plugin` version `0.1.2` | `build.gradle` |
| Active Gradle dependencies | none | Rest-Assured, JsonPath, and JSON Schema lines are comments |
| Browser | Chrome | shell scripts, suite collection, Chrome properties |
| Default selector method | XPATH | `settings/internal/com.kms.katalon.execution.properties` |
| Video recording | disabled (`enable: false`). Recorder preference AVI, LOW, record on failure only | same properties file |

Chrome driver arguments (`settings/internal/com.kms.katalon.core.webui.chrome.properties`):

- `start-maximized`
- `ignore-certificate-errors`
- `disable-popup-blocking`
- `auth-server-whitelist` (no allow-list value is stored)

`Include/config/log.properties` only comments that `logging.level.com.kms` can be set to `TRACE`. No level is enabled.

`console.properties` sets `remoteWebDriverType=Selenium` and leaves remote URL, Kobiton, TestCloud, TestOps, qTest, and Azure DevOps fields empty. `testOps.enabled` is empty.

## Execution profile

File: `ShopFlow/Profiles/default.glbl`. It is the default profile.

| Variable | Type | Committed initial value | Protected |
|---|---|---|---|
| `username` | STRING | a Gmail address (not repeated here) | no |
| `password` | STRING | empty | yes |
| `url` | STRING | `http://shopflow.io.dedi1534.jnb2.host-h.net` | no |
| `imap_host` | STRING | `imap.gmail.com` | no |
| `imap_user` | STRING | same Gmail address as `username` | no |
| `imap_pass` | STRING | empty | yes |
| `imap_port` | STRING | `993` | no |
| `LoginDate` | STRING | empty | no |
| `regressionTestPassCount`, `FailCount`, `SkipCount` | NUMBER | `0` | no |
| `smokeTestPassCount`, `FailCount`, `SkipCount` | NUMBER | `0` | no |

Protected empty strings mean Katalon is expected to supply those values outside the XML, or the run has no password. No second profile (QA, staging, production) exists. `TAG_STRATEGY.md` environment tags are unused.

The hostname is an xneelo-style dedicated-server name (`dedi1534.jnb2.host-h.net`). Scheme in the profile is `http`, not `https`. Chrome is configured to ignore certificate errors anyway.

Silicon Ark `playwright_tests` documents a ShopFlow Playwright suite aimed at `https://shopflow.php8` (override `SHOPFLOW_URL`) inside a directory named `qa.shopflow.io.dedi1534.jnb2.host-h.net`. That is a different repository and a different URL. Do not treat the two hosts as the same system without confirmation.

## How a run starts

`run_smoke_tests.sh` and `run_regression_tests.sh`:

1. Set `KATALON_PATH` to `/opt/katalon/katalon`.
2. Set `PROJECT_PATH` to `$(pwd)`. The operator must start the script inside `ShopFlow/`, because `-projectPath` is `.` and the suite paths are relative to the project.
3. Invoke the binary with `-noSplash -runMode=console -retry=1` (smoke) or `-retry=2` (regression), `-browserType=Chrome`, `-executionProfile=default`, and `-apiKey=your-api-key-here`.

The scripts do not export `JAVA_HOME`, do not install Chrome, and do not check the exit code. They are Bash. There is no PowerShell or `.bat` equivalent in this revision. The onboarding snapshot mentioned `sonarqube_scan.bat`; it is not in git.

`Test Suites/main/Tag_Based_Execution.ts` is a `TestSuiteCollectionEntity`, sequential, `maxConcurrentInstances` 4, one enabled configuration: Chrome, profile `default`, suite `Test Suites/suites/Regression_Tests_Dynamic`. Delay between instances is 0. Smoke is not in the collection.

## Suite lifecycle

Both dynamic suite Groovy files use Katalon annotations.

Smoke (`Smoke_Tests_Dynamic.groovy`):

- `@SetUp`: print, `WebUI.openBrowser('')`, `maximizeWindow`, set the three smoke counters to 0.
- `@SetupTestCase`: `WebUI.navigateToUrl(GlobalVariable.url)`.
- `@TearDownTestCase`: call `cleanupTestData()`, which only prints.
- `@TearDown`: print the three counters, `WebUI.closeBrowser()`.

Regression is the same pattern, plus `setupTestData()` / `cleanupTestData()` whose create and remove functions only print.

`Smoke_Tests_Auto_Discover.groovy` repeats the smoke lifecycle and is not paired with a `.ts` file. The shell scripts do not name it.

Filter entities:

| File | `filteringBuiltIn` | `filteringText` | `numberOfRerun` | `pageLoadTimeout` | `rerunImmediately` |
|---|---|---|---|---|---|
| `Smoke_Tests_Dynamic.ts` | `com.kms.katalon.execution.platform.DynamicBuiltInSearch` | `tag=(P1)` then `tag=(SMOKE)` | 1 | 30 | true |
| `Regression_Tests_Dynamic.ts` | same class | `tag=(REGRESSION)` | 2 | 60 | true |

`isRerun` is false on both. `mailRecipient` is empty. `rerunFailedTestCasesOnly` is false, so a rerun is not limited to failed cases.

Tags that Katalon filters are the `<tag>` element of the `.tc` XML. Comments inside the Groovy files are not tags. Two header comments disagree with their `.tc` files (`Add_To_Cart` says `CORE`; `API_Integration` says `P1`).

## Authentication implementation

`Scripts/01_Authentication/Login/Script1755182083031.groovy`:

- Opens its own browser even when suite setup already opened one.
- Locators are under `Object Repository/Page_Login  Transactflow/` (two spaces before `Transactflow`).
- Email object `input_LOGIN_inputEmail`: XPath `//input[@id='inputEmail']`, CSS `#inputEmail`, selector method XPATH, smart locator disabled. Placeholder recorded on the element is "Enter your email".
- Writes `GlobalVariable.LoginDate` in `yyyy/MM/dd HH:mm:ss` before the click.
- 2FA field and submit button live under `Page_Transactflow`, not under the login folder. The object names include a generated suffix (`inpu_99772f`, `ver_bfc570`).

`Scripts/01_Authentication/Read GMail 2fa Code/Script1755182083194.groovy`:

- JavaMail `Session` / `Store` protocol `imaps`.
- Properties force `TLSv1.2 TLSv1.3`, `ssl.trust` `*` (and also the host), `checkserveridentity` false, debug false.
- Folder `inbox`, `SubjectTerm("2FA Validation")`, `READ_ONLY`.
- Poll 30_000 ms, sleep 5_000 ms.
- Plain-text body, or the `text/plain` part of `multipart/alternative` and `multipart/mixed`. A raw-message fallback looks for `Content-Type: text/plain`.
- Returns the substring after `Your 2FA code is:`.
- On failure it prints the exception and falls off the end with no return value. Login treats an empty return as failure when the 2FA field was visible.
- The script prints the code it found.

`Invalid_Login` does not call `openBrowser`. It depends on a browser the suite already opened.

## UI automation

Scripts use `com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords`. Mobile, Windows, Cucumber, and TestNG keyword classes are imported in the standard Katalon header and are not called in the sections reviewed.

Object repository layout:

| Folder | Files | Origin of the name |
|---|---|---|
| `Page_Transactflow` | 456 | Browser title at record time contained Transactflow |
| `Page_AdminOverdrive` | 49 | Browser title contained AdminOverdrive. Object names include DataTables sorting classes |
| `Page_Login  Transactflow` | 11 | Login page title |
| `API` | 12 | Hand-written REST templates (`<objectType>RESTful</objectType>`), not WebElementEntity |

`ADD_TO_CART_TEST_FIXES.md` is the locator standard for the shop screen: `#productsTable`, `#cartsTable`, `input[type="text"][data-quantity]`, `button[onclick*='addProductToTable']`, column positions for price and name, `.dataTables_info`. It forbids styling-class selectors. `productsTable.rs` follows the id rule and sets selector method CSS, which overrides the project XPATH default for that object.

Many steps pass `FailureHandling.OPTIONAL` or catch exceptions and call `KeywordUtil.markFailed`. An optional failure does not abort the case. `WebUI.fail` is used for hard stops in Login and parts of Invalid_Login.

`Add_To_Cart` navigates to `GlobalVariable.url + '/shop'` and does not call the Login case. The script comment says login belongs to suite setup. Suite setup does not log in.

Route strings used by `navigateToUrl` are listed in `prd.md` WF-6. They are not declared in a shared map. Placeholder and the module scripts sometimes use different paths for the same area (`/pricefiles` versus `/pricefiles/list`, `/home` versus `/dashboard`).

## API objects

REST objects interpolate `${url}`, `${payload}`, and `${token}` from the `WS.sendRequest` argument map. Example: `OrganisationsLogin.rs` is POST, body `${payload}`, header `Content-Type: application/json`, timeout 30.

`Script1755182083040.groovy` builds URLs as `GlobalVariable.url + path`:

| Call | Method shape | Path |
|---|---|---|
| Organisations login | POST JSON | `/organisations/login` |
| List and create | GET, POST | `/organisations` |
| Read, update, delete | GET, PUT or as the object defines, DELETE | `/organisations/{id}` when an id was captured |
| Store | request object `GetStoreApi` | `/store-api` |
| Session | request object `GetSessionApi` | `/api-simulation` |
| Negative and load-style calls | various | `/organisations`, `/invalid-endpoint` |

The login payload in the script is a hard-coded example document, not the profile user. A 401 is marked failed. The `.tc` tags exclude this case from smoke and regression. Whether ShopFlow implements these paths is **Unknown / Requires Confirmation**. The segment `api-simulation` may mean a stub.

## Test data

`ShopFlow/TestData/` is not wired through Katalon Data Files (`findTestData` is imported and not called with a file id).

| File | Contents |
|---|---|
| `valid_price_file.csv` | Header `Product_ID,Product_Name,Category,Price,Currency,Effective_Date`. Five data rows, USD, date `2024-12-31` |
| `invalid_data_price_file.csv` | Same header. Negative price, text price, empty name, `invalid_date`, `INVALID_CURRENCY` |
| `invalid_file.txt` | Short prose saying the file should be rejected |
| `product_image.jpg` | Binary image. Not mentioned in `TEST_COVERAGE.md` |

`Price_File_Upload` looks at `uploadFileInput` and at a displayed name's extension (`csv`, `xlsx`, `xls`, `txt`). It does not pass these fixtures to `uploadFile`.

## Tag helper

`Scripts/Include/TagBasedExecution.groovy` defines class `TagBasedExecution`. `findTestCasesByTags` returns `[]` and the comment says to implement discovery later. Public runners `executeSmokeTests`, `executeCriticalTests`, `executeRegressionTests`, `executeAPITests`, and `executeUITests` therefore iterate nothing. `configureTestExecution` sets timeouts from tags on a `TestCaseContext` if something called it. No suite script calls that class.

The lower methods (`validateTagBasedExecution`, workflow, error handling, performance) assert properties of hard-coded lists such as `['P1','SMOKE']`. They do not read the test-case tree. `testTagBasedExecutionPerformance` sleeps 100 ms.

## Backups and generated names

Each script has a sibling `*.groovy.backup`. There are 25 backups, including one for `TagBasedExecution.groovy`. They are tracked. Katalon executes the `.groovy` file named from the test case, not the backup.

Script file names are Katalon timestamps, for example `Script1755182083035.groovy`. The folder path matches the test-case path except `Sales_Report_Generation.tc`, whose script folder is `ShopFlow_Reports_Generation` because the `.tc` `<name>` is `ShopFlow_Reports_Generation`.

## Security notes (suite, not the application)

- Gmail address stored in clear text in `default.glbl`. Passwords are protected and empty in git, which avoids committing them and also means a fresh clone cannot log in.
- 2FA script prints the verification code and disables IMAP certificate identity checks.
- API script contains an example password literal in the request body.
- Shell scripts contain the literal `your-api-key-here`.
- Chrome ignores certificate errors.
- Invalid_Login types SQL-shaped and XSS-shaped strings into the login form. That is test input against the system under test, not an exploit procedure stored for reuse. The strings are the usual textbook samples (`' OR '1'='1`, `<script>alert(...)`).

No application authorisation model, session store, or role table is in this repository.

## Data, jobs, storage, monitoring

| Area | Finding |
|---|---|
| Database | None. `TAG_STRATEGY.md` lists a `DATABASE` tag. No case uses it |
| Queues and workers | None |
| Object storage | `TEST_COVERAGE.md` lists AWS S3 as an external dependency. No S3 client, bucket, or upload call was found |
| Email | IMAP read of Gmail only. No SMTP send |
| Monitoring | TestOps fields empty. Suite mail recipient empty. Counters are not updated |
| CI | No pipeline file. `TEST_COVERAGE.md` lists CI as a future enhancement |
| SonarQube | Not in `7fa8653`. Discovery metadata for OVER-171 named `sonar-project.properties` and `sonarqube_scan.bat` |

## Development process visible in git

Author of all seven commits: joshgatdew `joshua@overdrive.co.za`. Dates 2025-08-19 to 2025-08-21. Messages are short ("Add initial shopflow tests", "Object fixes", "Fix Add to Cart tests"). No review trail is in the git data that was fetched. Branch model is a single `main`.

Local open path recorded in the project file is `/home/josh/work/katalon_tests/ShopFlow/`. The scan host path given to this onboarding task was `~/projects/sonar_scan/repos/katalon_tests`. Neither path was present on the machine that produced this document. The tree was read from a clone of `main` at `7fa8653`.

## Related documentation

| Document | Role |
|---|---|
| `ShopFlow/README.md` | Four lines. Profile location and an outdated Login path |
| `ShopFlow/TEST_COVERAGE.md` | Module catalogue and coverage percentages. Counts do not match the `.tc` files |
| `ShopFlow/TAG_STRATEGY.md` | Tag vocabulary and command examples for suites that are not in git |
| `ShopFlow/DYNAMIC_TEST_SUITES.md` | Explains the dynamic filter suites. Still mentions removed static suites |
| `ShopFlow/ADD_TO_CART_TEST_FIXES.md` | Locator policy after the August 2025 cart fixes. Paths use a `tests/ShopFlow/` prefix |
| Silicon Ark `playwright_tests/` | Separate Playwright coverage of a ShopFlow host. Different URL |

## Unknown / Requires Confirmation

1. Katalon Runtime path and licence on any machine that still runs these scripts.
2. Runtime values of `password` and `imap_pass`.
3. Whether `http://shopflow.io.dedi1534.jnb2.host-h.net` still responds, and whether it is the Playwright QA host or `https://shopflow.php8`.
4. Current browser title (Transactflow, ShopFlow, or Admin Overdrive).
5. Whether JavaMail is on the Katalon classpath without an extra jar. The script imports `javax.mail` and no `Libs/` jar is in git.
6. Whether the REST paths, especially `/api-simulation`, exist on the application.
7. Whether the sonar files from the 2026-09-28 directory listing should be added, or were never part of `main`.
