Skip to content

RI-8190 E2E coverage for prod vs non-prod modes#5984

Open
KrumTy wants to merge 6 commits into
mainfrom
claude/adoring-napier-45f3ac
Open

RI-8190 E2E coverage for prod vs non-prod modes#5984
KrumTy wants to merge 6 commits into
mainfrom
claude/adoring-napier-45f3ac

Conversation

@KrumTy
Copy link
Copy Markdown
Contributor

@KrumTy KrumTy commented May 29, 2026

What

Adds Playwright E2E coverage for prod vs non-prod modes. All scenarios run with dev-prodMode enabled via test.use({ featureFlags: ... }).

Specs are co-located with the feature area each scenario exercises:

  • databases/list/environment-badge.spec.ts — Production / Development / Unspecified DBs render the right badge (or no badge) in the list and the instance header.
  • browser/key-details/environment-gating.spec.ts — Browser writes on a Production DB open the modal (no typing needed); writes on a Development DB bypass it entirely (per-connection gating).
  • browser/bulk-actions/environment-gating.spec.ts — Bulk delete on a Production DB keeps the typed-input variant; mistyped name keeps Confirm disabled.
  • cli/dangerous-commands.spec.tsFLUSHDB on a Production DB opens the modal; cancel preserves keys, confirm runs (verified against the real Redis backend).
  • workbench/dangerous-commands.spec.ts — Workbench batch containing a dangerous command opens the modal mid-batch; same cancel/confirm contract.
  • workbench/profiler.spec.ts — Starting the Profiler on a Production DB requires a confirmation popover.
  • insights/tutorials.spec.ts — Tutorial Run buttons are disabled on a Production DB.

Modal copy, per-component wiring, and per-action confirmation strings are covered by unit tests and were deliberately not duplicated here.

Infrastructure

  • TypeToConfirmModal page object + fixture exposing both confirm() (input variant) and confirmWithoutInput() (Browser variant).
  • Environment enum in e2eSrc/types; optional environment flows through ApiHelper.createDatabase.
  • selectEnvironment() helper on AddDatabaseDialog; fillForm honours the new field.
  • DatabaseList.getRow switched from a cell-level locator to the inner name <p> so the environment badge in the same cell doesn't break the lookup.
  • TEST_PLAN entries distributed across sections 1.2, 2.4, 2.11, 3.1, 3.3, 3.4 and 4.1 (no dedicated section — coverage lives next to its peers).

Testing

  • CI: full Playwright run (@e2e-tests label).
  • Manual: yarn dev:api + yarn dev:ui, then cd tests/e2e-playwright && npx playwright test --project=chromium tests/main/browser/bulk-actions tests/main/browser/key-details tests/main/cli tests/main/workbench tests/main/insights/tutorials.spec.ts tests/main/databases/list/environment-badge.spec.ts against the docker-compose RTE.

Note

Low Risk
Changes are limited to E2E tests, page objects, and test plan updates; no production application logic is modified in this diff.

Overview
Adds Playwright E2E coverage for prod vs non-prod behavior when dev-prodMode is on, with specs placed next to each feature area (database list badges, Browser writes/bulk delete, CLI/Workbench dangerous commands, profiler start, tutorial Run).

Test harness: new TypeToConfirmModal page object and fixture; Environment on test types and ApiHelper.createDatabase; AddDatabaseDialog.selectEnvironment; DatabaseList.getRow matches the name <p> so PROD/DEV badges do not break row lookup. TEST_PLAN marks the new scenarios as implemented.

Reviewed by Cursor Bugbot for commit 8cb8d1a. Bugbot is set up for automated code reviews on this repo. Configure here.

Add Playwright E2E coverage for the per-database environment classification
(Production / Development / Unspecified) and the type-to-confirm modal flow,
all gated on the dev-prodMode feature flag.

Specs under tests/e2e-playwright/tests/main/databases/environment/ cover:
- PROD badge / DEV label rendering in DB list + instance header
- Browser write confirmations (no-input variant per RI-8201)
- Bulk delete (still requires typing the DB name)
- CLI FLUSHDB and Workbench dangerous batches (new title + ACL tip)
- Profiler confirmation popover + always-on advisory
- Tutorial Run button disabled on Production

