Skip to content

test(e2e): migrate legacy Playwright tests to dotcms-ui-e2e (#32525)#35882

Draft
nicobytes wants to merge 6 commits into
mainfrom
32525-e2e-migrate-legacy-playwright-e2e-tests-to-dotcms-ui-e2e-nx-project
Draft

test(e2e): migrate legacy Playwright tests to dotcms-ui-e2e (#32525)#35882
nicobytes wants to merge 6 commits into
mainfrom
32525-e2e-migrate-legacy-playwright-e2e-tests-to-dotcms-ui-e2e-nx-project

Conversation

@nicobytes
Copy link
Copy Markdown
Member

Proposed Changes

  • Migrate active legacy Playwright E2E tests from e2e/dotcms-e2e-node/frontend/src/tests into core-web/apps/dotcms-ui-e2e, the Nx-managed Playwright project
  • Refactor all test preconditions from UI-driven flows to API-first setup (no unnecessary navigation)
  • Remove manual LoginPage.login() from every beforeEach — session is now injected via auth.setup.ts storageState

Tests migrated (active tests only; test.skip entries excluded):

Legacy file New location Key change
pages/create-page.spec.ts src/tests/pages/create-page.spec.ts No change needed — already API-first
pages/unpublish-page.spec.ts src/tests/pages/unpublish-page.spec.ts No change needed — already API-first
pages/archive-page.spec.ts src/tests/pages/archive-page.spec.ts No change needed — already API-first
newEditContent/fields/textField.spec.ts src/tests/edit-content/fields/text-field/text-field.spec.ts Content type creation moved from UI (ListingContentTypesPage) to API (createFakeContentType)
contentSearch/portletIntegrity.spec.ts src/tests/content-search/portlet-integrity.spec.ts Generic content seed moved from Dojo UI to API (createContentlet); new focused ContentListingHelper replaces the 422-line legacy ContentPage

New file added:

  • src/tests/content-search/helpers/content-listing.ts — focused Dojo portlet helper using getLegacyFrame; covers only the selectors needed for the 8 active portlet integrity tests; replaces fragile Dojo widget IDs with role/class selectors per project conventions

Checklist

  • Tests
  • Translations
  • Security Implications Contemplated (add notes if applicable)

Additional Info

  • Closes e2e: Migrate Legacy Playwright E2E Tests to dotcms-ui-e2e NX Project #32525
  • login and translations tests were already migrated and are not included here
  • destroy-page, siteOrFolderField, and all contentEditing tests remain skipped in the legacy project and are out of scope
  • The legacy e2e/dotcms-e2e-node tree is left intact (no deletions)
  • Pre-commit hook (lint-staged + Prettier) passed clean on all 6 new files

Screenshots

No UI changes — test infrastructure only.

Made with Cursor

Port active tests from e2e/dotcms-e2e-node to core-web/apps/dotcms-ui-e2e,
replacing UI-driven setup with API-first preconditions and removing manual
login (session injected via auth.setup.ts storageState).

- pages: create, unpublish, archive specs using createPage + actionsPageWorkflow
- edit-content/fields/text-field: content type created via createFakeContentType API
- content-search: focused Dojo helper (ContentListingHelper) + portlet integrity
  tests (views, add-content, bulk workflow actions, query modal, advanced filter);
  search-filter seeds a contentlet via createContentlet API

Co-authored-by: Cursor <cursoragent@cursor.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jun 1, 2026

Claude finished @nicobytes's task in 2m 14s —— View job


Code Review

  • Gather context
  • Read changed files
  • Read existing project conventions
  • Post review findings

Findings

1. Null-safety gap across three spec files (medium)

contentType and pageContentlet are typed T | null but accessed without null guards in the test bodies:

  • text-field.spec.ts:25contentType.variable (would throw "Cannot read properties of null" if beforeEach fails, masking the real error)
  • text-field.spec.ts:37contentType.id in afterEach is guarded, but contentType.variable in the test body is not
  • archive-page.spec.ts:28,35pageContentlet.inode and pageContentlet.title unguarded
  • unpublish-page.spec.ts:35pageContentlet.title unguarded

The if (pageContentlet) checks in afterEach are correct — the test bodies need the same treatment (use non-null assertion ! with a comment, or a test.fail() guard).

Fix this →


2. archive-page.spec.ts — cleanup can't succeed if the test fails early (medium)

// afterEach (line 28)
await actionsPageWorkflow(request, pageContentlet.inode, ['Destroy']);

Destroy requires the page to already be archived. If the UI archive action (the test body) fails before completing, the afterEach Destroy call will fail too, leaving an orphaned page. Compare create-page.spec.ts which defensively does ['Unpublish', 'Archive', 'Destroy']. archive-page.spec.ts should do the same.

Fix this →


3. unpublish-page.spec.ts afterEach — same fragility (low)

afterEach does ['Archive', 'Destroy']. If the test's UI unpublish fails, the page is still Published. Archive on a Published page may fail in dotCMS, leaving orphaned data. Safer: ['Unpublish', 'Archive', 'Destroy'].


4. portlet-integrity.spec.ts:81 — weak URL assertion (low)

expect(newTab.url()).toBeTruthy();

Passes for about:blank or any error URL. The test verifies the popup opens but not that it navigated to anything useful. At minimum: expect(newTab.url()).toContain('/api/') or toMatch(/api\/v1/).

Fix this →


5. Module-level let variables outside any describe block (low)

text-field.spec.ts:6, archive-page.spec.ts:6, unpublish-page.spec.ts:6 declare mutable state at module scope. Existing specs in this project scope them inside test.describe. Module-level state is fine while each file has a single test, but the convention divergence makes it fragile the moment a second test is added to these files.


6. portlet-integrity.spec.ts:34-35 — CSS selector in Angular frame (low)

listing.frame.locator('.hydrated > dot-contentlet-thumbnail > .hydrated')

listing.frame is the Dojo iframe (from getLegacyFrame), but .hydrated is a Stencil.js hydration marker on an Angular component — it's unlikely to appear inside the Dojo frame. This looks like the selector is meant for the main page, not the frame. AGENTS.md mandates CSS "only in Dojo iframe"; for the Angular shell, prefer getByTestId or getByRole. This test may be silently passing/failing for the wrong reason.


Overall: The API-first setup approach and storageState auth removal are solid improvements. The main risks are the cleanup-fragility in archive-page and the null-safety gaps — both are one-line fixes.

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

Labels

AI: Safe To Rollback Area : Frontend PR changes Angular/TypeScript frontend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

e2e: Migrate Legacy Playwright E2E Tests to dotcms-ui-e2e NX Project

1 participant