Demo Web App
A small, self-contained ERP-style web app shipped as an npm package, plus a ready-to-run TestCase against it — the fastest way to see the framework work end-to-end without writing a locator by hand.
← Back to overview · 🇩🇪 Deutsch · ← Writing Your First TestCase
What is the Demo Web App?
@meintest/cc-testframework-demo-web is a separate npm package containing a small, vanilla-HTML/CSS/JS “ERP” application — Customers, Products, Orders — with a login screen, a dashboard, list/detail/form views, confirmation dialogs, and toast notifications. It ships pre-built (dist/index.html + assets) and runs entirely client-side: all state lives in the browser’s localStorage, nothing is sent over the network, and there is no server component to start or configure.
It exists so that you have a realistic, deterministic app to point your first TestCase at — without needing access to your own application yet, and without writing a single XPath by hand. The framework ships a matching Controls/TestSteps preset and a complete example TestCase; you install the package, wire two lines of config, and run a passing end-to-end test in minutes.
💡 Not a product demo. This is a test target, not a sales showcase. Its purpose is to let you exercise the framework’s dynamic element lookup and Self-Healing against something concrete before you point either at your own application.
See where each how-to page shows up here
This walkthrough is the same scratch-to-green-test journey the rest of the docs describe — just pre-wired, so you can see every piece in place before building your own:
| How-to page | Where it shows up in this walkthrough |
|---|---|
| Add a New App | Step 2 below — pointing GlobalConfig.apps at the shipped dist/index.html |
| Add Controls | The shipped 1_Controls/* files the _ExampleWebApp preset ships pre-instantiated |
| Build TestSteps | The shipped 2_Steps/* files — TS_Main_Login, TS_Main_VerifyToast, and friends |
| Writing Your First TestCase | The Example TestCase below |
| Run and Debug | Running TC_ExampleWebApp_HappyPath.spec.ts and reading its output |
Why deliberately no id / data-testid attributes
Most tutorial demo apps ship with generous id="submit-button" / data-testid="customer-row-3" attributes, which makes writing locators trivial — but that’s not how most real applications look. Legacy web apps, third-party UIs, and anything not built with test automation in mind rarely expose stable test hooks. A framework that only looks convincing against an instrumented tutorial app doesn’t tell you much about how it performs against the app you actually need to test.
The Demo Web App is built the other way round: no id, no data-testid, no data-cy attributes anywhere (the one exception — an id used purely for native <label for="..."> association — is never usable as a test selector). Elements must be addressed the way a tester would have to approach a real, un-instrumented application:
- Visible text content (button labels, table cells)
- Semantic roles (
<button>,<table>,<form>,<nav>) - CSS classes, as a secondary signal
- Structural position (e.g. “the row whose first cell reads ‘Acme Corp’”)
Some screens go further on purpose — several identically-labelled “Edit”/”Delete”/”Confirm” buttons appear in every table row, so a bare label lookup is ambiguous until you add row context. This gives the framework’s dynamic locator resolution (see Concepts) and Self-Healing Locators something realistic to work against: element addresses that must be derived from structure and content, not read off a convenient attribute — and, if a locator ever needs healing after a markup change, an app shaped enough like a real one that the healed result generalizes.
// From the shipped Button Control — no id/data-testid in sight:
Core.xpath`.//button[normalize-space()='${label}']`
// Row-scoped variant, needed because the same label repeats per row:
Core.xpath`.//tr[.//td[normalize-space()='${rowContext}']]//button[normalize-space()='${label}']`
💡 English-only for now. The demo UI is currently English-only.
How to start it
1. Install the package
From inside pm/:
npm install --save-dev @meintest/cc-testframework-demo-web
The package contains only a pre-built dist/ folder (index.html, styles.css, app.js, and its modules) plus its README.md and LICENSE — no source, no build step required on your side.
2. Point GlobalConfig.apps at it
2_Apps/1_Global/GlobalConfig.ts (your project’s copy, scaffolded from the templates) ships a commented example for exactly this. Uncomment it, or add the equivalent entry yourself:
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const demoIndex = require.resolve('@meintest/cc-testframework-demo-web/dist/index.html');
export const apps = {
ExampleWebApp: {
type: 'Web',
tool: 'Playwright',
baseUrl: `file://${demoIndex}`,
},
} as const;
require.resolve(...) finds the installed package’s dist/index.html on disk; baseUrl then becomes a plain file:// URL. There is no HTTP server involved — the framework’s Core.defineExecutionStep navigates the browser straight to that local file, the same way it would navigate to any https:// URL.
💡 Zero-Server story. Nothing needs to listen on a port, and nothing needs to be started before your test run —
npm installinsidepm/is the only setup step. This also makes the Demo Web App a convenient CI smoke target: no service to spin up, no port to wait on.
3. Scaffold the _ExampleWebApp preset
The templates package ships a fully pre-instantiated App folder — Controls, TestSteps, and their .i18n.json catalogs — under the _ExampleWebApp preset, plus a ready-to-run TestCase. When scaffolding a new project, pick this preset alongside (or instead of) the generic _Skeleton; your project’s 2_Apps/1_Global/References.ts then re-exports it:
// 2_Apps/1_Global/References.ts
export * as ExampleWebApp from '../_ExampleWebApp/References';
With that in place, Project.ExampleWebApp.TS_Main_Login(...) and friends are ready to call from any TestCase — see Writing Your First TestCase for how a TestCase composes TestSteps into a flow in general.
Feature tour
| Screen | What you can do |
|---|---|
| Login | Sign in with admin / demo123; a wrong password shows an error toast, a correct one a success toast and redirects to the Dashboard |
| Dashboard | See customer/order/product counters and jump to any section via quick actions |
| Customers | Sortable, filterable list (15 seeded rows); create, edit, deactivate/reactivate a customer via a form |
| Products | Price-sortable list (10 seeded rows) |
| Orders | List with status badges (Draft/Confirmed/Shipped/Cancelled); create a new order with a searchable customer combobox and a live total; transition an order’s status (Confirm/Ship/Cancel) |
| Confirmation dialogs | Shown before destructive actions (e.g. deactivating a customer); confirm, cancel, close via Escape, or click the backdrop |
| Toast notifications | Success/Error/Warning toasts, top-right, auto-dismiss after 3 seconds or close manually |
| Reset Data | A button in the footer clears all local state and reloads the app back to its deterministic seed data — useful at the start or end of a test run for isolation |
All data lives in 15 seeded customers, 10 seeded products, and 20 seeded orders; the Reset Data button always returns to that same starting point, so a TestCase can run repeatedly without accumulating state.
The Example TestCase
The templates package ships 3_Cases/TC_ExampleWebApp_HappyPath.spec.ts — a complete, tester-readable happy-path flow: start the app, log in, create a customer, create and confirm an order for that customer, deactivate the customer through the confirmation dialog, reset the data, log out, close the app. Every step is a plain Project.ExampleWebApp.TS_*(...) call — no page.locator(...), no Playwright calls directly in the TestCase file.
// 3_Cases/TC_ExampleWebApp_HappyPath.spec.ts (excerpt)
await Project.Core.Step.numberedStepBlock(`Login as admin`, async () => {
await Project.ExampleWebApp.TS_Main_Login('', 'admin', 'demo123');
await Project.ExampleWebApp.TS_Main_VerifyToast('', 'Login successful', 'Success');
await Project.ExampleWebApp.TS_Main_VerifyCurrentUser('', 'admin');
});
Once the package is installed and the two config steps above are done, this TestCase runs against your scaffolded project without any further changes — see Writing Your First TestCase for the general shape a TestCase follows.
Where to go next
- Writing Your First TestCase — the naming and re-export conventions this preset follows
- Concepts — the three-layer architecture (Core / 2_Apps / 3_Cases) the
_ExampleWebApppreset is built on - Run and Debug — running
TC_ExampleWebApp_HappyPath.spec.tsand reading its output - Self-Healing Locators — set this up against the Demo Web App to see automatic locator repair in action
- Quickstart — the general install-and-first-test flow, if you haven’t gone through it yet
📧 Questions? Contact: jens.szelag@itsbusiness.ch
itsbusiness AG · Bern · Switzerland