Skip to content

test(e2e): add comprehensive Playwright E2E tests for relationship field#35099

Merged
oidacra merged 20 commits intomainfrom
issue-35022-relationship-fields-show-empty-values-and-fail-to
Mar 25, 2026
Merged

test(e2e): add comprehensive Playwright E2E tests for relationship field#35099
oidacra merged 20 commits intomainfrom
issue-35022-relationship-fields-show-empty-values-and-fail-to

Conversation

@oidacra
Copy link
Member

@oidacra oidacra commented Mar 24, 2026

Summary

Adds a full Playwright E2E test suite for the relationship field in the new Edit Content mode, covering all 4 cardinalities (1:1, 1:M, M:1, M:M), content selection, inline creation, search/filter, drag & drop reorder, and custom columns. Also fixes a circular dependency and signalMethod warning in the relationship field component.

Changes Made

Frontend (Angular)

  • Circular dependency fix: Lazy-load DotEditContentDialogComponent via dynamic import to resolve NG0919 (dot-relationship-field.component.ts:271)
  • signalMethod fix: Changed this.initialize(this.$inputs) to this.initialize(this.$inputs()) (dot-relationship-field.component.ts:191)
  • Dialog closable: Added closable: true to Create New content dialog config
  • Form bridge stack: Added pushFormBridge()/popFormBridge() to AngularFormBridge so nested dialogs preserve outer form state (angular-form-bridge.ts:116-148)
  • data-testid attributes: Added relationship-add-button, relationship-delete-button, relationship-drag-handle, relationship-table-pagination, relationship-language-filter

E2E Tests (Playwright)

  • 4 spec files covering relationship field journeys:
    • relationship-field-select.spec.ts — Select existing (single/multiple), create new inline, dialog dismissal
    • relationship-field-edit.spec.ts — Load, add, remove relations, persistence
    • relationship-field-table.spec.ts — Drag & drop reorder, search/filter, pagination
    • relationship-field-advanced.spec.ts — Multiple fields coexistence, custom columns (showFields)
  • Locator helpers in tests/edit-content/fields/relationship-field/helpers/
  • Fixture with API helpers for content type creation, contentlet CRUD, relationship setup
  • Auth setup project — Single login via storageState, shared across all workers

Infrastructure & Conventions

  • CLAUDE.md — Comprehensive E2E testing guide with selectors, patterns, gotchas
  • auth.setup.ts — Playwright setup project for shared authentication
  • utils/portlets.ts — Centralized portlet URL constants (Portlet.Content, Portlet.ContentTypes)
  • utils/iframe.tsgetLegacyFrame() helper for Dojo iframe access
  • utils/credentials.ts — Moved credentials from tests/login/ to shared utils
  • requests/field-variables.ts — API helper for creating field variables on content type fields
  • Login fix — Updated selectors to getByTestId('userNameInput') / getByTestId('password') with click → fill → Tab sequence

Technical Details

  • Tests create isolated content types via API in beforeEach and clean up in afterEach
  • Each test uses unique suffixes (timestamp) for parallel safety
  • Dojo iframe interactions use getLegacyFrame() + force: true on menu clicks (flicker workaround)
  • PrimeNG popover elements (search/clear buttons) render outside the dialog scope — use page not dialog locator
  • SystemWorkflow ID (d61a59e1-a49c-46f2-a929-db2b4bfa88b2) required for Save button to appear
  • Cardinality mapping: 0=ONE_TO_MANY, 1=MANY_TO_MANY, 2=ONE_TO_ONE, 3=MANY_TO_ONE (counterintuitive)

Known Issues (marked as test.fixme)

  • Table pagination bug — shows all items instead of paginating at expected page size
  • Apply button disabled state — <p-button> custom element requires .locator('button') for native disabled check
  • Thumbnail rendering — requires content type with image fields (test Author has text fields only)

Breaking Changes

None

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • E2E tests added/updated

Related Issues

Closes #35022

Additional Notes

  • The CLAUDE.md and dotcms-e2e skill were updated with all conventions discovered during implementation
  • The storageState auth pattern replaces per-test login, significantly reducing test execution time

This PR fixes: #35022

@github-actions github-actions bot added the Area : Frontend PR changes Angular/TypeScript frontend code label Mar 24, 2026
@claude
Copy link
Contributor

claude bot commented Mar 24, 2026

Claude finished @oidacra's task in 4m 6s —— View job


PR Review

  • Read key changed files
  • Review angular-form-bridge push/pop stack
  • Review fixture teardown
  • Review spec files for issues
  • Review helper files
  • Post findings

Issues Found

1. destroy() corrupts ref count across push/pop stackangular-form-bridge.ts:271

destroy() always decrements the static AngularFormBridge.refCount. But after pushInstance(), refCount belongs to the nested (dialog) context. If any parent bridge consumer calls destroy() while the dialog is open (e.g. an outer NativeFieldComponent unmounts), it will decrement the dialog's ref count instead of the parent's, potentially triggering forceDestroy() on the wrong instance. The same problem exists in reverse after popInstance() if the dialog's cleanup fires late.

The guard at line 277 (if (AngularFormBridge.instance === this)) only prevents orphaned null assignment but does not prevent the wrong ref count from being decremented.

Fix this →

2. No test cleanup — content types accumulaterelationship.fixture.ts:374

The fixture's apiHelpers exposes createContentType and createContentlet but no deleteContentType. No spec file has an afterEach that deletes the created E2E_* content types. On any shared/long-lived instance, each test run permanently adds content types. The PR description says "clean up in afterEach" but this is not implemented.

Additionally, enableNewEditor permanently sets DOT_CONTENT_EDITOR2_CONTENT_TYPE and DOT_CONTENT_EDITOR2_ENABLED in the system table with no cleanup.

Fix this →

3. enableNewEditor is not parallel-saferelationship.fixture.ts:186

DOT_CONTENT_EDITOR2_CONTENT_TYPE is a single system table key. When multiple Playwright workers run different describe blocks concurrently, each beforeEach overwrites this key with its own content type variable. Worker A may set E2EBlogONE_TO_MANY_abc while Worker B immediately overwrites with E2EBlogEdit_xyz, causing Worker A's editor to never appear. All tests within a block are serial, but blocks across the 4 spec files run in parallel.

4. Serial mode comment is misleadingrelationship-field-select.spec.ts:19

Most describe blocks have:

// Serial: beforeEach shares mutable `let` vars across tests.

This is inaccurate. beforeEach runs before every test regardless of serial/parallel mode. The actual reason for serial mode is to avoid concurrent API calls to the same dotCMS instance while let vars are being reassigned. The comment should say something like:

// Serial: prevents concurrent beforeEach/afterEach API calls racing on the same instance.

A secondary risk: in serial mode, any test failure skips all subsequent tests in the block, which can hide failures.

5. onRowReorder silently ignores event datadot-relationship-field.component.ts:264

onRowReorder(event: TableRowReorderEvent) {
    const dragIndex = event?.dragIndex;
    const dropIndex = event?.dropIndex;
    if (this.$isDisabled() || dragIndex == null || dropIndex == null) {
        return;
    }
    this.store.setData(this.store.data());  // dragIndex/dropIndex unused
}

The variables are extracted, null-checked, then completely ignored. The comment explains that PrimeNG already mutates the array in-place, so the store just needs a snapshot. That's fine, but dragIndex/dropIndex being declared and unused will trip the linter (@typescript-eslint/no-unused-vars). Consider replacing the destructuring with just if (this.$isDisabled() || event?.dragIndex == null || event?.dropIndex == null).

6. DotEditContentDialogComponent: pushFormBridge() not guarded against double-popdot-create-content-dialog.component.ts:84

pushFormBridge() is called in the constructor. popFormBridge() is called in ngOnDestroy. The onClose subscription (line 86) also calls #handleDialogClose, which does NOT call popFormBridge. However, if the component is destroyed without ngOnDestroy being called (e.g., forced Angular tree teardown during test cleanup), the stack would grow unbounded. This is a defensive concern, not a current bug, but worth noting given the singleton pattern.


Not bugs, just noted:

  • Copilot's blogTypeId unused-var comments: in the current code, it's blogTypeVariable (.variable property) that's used everywhere, not .id. The issue only arises if someone tries to destructure { id: blogTypeId } — this was flagged in older commits and appears to have been addressed.
  • testSuffix uses crypto.randomUUID().slice(0, 8) — safe; the first 8 chars of a UUID are always hex digits (the first hyphen is at index 8).