Infrastructure: new TypeToConfirmModal page object + fixture, Environment
enum in e2e types, optional environment in createDatabase API helper,
selectEnvironment helper on AddDatabaseDialog. TEST_PLAN.md updated with
section 1.9.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@KrumTy KrumTy added the AI-Made label May 29, 2026
@jit-ci
Copy link
Copy Markdown

jit-ci Bot commented May 29, 2026

🛡️ Jit Security Scan Results

CRITICAL HIGH MEDIUM

✅ No security findings were detected in this PR


Security scan by Jit

The pre-commit hook is misconfigured for worktree commits (it runs
lint-staged against the main checkout's tests/e2e-playwright via
core.hooksPath), so prettier didn't normalize these files locally
and CI's format:check rejected them.

No behavioural changes — pure whitespace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The PROD/DEV badge introduced by RI-8181 is rendered inside the same
`td:nth-child(2)` cell as the database alias, so the cell's full text
becomes "PROD <alias>" (or "DEV <alias>"). The previous getRow regex was
anchored at start and end of the cell text — once a badge appeared the
filter no longer matched, and tests that exercised expectDatabaseVisible
on a Production/Development DB timed out.

Switch the locator from `td:nth-child(2)` (cell-level text) to
`td:nth-child(2) p` (the database-alias paragraph) so the anchored
regex applies only to the name paragraph, regardless of any sibling
badge paragraph in the same cell.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

