Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
dbd8494
feat: add diagnostics popup
fateeand Oct 7, 2026
04d6ab2
Merge branch 'main' into 1-create-an-embedded-developer-diagnostics-p…
fateeand Oct 7, 2026
b182407
maxChars fix
fateeand Oct 7, 2026
d8daed5
Merge branch 'main' into 1-create-an-embedded-developer-diagnostics-p…
fateeand Oct 8, 2026
ac98fe2
Merge remote-tracking branch 'origin/main' into 1-create-an-embedded-…
fateeand Nov 4, 2026
26ef61a
fix table and info circle issues
fateeand Nov 4, 2026
6d0f90e
rename
fateeand Nov 4, 2026
4ffe0e5
add transparency slider
fateeand Nov 4, 2026
dceee43
docking
fateeand Nov 4, 2026
490ae41
add vars
fateeand Nov 4, 2026
4648f58
polish
fateeand Nov 4, 2026
b4864ef
lab phases 1 and 2
fateeand Nov 4, 2026
2d7fdf0
web fragments
fateeand Nov 5, 2026
25ae140
smoke test
fateeand Nov 5, 2026
3a9b829
fixing issues
fateeand Nov 5, 2026
20e5c9c
Merge branch 'main' into 1-create-an-embedded-developer-diagnostics-p…
fateeand Nov 5, 2026
ffc4e09
more to prev
fateeand Nov 5, 2026
f18c576
add test
fateeand Nov 5, 2026
e7037bd
cover everything
fateeand Nov 5, 2026
4a3bd9e
address review round
fateeand Nov 5, 2026
f8cbf44
fix lockfile
fateeand Nov 5, 2026
1ff4bad
a11y and wording fixes
fateeand Nov 6, 2026
deb1e8a
adjusting layout for every dock position
fateeand Nov 6, 2026
425c460
inspector workflows
fateeand Nov 6, 2026
9ac462f
results beside the actions, folding header and nav, broker setup in S…
fateeand Nov 6, 2026
40b2194
fix tests
fateeand Nov 6, 2026
f786884
fix pw tests
fateeand Nov 6, 2026
ce40677
delete temp docs
fateeand Nov 9, 2026
4f23e58
fix: keep rows on update, Escape and focus inside, safe config defaults
fateeand Nov 9, 2026
ce92342
fix: inspector copy and focus, quiet pause notice; lab keeps startup …
fateeand Nov 9, 2026
ef368d5
fix: low review findings: inspector open and focus edge cases, lab li…
fateeand Nov 9, 2026
4382f22
test: isolated consumer smoke test, SSR sends made visible, no fixed …
fateeand Nov 9, 2026
87c3294
fix: warn once when RUM rejects errors, never edit the app's RUM config
fateeand Nov 10, 2026
4c643b5
fix: close the inspector's open lists on page scroll and keep the whe…
fateeand Nov 11, 2026
787819e
link the lab header sign-in state to the Identity page
fateeand Nov 11, 2026
ee844a5
add favicon for event inspector
fateeand Nov 11, 2026
39d6e77
update design
fateeand Nov 11, 2026
002fd59
update spacing
fateeand Nov 11, 2026
448e4cc
a dock menu in place of the dock buttons when the inspector is narrow
fateeand Nov 11, 2026
124a70a
convert header sign-in state to a status with a tooltip
fateeand Nov 12, 2026
69dbcfc
replace browser default outline with focus ring
fateeand Nov 12, 2026
ec43c08
fix z-index
fateeand Nov 12, 2026
423b829
close the dialog on esc from inside
fateeand Nov 12, 2026
5dd266c
make the embedded application look the same in an iframe and as a Web…
fateeand Nov 13, 2026
cdc84c4
update page desc
fateeand Nov 13, 2026
e4a3ffb
separate window reload behavior
fateeand Nov 13, 2026
7970148
feat(lab): control every library and Event Inspector setting, and the…
fateeand Nov 13, 2026
2b4c10f
editors for logger levels, inspector shortcuts and the redaction list…
fateeand Nov 13, 2026
831d29b
control the app identity
fateeand Nov 13, 2026
f471f82
take the URL-parameter wording out of the Settings page
fateeand Nov 13, 2026
0546dac
settings redesign
fateeand Nov 13, 2026
8c615c2
show modified and not-applied settings with Reset and Undo, and link …
fateeand Nov 13, 2026
410e26d
help text for every setting
fateeand Nov 13, 2026
8c028a4
reset every setting to the lab's defaults from the overview
fateeand Nov 13, 2026
3cf21e3
reloading the separate window reopens the inspector
fateeand Nov 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ module.exports = {
},
overrides: [
{
files: ['playwright/**/*.ts', 'playwright.config.ts'],
files: [
'playwright/**/*.ts',
'playwright.config.ts',
'projects/watchtower-lab/server/**/*.ts'
],
env: {
jest: false,
node: true
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,52 @@ jobs:

- name: Typecheck
run: npm run typecheck

e2e:
name: Playwright (Chromium, WebKit)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 22.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Install browsers
run: npx playwright install --with-deps chromium webkit

- name: Run the Watchtower Lab suite
run: npm run e2e

- name: Upload the report
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report
path: playwright-report/
retention-days: 14

smoke:
name: Consumer smoke test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 22.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Pack, install and build as a consumer
run: npm run smoke
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

# Node
/node_modules
/projects/watchtower-consumer-smoke/node_modules
npm-debug.log
yarn-error.log

Expand All @@ -30,6 +31,9 @@ yarn-error.log
.sass-cache/
/connect.lock
/coverage
/test-results
/playwright-report
/blob-report
/libpeerconnection.log
testem.log
/typings
Expand Down
83 changes: 83 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Claude Code Guidelines

## Core Principles

- **Do only what was asked.** Make no unrequested changes. Keep the
scope of every change limited to the task.
- **Prefer simplicity over complexity.** Choose the simplest solution
that correctly addresses the problem. If a fix would introduce
noticeable complexity, stop and explain the trade-off before
proceeding.
- **Find the root cause first.** Investigate and understand the
underlying cause before changing code. Avoid speculative fixes and
symptom-only workarounds.
- **Never hide failing tests.** Do not delete, skip, weaken, disable,
or otherwise suppress a failing test just to make the test suite
pass.
- **Establish behavior before refactoring.** Add or verify
characterization tests before refactoring so existing behavior is
protected. For bug fixes, first create a test that reproduces the
bug and fails for the expected reason.
- **Write useful comments.** Comments should explain intent,
rationale, constraints, or context that cannot be made clear by the
code itself. Do not write comments that merely restate what the code
does.
- **Be transparent about verification.** Clearly report what was
tested or otherwise verified, what passed or failed, and what was
not verified. Never imply that checks were run when they were not.
- **Keep refactoring separate from behavior changes.** Do not combine
structural cleanup with changes to application behavior. Keep
changes focused and make behavior changes explicit.

## Working Workflow

1. **Understand the request.** Identify the requested outcome and the
scope. Do not expand the task without asking.
2. **Inspect before editing.** Read the relevant code and tests, trace
the behavior, and identify the root cause.
3. **Plan the smallest viable change.** Prefer a focused fix over broad
redesigns, new abstractions, or unrelated cleanup.
4. **Protect existing behavior.** Before refactoring, establish the
relevant behavior with characterization tests. Before fixing a bug,
add a regression test that demonstrates it.
5. **Make the change.** Avoid unrelated formatting, renaming,
dependency changes, or file moves.
6. **Run relevant checks.** Execute the most relevant tests and checks
available. Do not alter tests merely to obtain a green result.
7. **Report accurately.** Summarize the change and list verification
results, including anything not run and any remaining uncertainty.

## When a Fix Adds Complexity

If the simplest correct fix appears to require a noticeable increase in
complexity:

- Stop before implementing the more complex approach.
- Explain why the complexity is necessary.
- Describe the main trade-offs and, where practical, a simpler
alternative.
- Ask for direction before proceeding.

## Testing Rules

- A bug fix should have a regression test that fails before the fix
and passes after it, whenever practical.
- A refactor should be protected by characterization tests that
capture the existing behavior.
- Preserve the intent and meaningful assertions of existing tests.
- If a test fails, investigate the failure; do not suppress it or
weaken its assertions to make the suite pass.
- Distinguish failures caused by the change from pre-existing or
environment-related failures.

## Final Response

At the end of the task, state:

- **Changed:** What was changed and why.
- **Verified:** Which tests, commands, or checks were actually run and
their results.
- **Not verified:** Relevant checks that were not run, could not be
run, or remain inconclusive.

Do not claim success beyond what the evidence supports.
176 changes: 161 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@ How it is designed: [projects/ngx-ui-watchtower/DESIGN.md](projects/ngx-ui-watch

```text
projects/ngx-ui-watchtower/
src/ main entry point — @absaoss-cps/ngx-ui-watchtower
rum/ secondary entry point — @absaoss-cps/ngx-ui-watchtower/rum
README.md usage guide, published to npm
DESIGN.md full design
package.json the published package's manifest
src/ main entry point — @absaoss-cps/ngx-ui-watchtower
rum/ secondary entry point — @absaoss-cps/ngx-ui-watchtower/rum
event-inspector/ secondary entry point — @absaoss-cps/ngx-ui-watchtower/event-inspector
README.md usage guide, published to npm
DESIGN.md full design
package.json the published package's manifest
projects/watchtower-lab/ the Watchtower Lab: a testing app, never published
server/ its server: mock backend, fragment gateway, SSR
projects/watchtower-lab-fragment/ the lab's embedded application: a second app it embeds
projects/watchtower-consumer-smoke/ a minimal app that installs the packed library
playwright/ the lab's end-to-end suite (Playwright)
```

## Getting started
Expand All @@ -41,16 +47,154 @@ The package is built to `dist/ngx-ui-watchtower`.

## Scripts

| Script | What it does |
| ----------------------- | ---------------------------------------------------- |
| `npm run build` | Builds the package (production, partial compilation) |
| `npm run watch` | Rebuilds on change (development) |
| `npm run test` | Runs the unit tests (Jest) |
| `npm run test:coverage` | Runs the unit tests with coverage, as CI does |
| `npm run typecheck` | Type-checks every library and spec tsconfig |
| `npm run lint` | ESLint, no warnings allowed |
| `npm run format` | Formats with Prettier |
| `npm run format:check` | Checks formatting without writing |
| Script | What it does |
| ----------------------- | ------------------------------------------------------ |
| `npm run build` | Builds the package (production, partial compilation) |
| `npm run watch` | Rebuilds on change (development) |
| `npm run test` | Runs the unit tests (Jest) |
| `npm run test:coverage` | Runs the unit tests with coverage, as CI does |
| `npm run typecheck` | Type-checks every library, spec and suite tsconfig |
| `npm run lint` | ESLint, no warnings allowed |
| `npm run format` | Formats with Prettier |
| `npm run format:check` | Checks formatting without writing |
| `npm run lab` | Starts the Watchtower Lab on http://localhost:4280 |
| `npm run lab:build` | Builds the lab's fragment and shell |
| `npm run e2e` | Builds the lab and runs the Playwright suite |
| `npm run e2e:ui` | Builds the lab, and opens the suite in Playwright's UI |
| `npm run smoke` | Packs the library and builds an app from the tarball |

## Watchtower Lab

A testing app for the library, built from its source, so a change shows up
on save. `npm run lab` starts it on http://localhost:4280. Its shell is
rendered on the server, then hydrated. Its server (`server/server.ts`, which
`ng serve` runs too) also has a mock backend, which stands in for everything
the library talks to: the real `aws-rum-web` runs against a mock RUM broker
and dataplane, fully offline, and logs go to a mock log backend.

One page per concern, in three groups. **Library**: **Scenarios**, **BI
events**, **Logging**, **Identity**, **Privacy** and **Lifecycle**, each with
a **Results** column beside its buttons — the page's own readout, and what
it sent, ticked once the mock backend has it. **Embedded apps**: **Iframe**
and **Web Fragment** (the same second app in a plain iframe, and
as a [Web Fragment](https://web-fragments.dev) through the server's gateway,
each forwarding through the shell over the tab's own channel). **Tools**:
**Event Inspector** (every dock, showing the one it is in, event generators,
and the `--uwt-inspector-inset-*` opt-in on the lab's fixed header and status
bar) and **On the wire**: what the mock backend actually received.

**Settings**, at the foot of the nav, sets up the run every page shares: a
page per section, listed beside it by area, each saying how it applies.
**Library**: App identity, Delivery, Scenarios, BI events, Logging, Privacy &
redaction and Event Inspector. **Mock backend**: RUM broker and App monitor.
**Diagnostics**: Debug flags, which apply at once. **Advanced**: Configuration
as JSON, and the Effective configuration. A change waits, from whichever
section, in a bar listing them all, until they are applied together with one
reload, or discarded. A setting says what it does, from the library's
documentation (and aws-rum-web's, for the app monitor), and where it stands:
**Not applied**, with Undo, or **Modified** from the lab's default, with the
default and a Reset that waits to be applied too (a debug flag resets at
once); the list counts each section's modified settings. The **Overview**
lists both, to undo or reset each, or to reset all of them at once.
**Find a setting**, or `/`, finds one by its name, its name in the JSON or
what it does, and shows it in its section. On a narrow screen the sections
fold into a picker.

The header's chips show how this load runs, each a link to its setting;
where the broker is set differently for the next one, its chip says so:
`broker: ok → null after reload`. On a narrow screen, or beside a docked
pane, the chips fold behind **Run settings**, and the page list behind
**Pages**.
The header's **Signed in** or **Signed out** only shows the state:
**Identity** and the fragments both sign in and out.

Options, read once at startup like an app's configuration, and kept in the
address from the start page and through the page links, so a reload keeps
them too:

| Query | Effect |
| ----------------------- | --------------------------------------------------------------------------------------------- |
| `?destination=noop` | The noop destination instead of RUM |
| `?destination=custom` | The lab's own sink, through `provideUwtTelemetryDestination` |
| `?telemetry=off` | Telemetry off, through `withTelemetryEnabled`'s factory form |
| `?channel=shared` | The shell on the default broadcast channel, shared by every tab: their hosts elect one leader |
| `?inspector=off` | The Event Inspector disabled |
| `?inspector=noshortcut` | The Event Inspector without its shortcut |
| `?config=<JSON>` | Library settings laid over the lab's own |

`?config=` takes `identity` (`eventNamespace`), `scenarios`, `logging`, `bi`,
`redaction` and `inspector`, each as its `with…` function or
`provideUwtEventInspector` takes it, in JSON: a pattern is a `RegExp` source,
and the one value transform is `mask-order-ids`. One more, `lab`, is the
lab's own: `{ "logBatching": true }` makes its log provider batch, and send
when the library flushes it. For example
`?config={"scenarios":{"emitLifecycleEvents":true}}`. **Settings** edits it,
with a control for each setting — switches, numbers, lists to pick from, lists
of patterns, and editors for logger levels and the inspector's shortcuts — and
the JSON itself, and refuses a section, setting or type the library doesn't
have.

The mock RUM broker's answer is set in **Settings** too, under **RUM
broker**:

| Mode | The broker |
| --------------------------- | ------------------------------------------------------------ |
| `ok` | Answers normally |
| `null` | Turns RUM off for the page |
| `fail` | Errors; the app carries on |
| `short-expiry` | Gives credentials that are refreshed within seconds |
| `flaky` | Fails twice, then answers: the sink retries, then catches up |
| `invalid` | Sends a pattern as a string: the sink doesn't start RUM |
| `null-on-refresh` | Turns RUM off at the first refresh |
| `no-credentials-on-refresh` | Refreshes without credentials: the sink keeps the old ones |

It also sets RUM's own `telemetries` (the library's default, or any of
`errors`, `performance`, `interaction`, `http` and `replay`, down to none),
and, under **App monitor**, the broker's app monitor config: controls for the
settings most worth trying (`sessionSampleRate`, `sessionEventLimit`,
`dispatchInterval`, `allowCookies`, `enableXRay`, `disableAutoPageView`,
`recordResourceUrl` and the pages to include or exclude), and a JSON object
laid over it for the rest, such as `{ "sessionSampleRate": 0 }`.

### Automated tests

`npm run e2e` builds the lab and runs the suite in `playwright/` on Chromium
and WebKit, checking what the mock backend received against what each page
sends. It covers every control on every lab page: the whole scenario API and
`traceScenario`, BI events, logging and log queries, identity, redaction,
flushing, server rendering and hydration, both fragment pages, two tabs on
their own channels or one shared, a custom destination, every broker mode
and RUM's start-up and refresh, RUM's telemetries, the library's settings
through `?config=`, the debug flags, and the Event Inspector's docks,
shortcut, pause, kinds, search, filters, export, paging, resizing, links
between an error and its log event, and events kept from before opening —
and the lab's own frame: results beside the buttons, the header and nav
folding when narrow, and no page wider than a phone. It also runs axe-core's
WCAG 2.2 A and AA rules on every lab page and on the Event Inspector with its
Export menu and filter help open, measures the contrast of its coloured
text, and checks its states under forced colours. Internal edge cases —
timers longer than 24 days, giving up after five minutes, no Web Locks or
storage, message validation, start-up errors — are left to the unit tests.

It runs the built server on http://localhost:4390, beside `npm run lab`,
starting its own each time: one already on that port stops it, rather than
serving an older build. The first time, download the browsers with
`npx playwright install chromium webkit`.

## Consumer smoke test

Everything above uses the library from source. `npm run smoke` uses it as
published: it packs the built package, then sets up
`projects/watchtower-consumer-smoke` on its own, in a temporary folder
outside the workspace, with its own `package.json` (the workspace's
versions) and `angular.json`, and installs it with `npm install`, peer
checks and all. Nothing comes from the workspace, so a peer the package
leaves out or mis-ranges fails as it would for an app. It builds that app
for the browser and, prerendering, for the server, and checks the tarball's
files, that all three entry points resolve with their typings, that the page
renders on the server, and that an app which never imports `/rum` has no
`aws-rum-web` in its bundle. It needs the npm registry, and keeps the folder
when a check fails.

## Before you push

Expand All @@ -62,6 +206,8 @@ npm run typecheck
npm run lint
npm run format:check
npm run build
npm run e2e
npm run smoke
```

CI runs the same checks on every pull request and every push to `main`.
Expand Down
Loading