@claude
Copy link
Contributor

claude bot commented Mar 24, 2026

Claude finished @oidacra's task in 1m 58s —— View job


Rollback Safety Analysis

  • Read rollback-unsafe categories reference
  • Get full PR diff (33 files, 9 commits)
  • Analyze diff against unsafe categories
  • Apply label: AI: Safe To Rollback

Result: ✅ Safe to Rollback

All 33 changed files are confined to two areas:

Area Files
E2E tests (Playwright) core-web/apps/dotcms-ui-e2e/**
Angular frontend core-web/libs/edit-content*/**

Category-by-category verdict:

Category Verdict
C-1 Structural DB model change ✅ None — no database touched
C-2 ES mapping change ✅ None — no ES code changed
C-3 Content JSON model version bump ✅ None — no ImmutableContentlet changes
C-4 DROP TABLE / DROP COLUMN ✅ None
H-1 One-way data migration ✅ None
H-2 RENAME TABLE / COLUMN ✅ None
H-3 PK restructuring ✅ None
H-4 New unrecognized field type ✅ None
H-5 Storage provider change ✅ None
H-6 DROP PROCEDURE / FUNCTION ✅ None
H-7 NOT NULL column without default ✅ None
M-1 Non-broadening column type change ✅ None
M-2 Push publishing bundle format ✅ None
M-3 REST / GraphQL contract change ✅ None — no REST endpoints modified
M-4 OSGi public interface change ✅ None

The frontend changes (circular dependency fix, signalMethod correction, pushFormBridge/popFormBridge additions, data-testid attributes) are pure UI-layer modifications with no effect on the backend, data storage, or API contracts. Rolling back to N-1 leaves all data, schema, and API surfaces intact.

@oidacra oidacra requested review from hmoreras and nicobytes March 24, 2026 14:28
@oidacra oidacra marked this pull request as ready for review March 24, 2026 16:41
oidacra added 11 commits March 24, 2026 13:01
…ependency in new edit mode

- Fix signalMethod warning by passing value instead of signal in ngOnInit
- Break circular dependency (NG0919) by lazy-loading DotEditContentDialogComponent
- Add closable: true to new content dialog config
- Add push/pop stack to AngularFormBridge for nested form contexts (dialogs)

Closes #35022
…lationship fields

- Introduced new fixture for relationship tests, including content type and contentlet definitions.
- Implemented API helpers for creating, deleting, and managing content types and contentlets.
- Added multiple test cases covering various scenarios for relationship fields, including creation, editing, and validation of relationships.
- Enhanced existing page objects to support new functionalities related to relationship management.

This update aims to improve the testing framework for relationship fields, ensuring robust coverage and reliability in the new edit content experience.
…pport

- Added a constant for the standard SystemWorkflow ID across dotCMS instances.
- Updated , , and  functions to accept an optional  parameter, allowing for dynamic workflow assignment.
- Modified API helpers to utilize the new workflow ID parameter when creating content types.
- Improved login page interaction by adding a tab press after filling the username input.

This update enhances the flexibility of content type creation and improves user interaction in the login process.
…tionship tests

- Added error handling for failed content type creation in , logging detailed error messages.
- Updated locator strategies in  to use more robust selectors, enhancing stability during interactions.
- Refined test logic in  to ensure proper visibility checks and response handling when saving inline content.
- Adjusted helper methods in  to use role-based locators for better maintainability.

These changes aim to enhance the reliability and clarity of end-to-end tests for relationship fields and content creation workflows.
…tionship field tests

- Introduced a new E2E testing guide (CLAUDE.md) outlining project structure, commands, naming conventions, and best practices for Playwright tests.
- Updated relationship fixture to improve API helper signatures for better type safety and clarity.
- Enhanced the NewEditContentFormPage to ensure proper loading and interaction with Dojo iframe elements.
- Added multiple new test cases for relationship fields, covering scenarios such as multiple relationships, editing existing content, and verifying persistence.
- Implemented helper classes for better encapsulation of relationship field interactions.

These changes aim to improve the overall testing framework, ensuring robust coverage and reliability in the new edit content experience.
… in relationship tests

- Added error handling for failed API responses in fireContentletWithRelationship, logging detailed error messages for better debugging.
- Updated the save method in NewEditContentFormPage to use a more flexible locator for the primary action button, accommodating both Save and Publish actions.
- Refined relationship field tests to improve clarity and maintainability, including renaming test cases for better readability.

These changes aim to enhance the reliability and clarity of end-to-end tests for relationship fields and content creation workflows.
… improve readability

- Renamed test suites and cases for clarity, focusing on "Add More Relations" and "Remove Relations".
- Removed unnecessary comments and consolidated setup logic for better maintainability.
- Updated test descriptions to be more concise and consistent.
- Enhanced the use of helper classes for dialog interactions, improving code readability.

These changes aim to improve the organization and clarity of end-to-end tests for relationship fields, ensuring a more efficient testing process.
…functionality

- Introduced a new utility function `createFieldVariable` for creating field variables in content types, improving the flexibility of field management.
- Updated the `TestContentType` interface to include a `fields` property for better structure and data handling.
- Modified the relationship fixture to utilize the new field variable functionality, enhancing the test setup for relationship fields.
- Adjusted the relationship field tests to incorporate the new field variable logic, improving test coverage and reliability.

These changes aim to streamline the management of field variables in relationship tests, ensuring a more robust and flexible testing framework.
…al management

- Added a new `.gitignore` file to exclude authentication state files from version control.
- Introduced an `auth.setup.ts` file to handle admin authentication setup for Playwright tests, improving test efficiency by saving authentication state.
- Updated `playwright.config.ts` to include a new project for setup and adjusted the Chromium project to use the saved authentication state.
- Refactored credential imports across various request files to utilize a centralized `credentials.ts` file, enhancing maintainability and clarity.

These changes aim to improve the structure and efficiency of end-to-end tests by centralizing authentication logic and managing credentials more effectively.
…entication handling

- Modified `.gitignore` to exclude the `.auth` directory for better version control.
- Updated `playwright.config.ts` to use a dynamic path for the authentication state file, enhancing portability.
- Refactored `auth.setup.ts` to utilize centralized credential management, improving test setup efficiency.
- Adjusted relationship field tests to streamline cleanup logic and remove unnecessary reloads, enhancing test performance and reliability.

These changes aim to improve the structure and efficiency of end-to-end tests, particularly in the context of authentication and relationship field management.
- Reorganized imports in `relationship.fixture.ts` for better clarity and consistency.
- Simplified function definitions and error logging in various test files to enhance readability.
- Adjusted locator strategies in `newEditContentForm.page.ts` and other test files for improved maintainability.
- Enhanced HTML structure in `dot-relationship-field.component.html` for better formatting.

These changes aim to improve the overall structure and readability of the end-to-end tests, facilitating easier maintenance and understanding of the test framework.
@oidacra oidacra force-pushed the issue-35022-relationship-fields-show-empty-values-and-fail-to branch from 8a03100 to 4289b51 Compare March 24, 2026 17:02
oidacra added 6 commits March 24, 2026 15:28
…tor strategies

- Updated `auth.setup.ts` to include response status checks for better error handling during authentication.
- Modified `relationship.fixture.ts` to use `crypto.randomUUID()` for generating unique test suffixes, improving test reliability.
- Refined locator strategies in `relationship-field.ts` to utilize role-based selectors, enhancing maintainability and clarity.

These changes aim to improve the robustness and clarity of end-to-end tests, particularly in authentication and relationship field interactions.
rjvelazco
rjvelazco previously approved these changes Mar 25, 2026
@oidacra oidacra added this pull request to the merge queue Mar 25, 2026
nicobytes
nicobytes previously approved these changes Mar 25, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a Playwright E2E suite for the new Edit Content relationship field (covering key relationship workflows) and makes a few targeted frontend changes to support/unstick those flows (dialog behavior, circular dep, bridge nesting, and test selectors).

Changes:

  • Added Playwright E2E specs + helpers/fixtures for relationship field journeys (select/edit/table/advanced) and an auth storageState setup project.
  • Updated relationship field UI to add stable data-testid hooks and fixed a signals initialization warning + circular dependency (dynamic import).
  • Extended the edit-content form bridge to support nested dialog contexts via push/pop stack behavior.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 22 comments.