constructor(page: Page) {
this.page = page;
this.title = page.getByTestId('type-to-confirm-modal-title');
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a generic, reusable modal, that's used with various props based on case; hence it's easier to manage it via test ids in e2e

…PLAN entries

Reshape per review feedback:

* Replace dedicated "1.9 Environment Modes" section in TEST_PLAN with
  entries distributed across existing feature sections (1.2 Database
  List, 2.4 Key Details - String, 2.11 Bulk Actions, 3.1 Command
  Execution, 3.3 Tutorials, 3.4 Profiler, 4.1 CLI Panel).
* Use `test.describe('Production DB' | 'Development DB' | 'Unspecified DB')`
  groups; tests start with `should ...` and don't repeat the environment
  in the test name.
* Consolidate 14 -> 9 tests, dropping coverage already exercised by unit
  tests: per-key-type Browser write variants (TTL, hash) since the
  rename test already proves the provider+modal+useProductionWriteConfirmation
  wiring; modal copy assertions (title, ACL tip) which live in the
  modal's own spec; "mistyped name keeps Confirm disabled" since that's
  modal-internal logic; Unspecified-only variants of Profiler/Tutorials
  which are just the default no-op path.
* Split profiler-tutorials.spec.ts into profiler.spec.ts and
  tutorials.spec.ts so each spec aligns 1:1 with its TEST_PLAN section.
* Strip ticket-id references from comments, test names, page-object
  docstrings, and TEST_PLAN rows.
* Simplify AddDatabaseDialog.selectEnvironment to derive the option
  label directly from the Environment enum value.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… areas

Move each spec out of tests/main/databases/environment/ and into the
folder of the feature it exercises, matching the new TEST_PLAN
distribution:

  databases/list/environment-badge.spec.ts          (was connection-form)
  browser/key-details/environment-gating.spec.ts    (was browser-confirmations)
  browser/bulk-actions/environment-gating.spec.ts   (was bulk-delete)
  cli/dangerous-commands.spec.ts                     (was cli-dangerous)
  workbench/dangerous-commands.spec.ts               (was workbench-dangerous)
  workbench/profiler.spec.ts                         (was profiler)
  insights/tutorials.spec.ts                         (was tutorials)

Pure file moves; no content changes. Removes the now-empty environment/
directory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@KrumTy KrumTy marked this pull request as ready for review May 29, 2026 10:58
@KrumTy KrumTy requested a review from a team as a code owner May 29, 2026 10:58
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a0e8be7. Configure here.

Comment thread tests/e2e-playwright/pages/components/TypeToConfirmModal.ts
…ped DB name

Address PR feedback: exercise the newly-defined
`TypeToConfirmModal.expectConfirmDisabledWhen` helper inside the
bulk-delete spec, where the typed-input variant of the modal lives. The
extra assertion proves the integration end-to-end (form value → modal
state → Confirm button enable/disable), complementing the unit-test
coverage on the modal in isolation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| 🔲 | main | Confirm deletion failures surfaced in summary log |
| 🔲 | main | Confirm performance when deleting thousands of keys |
| 🔲 | main | Confirm performance when bulk uploading large datasets (>10K keys) |
| ✅ | main | Production DB > should require typing the database name to bulk-delete |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: Make sure to run this test in an isolated database instance, so it doesn’t conflict with other tests that depend on the same data, which will be deleted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

database = await apiHelper.createDatabase(StandaloneConfigFactory.build({ environment: Environment.Production }));
for (let i = 0; i < 5; i++) {
await apiHelper.createStringKey(database.id, `${keyPrefix}${i}`, `value-${i}`);

it creates keys with a keyPrefix, then bulk deletes only them

lets see if this ever collides with another test first?

If we have a test that deliberately wants to read/mutate all data in the database and does not want to rely on predixes, then maybe we can spin an instance for this test alone

await browserPage.goto(database.id);
await browserPage.openProfiler();

await page.getByTestId('start-monitor').click();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think you can hide this inside a page object for the Profiler component

example: tests/e2e-playwright/pages/browser/components/AddKeyDialog.ts

await browserPage.goto(database.id);
await browserPage.openProfiler();

await page.getByTestId('start-monitor').click();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is there a way to use a better visual selector, instead of the IDs

await page.getByTestId('start-monitor').click();
await expect(page.getByTestId('profiler-start-confirm')).toBeVisible();
await expect(page.getByTestId('profiler-start-cancel')).toBeVisible();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Can we verify visually that the profiler is running and outputting stuff, to make these e2e test meaningful? Otherwise, the same check can be performed via a simple jest test, for much less cost.

| 🔲 | main | History limited to 30 commands (oldest replaced by newest) |
| 🔲 | main | Quick-access to command history with Up Arrow |
| 🔲 | main | Use Non-Redis Editor with Shift+Space |
| ✅ | main | Production DB > should require type-to-confirm modal for dangerous workbench batches |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: same as https://github.com/redis/RedisInsight/pull/5984/changes#r3324636891, since the test contains FLUSHALL in the list of dangerous commands we execute.

await apiHelper.deleteDatabase(database.id).catch(() => {});
});

test('should disable the tutorial Run button', async ({ browserPage, insightsPanel }) => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: update the test title

should disable the tutorial Run button when database is flagged as Production

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's contained in the description above

test.describe('Production DB', () => {

Copy link
Copy Markdown
Member

@valkirilov valkirilov May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad 👍

Do we need this describe block then, since it's the only test case in the suite, but is 3 level deep already?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unlikely to add more here but I wanted to keep the test itself starting with "should" but also have a prefix in the logs in front that it's for prod environment

alternative is to push it to the end - "should disable the tutorial Run button for Production environment", which works too if this bothers you

this.title = page.getByTestId('type-to-confirm-modal-title');
this.description = page.getByTestId('type-to-confirm-modal-description');
this.input = page.getByTestId('type-to-confirm-modal-input');
this.confirmButton = page.getByTestId('type-to-confirm-modal-confirm-btn');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: Title and Description are dynamic, I get that. But for the static labels, I still think we can use real visual selectors, instead of their IDs.

Copy link
Copy Markdown
Contributor Author

@KrumTy KrumTy May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's all dynamic actually; some may use the default values but still..

I could drop the ids and rely on specific text but I thought this can be left for unit tests and we are testing functionality only here; eventually we can do visual/snapshots and check texts as well

either way, no hard preference for me; if you want I can switch to text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants