From automation
Complete guide to writing Playwright e2e tests for finstreet/boilerplate features. Covers form modules, card CRUD modules, inquiry process pages, happy path tests, fixtures, test data, and dataTestIds. Use this skill whenever adding, modifying, or debugging e2e tests, or when the user mentions e2e, end-to-end, playwright tests, or integration tests for features.
npx claudepluginhub joshuarweaver/cascade-code-languages-misc-1 --plugin finstreet-fe-claude-pluginsThis skill uses the workspace's default tool permissions.
This project uses a layered Playwright e2e test architecture with reusable page objects, form modules, card CRUD modules, and inquiry process pages. All tests use `data-testid` selectors and follow strict patterns.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
This project uses a layered Playwright e2e test architecture with reusable page objects, form modules, card CRUD modules, and inquiry process pages. All tests use data-testid selectors and follow strict patterns.
BaseHelper (clickByTestId, getLocatorByTestId, getTextByTestId, waitForSelectorByTestId)
│
BasePage (composes: form: FormInteractor, errors: ErrorHandler, navigation: NavigationHelper)
│
├── FormModule<T> ── abstract fillAndSubmitForm(data: T)
│ executeValidationAndSubmit(options)
│
├── CardCrudModule<T> ── abstract fillAndSubmitForm(data: T) + verifyCardExists(data: T)
│ executeCrudCycle(options)
│
└── InquiryPage (BasePage) ── composes step modules per product
completeFullInquiryProcess / fillAllStepsWithoutFinalSubmit
e2e/
├── config/ # Step configs for inquiry processes
├── data/
│ ├── dataTestIds.ts # Centralized data-testid constants
│ ├── common/ # Shared test data
│ └── {product}/ # Product-specific test data
│ └── {feature}TestData.ts
├── fixtures/
│ └── fixtures.ts # Playwright fixture registration
├── files/ # File upload resources
├── helpers/
│ ├── core/
│ │ ├── BaseHelper.ts # Base class: data-testid interactions
│ │ ├── FormInteractor.ts # fillField for all 12 field types
│ │ ├── NavigationHelper.ts # goto, waitForUrl, clickBackButton
│ │ └── ErrorHandler.ts # getFieldError, getFormError
│ ├── components/
│ │ ├── CardHelper.ts # Card CRUD: getCard, clickUpdateCard, deleteCard
│ │ └── InteractiveListHelper.ts # List: waitForListToLoad, clickFirstListItem
│ └── utilities/
│ ├── InvitationHelper.ts # Email invitation workflows
│ └── MailtrapHelper.ts # Email testing via Mailtrap API
├── modules/
│ ├── FormModule.ts # Abstract form validation+submit cycle
│ ├── CardCrudModule.ts # Abstract card CRUD cycle
│ ├── LegalRepresentativesModule.ts # Reusable card CRUD (shared across products)
│ ├── common/ # Shared modules (documents, property manager steps)
│ └── {product}/ # Product-specific modules
│ ├── {Feature}Module.ts # FormModule or CardCrudModule subclass
│ └── inquiryProcess/ # Inquiry step modules
│ └── {Step}StepModule.ts
├── pages/
│ ├── BasePage.ts # Composes FormInteractor + ErrorHandler + NavigationHelper
│ ├── InquiryPage.ts # Generic inquiry flow orchestration
│ ├── auth/
│ │ ├── LoginPage.ts # Portal-specific login methods
│ │ └── AcceptInvitationPage.ts
│ └── {product}/
│ ├── {Product}InquiryPage.ts # InquiryPage subclass
│ ├── PM{Product}FinancingCaseOverviewPage.ts # PM overview with modules
│ └── FSP{Product}FinancingCaseOverviewPage.ts # FSP overview with modules
├── tests/
│ └── {product}/
│ ├── {product}HappyPath.spec.ts
│ ├── {product}InquiryProcess.spec.ts
│ ├── {product}InquiryProcessNavigation.spec.ts
│ └── {product}InquiryProcessBanner.spec.ts
└── utils/
├── portalRoutes.ts # Portal-aware route resolvers
└── test-helpers.ts # testCredentials, clearAuthState
When adding e2e tests for a new feature, follow this order:
e2e/data/dataTestIds.tse2e/data/{product}/{feature}TestData.tse2e/modules/{product}/{Feature}Module.ts (extends FormModule<T> or CardCrudModule<T>)PM{Product}FinancingCaseOverviewPage)e2e/fixtures/fixtures.tse2e/tests/{product}/*.spec.tsFor inquiry processes, also create:
e2e/modules/{product}/inquiryProcess/e2e/pages/{product}/{Product}InquiryPage.tse2e/utils/portalRoutes.ts// Playwright
import { Page, expect, test } from "@playwright/test";
// Base classes
import { FormModule } from "e2e/modules/FormModule";
import { CardCrudModule } from "e2e/modules/CardCrudModule";
import { BasePage } from "e2e/pages/BasePage";
import { InquiryPage, InquiryRoutes } from "e2e/pages/InquiryPage";
// Helpers
import { InteractiveListHelper } from "e2e/helpers/components/InteractiveListHelper";
import { CardHelper } from "e2e/helpers/components/CardHelper";
import { MailtrapHelper } from "e2e/helpers/utilities/MailtrapHelper";
import { InvitationHelper } from "e2e/helpers/utilities/InvitationHelper";
// Data
import { dataTestIds } from "e2e/data/dataTestIds";
import { routes } from "@/routes";
import { BaseField } from "@finstreet/forms";
import { Portal } from "@/shared/types/Portal";
// Fixtures
import { test, expect } from "e2e/fixtures/fixtures";
// Utilities
import { clearAuthState, testCredentials } from "e2e/utils/test-helpers";
All element interactions use data-testid attributes. Never use CSS selectors, class names, or text content for element selection. The dataTestIds object in e2e/data/dataTestIds.ts centralizes all test ID constants.
The FormInteractor.fillField() method appends field-type suffixes to the fieldName:
| BaseField Type | data-testid Pattern |
|---|---|
INPUT | ${fieldName}-input |
PASSWORD | ${fieldName}-password |
NUMBER | ${fieldName}-number |
TEXTAREA | ${fieldName}-textarea |
CHECKBOX | ${fieldName}-checkbox |
YES_NO_RADIO_GROUP | ${fieldName}-yes-no-radio-group__item-yes/no |
RADIO_GROUP | ${fieldName}-radio-group__item-${value} |
SELECT | ${fieldName}-select__trigger / __content / __item-${value} |
COMBOBOX | ${fieldName}-combobox__input (5s wait, then click __item-0 or __item-1) |
DATEPICKER | ${fieldName}-datepicker |
SELECTABLE_CARDS | ${fieldName}-selectable-cards__card-${value} |
FILE_UPLOAD | ${fieldName}-file-upload |
Always wrap logical sections in test.step() for clear HTML report output:
await test.step("Fill in and confirm financing details", async () => {
// ...
});
Always call clearAuthState(page) in beforeEach to clear cookies:
test.beforeEach(async ({ page }) => {
await clearAuthState(page);
});
test.describe.configure({ timeout: 60000 }) for inquiry processestest.setTimeout(360000) inside the test for long flowsAlways import test and expect from e2e/fixtures/fixtures (not from @playwright/test) in spec files:
import { test, expect } from "e2e/fixtures/fixtures";
Import schema types from @/features/... and option enums from their source files:
import { FinancingDetailsType } from "@/features/propertyManagement/forms/financingDetails/financingDetailsFormSchema";
import { UsagePurposes } from "@/features/propertyManagement/forms/financingDetails/usagePurposeOptions";
import { YesNoOptions } from "@/shared/components/form/YesNoRadioGroup/options";
Routes differ by portal. Use portal route resolvers:
// e2e/utils/portalRoutes.ts
export function getHoaLoanInquiryRoutes(portal: Portal) {
return portal === "propertyManager"
? routes.pm.hoaLoan.inquiry
: routes.fsp.hoaLoan.inquiry;
}
form-module-tests.mdUse when: A feature has a form that validates, submits, and navigates back to an overview page. Examples: Financing details, SEPA mandate, reference account, additional information.
card-crud-tests.mdUse when: A feature creates items via a modal form, displays them as cards, and supports update/delete operations. Examples: Property items, legal representatives.
inquiry-process-tests.mdUse when: Adding a new product's multi-step inquiry process with any number of steps. Examples: HOA Loan inquiry, HOA Account inquiry, Factoring inquiry.
happy-path-tests.mdUse when: Testing the complete workflow from inquiry creation through all financing case actions. Examples: HOA Loan happy path, HOA Account happy path.
core-reference.mdUse when: You need the exact API for base classes, helpers, or field interaction patterns.
| File | When to Read |
|---|---|
core-reference.md | Need exact method signatures for BaseHelper, FormInteractor, NavigationHelper, ErrorHandler, CardHelper, InteractiveListHelper, or field type patterns |
form-module-tests.md | Adding a standalone form test module (validate → submit → navigate) |
card-crud-tests.md | Adding card-based CRUD tests (modal → card → update/delete cycle) |
inquiry-process-tests.md | Adding a new product's multi-step inquiry process tests |
happy-path-tests.md | Adding full lifecycle integration tests |