Show a summary per file
File Description
core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.html Adds data-testid hooks for error/empty states in the selection dialog.
core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/components/search/search.component.html Adds a data-testid hook for the dialog search query input.
core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/components/search/components/language-field/language-field.component.html Adds a data-testid hook for the language filter control.
core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-relationship-field/dot-relationship-field.component.ts Fixes signalMethod usage, documents row reorder semantics, and lazy-loads the create dialog component.
core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-relationship-field/dot-relationship-field.component.html Adds data-testid hooks for add/delete/drag/pagination/empty UI.
core-web/libs/edit-content/src/lib/components/dot-create-content-dialog/dot-create-content-dialog.component.ts Pushes/pops a form-bridge stack for nested dialogs and uses takeUntilDestroyed() for onClose subscription.
core-web/libs/edit-content-bridge/src/lib/factories/form-bridge.factory.ts Exposes pushFormBridge()/popFormBridge() utilities wrapping AngularFormBridge stack operations.
core-web/libs/edit-content-bridge/src/lib/bridges/angular-form-bridge.ts Implements singleton stacking (push/pop) to allow nested bridge contexts.
core-web/libs/edit-content-bridge/src/index.ts Re-exports the new bridge stack helpers.
core-web/apps/dotcms-ui-e2e/src/utils/portlets.ts Adds centralized portlet URL constants for navigation.
core-web/apps/dotcms-ui-e2e/src/utils/iframe.ts Adds getLegacyFrame() helper for the Dojo iframe.
core-web/apps/dotcms-ui-e2e/src/utils/credentials.ts Centralizes E2E credentials and allows env overrides.
core-web/apps/dotcms-ui-e2e/src/tests/login/login.spec.ts Switches login tests to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/relationship-field-table.spec.ts Adds table-focused relationship E2Es (reorder/search/filter/pagination), including known-issue fixmes.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/relationship-field-select.spec.ts Adds selection + inline-create E2Es across all cardinalities and dismissal behaviors.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/relationship-field-edit.spec.ts Adds edit-mode E2Es for load/add/remove/persistence flows.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/relationship-field-advanced.spec.ts Adds multi-field coexistence + showFields/custom columns E2Es.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/helpers/select-existing-content-dialog.ts Adds a dialog-scoped locator helper for selection dialog interactions.
core-web/apps/dotcms-ui-e2e/src/tests/edit-content/fields/relationship-field/helpers/relationship-field.ts Adds a relationship-field locator helper for table/menu/delete/drag/pagination.
core-web/apps/dotcms-ui-e2e/src/requests/workflowActions.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/updateFeatureFlag.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/templates.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/sites.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/schemas.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/pages.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/requests/field-variables.ts Adds API helper to create field variables (e.g., showFields).
core-web/apps/dotcms-ui-e2e/src/requests/contentlets.ts Adds API helpers for create/relate/delete contentlets via workflow endpoints.
core-web/apps/dotcms-ui-e2e/src/requests/contentType.ts Switches to shared credentials utility.
core-web/apps/dotcms-ui-e2e/src/pages/newEditContentForm.page.ts Adds navigation helpers through Dojo listing + improves save action handling.
core-web/apps/dotcms-ui-e2e/src/pages/login.page.ts Updates login selectors to data-testid and stabilizes interaction sequence.
core-web/apps/dotcms-ui-e2e/src/fixtures/relationship.fixture.ts Adds relationship test fixture providing API helpers + unique test suffix.
core-web/apps/dotcms-ui-e2e/src/auth.setup.ts Adds Playwright setup project to persist admin storageState.
core-web/apps/dotcms-ui-e2e/playwright.config.ts Adds setup/auth project wiring and increases global timeout.
core-web/apps/dotcms-ui-e2e/CLAUDE.md Adds E2E testing conventions and patterns documentation.
core-web/apps/dotcms-ui-e2e/.gitignore Ignores generated .auth/ storageState artifacts.

@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 25, 2026
@oidacra oidacra dismissed stale reviews from nicobytes and rjvelazco via 0ff6c2b March 25, 2026 20:32
@oidacra oidacra enabled auto-merge March 25, 2026 20:46
@oidacra oidacra added this pull request to the merge queue Mar 25, 2026
Merged via the queue into main with commit 5413347 Mar 25, 2026
47 checks passed
@oidacra oidacra deleted the issue-35022-relationship-fields-show-empty-values-and-fail-to branch March 25, 2026 22:31
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.

Relationship fields fail to save when editing Blog content in new edit content mode

4 participants