-
Notifications
You must be signed in to change notification settings - Fork 7
feat(test): add Playwright E2E test framework #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add comprehensive Playwright-based E2E test suite with Page Object Model architecture for testing user flows in the Spring Demo Application. Test coverage includes: - User registration and email verification flows - Login/logout and session management - Password reset workflow - Profile updates and password changes - Account deletion - Event registration and management - Access control and protected page verification - Admin page restrictions Framework features: - Page Object Model with BasePage, LoginPage, RegisterPage, etc. - Test fixtures for common setup and cleanup - Test API client for backend data manipulation - Automatic user cleanup after tests - Support for running against live server All 81 tests passing.
Add Test API endpoints for Playwright test data management: - Create/delete test users - Check user existence and enabled status - Get verification and password reset URLs - Create verification tokens for testing Add AdminController with @PreAuthorize for access control testing. Add playwright-test profile configuration: - Disable email verification (auto-verify users) - Enable Test API endpoints - Configure for local test execution
- Update build.gradle with test profile configuration - Add playwright test artifacts to .gitignore - Update application.yml with test-related settings
Minor template updates to ensure consistent behavior during automated testing: - layout.html: Ensure consistent structure - forgot-password-change.html: Form field IDs for test selectors - login.html: Consistent error display for test assertions
PR Review: Playwright E2E Test FrameworkThis is an excellent addition to the testing infrastructure! The PR adds a comprehensive Playwright-based E2E test suite with 81 tests covering all major user workflows. Here's my detailed feedback: ✅ StrengthsArchitecture & Design
Code Quality
Coverage
🔒 Security Concerns (CRITICAL)1. Test API Exposure Risk (HIGH PRIORITY)Location: Issue: The test API endpoints at
Recommendation: // Add IP whitelist restriction
@Bean
@Order(1)
public SecurityFilterChain testApiSecurityFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher("/api/test/**")
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(request -> {
String remoteAddr = request.getRemoteAddr();
return "127.0.0.1".equals(remoteAddr) || "localhost".equals(remoteAddr);
}).permitAll()
.anyRequest().denyAll()
)
.csrf(csrf -> csrf.disable());
return http.build();
}Additionally, consider:
2. Dependency Version ConcernLocation: Issue: The framework dependency was changed to a SNAPSHOT version: implementation 'com.digitalsanctuary:ds-spring-user-framework:4.0.3-SNAPSHOT'Impact: SNAPSHOT dependencies can change without notice, leading to:
Recommendation: Either:
3. Configuration SecurityLocation: Issue: The configuration adds Recommendation: Remove from 🐛 Potential Bugs1. Token Deletion Race ConditionLocation: Issue: When deleting a user, tokens are deleted but there's a potential race condition if tokens are being accessed during deletion: VerificationToken verificationToken = verificationTokenRepository.findByUser(user);
if (verificationToken != null) {
verificationTokenRepository.delete(verificationToken);
}Recommendation: Consider using cascade delete on the User entity, or add proper locking: @Transactional
public ResponseEntity<Map<String, Object>> deleteTestUser(@RequestParam String email) {
User user = userRepository.findByEmail(email);
if (user == null) {
// handle not found
}
// Use deleteAll with query to handle multiple tokens if any
verificationTokenRepository.deleteByUser(user);
passwordResetTokenRepository.deleteByUser(user);
userRepository.delete(user);
// ...
}2. Hardcoded Timeout in BasePageLocation: Issue: Recommendation: async logout(): Promise<void> {
const accountDropdown = this.page.locator('#accountDropdown');
if (await accountDropdown.count() > 0) {
await accountDropdown.first().click();
// Wait for dropdown menu to be visible instead of arbitrary timeout
await this.page.locator('.dropdown-menu').waitFor({ state: 'visible', timeout: 2000 });
}
// ...
}3. Missing Error Handling in Test API ClientLocation: Issue: API calls don't check response status codes. Failed requests return error JSON but tests may not detect them: async userExists(email: string): Promise<UserExistsResponse> {
const response = await context.get(`/api/test/user/exists`, {
params: { email },
});
return response.json(); // What if response.status is 500?
}Recommendation: async userExists(email: string): Promise<UserExistsResponse> {
const response = await context.get(`/api/test/user/exists`, {
params: { email },
});
if (!response.ok()) {
throw new Error(`Test API request failed: ${response.status()} ${response.statusText()}`);
}
return response.json();
}⚡ Performance Considerations1. Parallel Test ExecutionLocation: Issue: On CI, workers are set to 1, which will make test runs very slow: workers: process.env.CI ? 1 : undefined,Recommendation: Consider using a higher number even on CI (e.g., 2-4) since tests appear to be properly isolated with unique emails. If there are database concurrency concerns, that's a separate issue to address. 2. WebServer ReuseLocation: Good practice: webServer: {
// ...
reuseExistingServer: !process.env.CI,
// Add this:
healthCheckUrl: 'http://localhost:8080/api/test/health',
}3. Database Connection PoolingLocation: Recommendation: Add connection pool settings for better test performance: spring:
datasource:
hikari:
maximum-pool-size: 5
minimum-idle: 2📝 Code Quality Suggestions1. Magic StringsLocation: Multiple test files Issue: URLs and selectors are sometimes hardcoded in tests instead of using page objects. Example from registration.spec.ts:23: expect(page.url()).toContain('registration-complete');Recommendation: Add constants or methods to page objects: // In RegisterPage
readonly REGISTRATION_COMPLETE_PATH = '/user/registration-complete';
async isOnRegistrationComplete(): Promise<boolean> {
return this.page.url().includes(this.REGISTRATION_COMPLETE_PATH);
}2. Test Data BuildersIssue: Test user generation is basic and doesn't support custom attributes easily. Recommendation: Implement a builder pattern: class TestUserBuilder {
private user: Partial<TestUser> = {
password: generateTestPassword(),
firstName: 'Test',
lastName: 'User',
};
withEmail(prefix: string): this {
this.user.email = generateTestEmail(prefix);
return this;
}
withName(firstName: string, lastName: string): this {
this.user.firstName = firstName;
this.user.lastName = lastName;
return this;
}
build(): TestUser {
if (!this.user.email) {
this.user.email = generateTestEmail('default');
}
return this.user as TestUser;
}
}3. Add JSDoc CommentsLocation: Page object methods Many methods lack documentation. Example: /**
* Register a new user and wait for the registration to complete.
* @param firstName - User's first name
* @param lastName - User's last name
* @param email - User's email address
* @param password - User's password
* @throws {Error} If registration fails or times out
*/
async registerAndWait(/* ... */): Promise<void> {
// ...
}🔍 Test Coverage GapsWhile the 81 tests are comprehensive, consider adding:
📚 DocumentationMissing Documentation
✨ Minor Issues
command: 'cd .. && ./gradlew bootRun --args="--spring.profiles.active=playwright-test"',
tasks.register('playwrightTestHeaded', Exec) {
description = 'Run Playwright tests in headed mode for debugging'
workingDir 'playwright'
commandLine 'npx', 'playwright', 'test', '--headed'
dependsOn 'playwrightBrowsers'
}🎯 Recommendations SummaryMust Fix (Before Merge)
Should Fix (High Priority)
Nice to Have
🎉 ConclusionThis is high-quality work that significantly improves the project's test coverage. The Page Object Model architecture is solid, the test API is a clever solution for test data management, and the coverage is comprehensive. With the security concerns addressed (particularly around the test API), this will be a valuable addition to the codebase. The main concern is ensuring the test API can never be accidentally exposed in production. Once that's addressed, this is ready to merge. Approval Status: Great work on this comprehensive test suite! 🚀 |
|
|
||
| http.securityMatcher("/api/test/**") | ||
| .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()) | ||
| .csrf(csrf -> csrf.disable()); |
Check failure
Code scanning / CodeQL
Disabled Spring CSRF protection High test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
In general, the problem is that CSRF protection is completely disabled for the /api/test/** endpoints. The fix is to stop calling csrf.disable() and instead leave CSRF enabled, optionally configuring it to ignore specific non-browser-safe endpoints when necessary. For test-only APIs that might be hit by browser-based tools (like Playwright, which does behave like a browser), the safest approach is to keep CSRF protection on and have the tests supply CSRF tokens, or to limit CSRF ignoring to clearly non-mutating or non-browser-facing endpoints.
For this specific file, the minimal change that removes the vulnerability while preserving overall behavior is:
- Remove the
.csrf(csrf -> csrf.disable())call from theHttpSecurityconfiguration. - Do not add any custom ignoring, since this is a small test API and the comment already indicates security sensitivity. Leaving CSRF enabled means:
- Any state-changing endpoints under
/api/test/**will now require CSRF tokens when invoked from a browser. - Non-browser clients can still call them if they send the appropriate CSRF header/cookie when needed.
- Any state-changing endpoints under
Concretely:
- In
src/main/java/com/digitalsanctuary/spring/demo/test/config/TestApiSecurityConfig.java, withintestApiSecurityFilterChain, delete the.csrf(csrf -> csrf.disable());call and terminate the previous configuration chain with a semicolon. No new imports or methods are required.
-
Copy modified line R33 -
Copy modified line R43
| @@ -30,7 +30,7 @@ | ||
| @Bean | ||
| @Order(1) | ||
| public SecurityFilterChain testApiSecurityFilterChain(HttpSecurity http) throws Exception { | ||
| log.info("Configuring Test API security - CSRF disabled for /api/test/** (localhost only)"); | ||
| log.info("Configuring Test API security - CSRF enabled for /api/test/** (localhost only)"); | ||
|
|
||
| http.securityMatcher("/api/test/**") | ||
| .authorizeHttpRequests(authorize -> authorize | ||
| @@ -40,8 +40,7 @@ | ||
| "0:0:0:0:0:0:0:1".equals(remoteAddr) || | ||
| "localhost".equals(remoteAddr); | ||
| }).permitAll() | ||
| .anyRequest().denyAll()) | ||
| .csrf(csrf -> csrf.disable()); | ||
| .anyRequest().denyAll()); | ||
|
|
||
| return http.build(); | ||
| } |
Update from 4.0.3-SNAPSHOT to 4.0.3 stable release.
Pull Request Review: Playwright E2E Test FrameworkThank you for this comprehensive addition! This PR adds a robust Playwright-based E2E testing framework with 81 tests. Here's my detailed review: StrengthsArchitecture & Design
Code Quality
Security
Critical Issues1. SECURITY: Production Deployment ProtectionLocation: TestDataController.java, TestApiSecurityConfig.java, application-playwright-test.yml Issue: While @Profile annotations prevent the test API from loading in production, there's no failsafe if the profile is accidentally enabled. Recommendation: Add an application startup check to abort if test profile is active in production. Create a TestProfileGuard component that checks environment variables and fails startup if ENVIRONMENT=production. 2. Security: Overly Broad URI ExceptionsLocation: application-playwright-test.yml:27 Issue: unprotectedURIs adds /api/test/** to the global unprotected list, bypassing security at multiple layers. Recommendation: Remove /api/test/** from YAML config - TestApiSecurityConfig already handles this with securityMatcher, which is more explicit and maintainable. 3. Missing Error Handling in Test API ClientLocation: test-api-client.ts - all methods Issue: API calls don't check response status codes before parsing JSON. Recommendation: Add response.ok() validation and throw descriptive errors for non-200 responses. 4. Parallel Execution ConcernsLocation: playwright.config.ts:33 Issue: Tests run in parallel locally but share the same database, potentially causing race conditions. Current mitigation: Unique email generation provides some isolation. Recommendation: Document limitations or consider database transaction rollback support. Minor Issues
Documentation Suggestions
Recommendations SummaryMust Fix Before Merge:
Should Fix:
Nice to Have:
Final VerdictThis is high-quality work that significantly improves test coverage. The Page Object Model architecture is well-designed and maintainable. Primary concern: Security configuration needs safeguards against accidental production deployment. Recommendation: Approve with minor changes requested Great job on this comprehensive testing framework! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a comprehensive Playwright-based E2E test framework to the Spring Demo Application, providing 81 tests covering major user workflows including registration, login, email verification, password reset, profile management, account deletion, access control, and event management.
Changes:
- Added Playwright test framework with Page Object Model architecture, test fixtures, and a Test API client for database manipulation
- Created backend Test API controller and security configuration (active only in playwright-test profile) to support test scenarios
- Fixed several template issues including CSRF meta tag null checks, login error message display, and script tag path resolution
- Updated build configuration to include Gradle tasks for running Playwright tests
Reviewed changes
Copilot reviewed 39 out of 42 changed files in this pull request and generated 31 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/com/digitalsanctuary/spring/demo/test/config/TestApiSecurityConfig.java | Security configuration that disables CSRF and authentication for /api/test/** endpoints when playwright-test profile is active |
| src/main/java/com/digitalsanctuary/spring/demo/test/api/TestDataController.java | REST controller providing test data manipulation endpoints for E2E tests |
| src/main/java/com/digitalsanctuary/spring/demo/controller/AdminController.java | Admin controller with role-based access control for testing authorization |
| src/main/resources/application-playwright-test.yml | Test profile configuration disabling emails and enabling test API endpoints |
| src/main/resources/application.yml | Updated unprotected URIs to include /js/utils/* path |
| src/main/resources/templates/user/login.html | Added error message display for form login failures |
| src/main/resources/templates/user/forgot-password-change.html | Fixed script tag to use Thymeleaf URL expression |
| src/main/resources/templates/layout.html | Added null checks for CSRF meta tags to prevent errors when CSRF is disabled |
| playwright/playwright.config.ts | Playwright configuration with webServer auto-start and multi-browser testing |
| playwright/tsconfig.json | TypeScript configuration with path aliases for cleaner imports |
| playwright/package.json | Node.js dependencies including Playwright 1.40+ |
| playwright/src/pages/*.ts | Page Object Model classes for all application pages |
| playwright/src/fixtures/test-fixtures.ts | Test fixtures for common setup/teardown and user generation |
| playwright/src/utils/test-api-client.ts | Client for interacting with Test API endpoints |
| playwright/tests/**/*.spec.ts | 81 test specifications organized by feature area |
| build.gradle | Added Gradle tasks for Playwright installation and test execution |
| .gitignore | Added Playwright-specific ignore patterns |
Files not reviewed (1)
- playwright/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Role userRole = roleRepository.findByName("ROLE_USER"); | ||
| if (userRole != null) { | ||
| user.setRoles(Collections.singletonList(userRole)); | ||
| } |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the userRole is null (ROLE_USER doesn't exist in the database), the user will be created without any roles. This could lead to unexpected test failures or authentication issues. Consider either throwing an exception when the role is not found, or logging a warning at minimum, to make these issues more visible during test execution.
| this.changePasswordLink = page.getByRole('link', { name: 'Change Password' }).locator('visible=true').first(); | ||
| this.deleteAccountLink = page.getByRole('link', { name: 'Delete Account' }).locator('visible=true').first(); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The selector 'visible=true' is not a valid Playwright locator filter. Playwright uses the 'visible' state option in waitFor() or isVisible() methods, but not as a chained locator filter. This will likely cause runtime errors. Instead, use the filter method with hasText or simply call first() on visible elements, or use locator.filter() with proper options.
| this.changePasswordLink = page.getByRole('link', { name: 'Change Password' }).locator('visible=true').first(); | |
| this.deleteAccountLink = page.getByRole('link', { name: 'Delete Account' }).locator('visible=true').first(); | |
| this.changePasswordLink = page.getByRole('link', { name: 'Change Password' }).first(); | |
| this.deleteAccountLink = page.getByRole('link', { name: 'Delete Account' }).first(); |
| await this.firstNameInput.clear(); | ||
| await this.firstNameInput.fill(firstName); | ||
| await this.lastNameInput.clear(); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The clear() method is not a standard Playwright Locator method. Use fill('') to clear the field before filling, or simply call fill() directly which will clear and then fill the input. Calling clear() will cause a runtime error.
| await this.firstNameInput.clear(); | |
| await this.firstNameInput.fill(firstName); | |
| await this.lastNameInput.clear(); | |
| await this.firstNameInput.fill(firstName); |
| const user = generateTestUser('delete-account'); | ||
| // Don't add to cleanupEmails since we're deleting it |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user created in this test is not added to cleanupEmails, but if the test fails before the deletion actually happens (e.g., the deleteAccountAndWait() fails), the user will remain in the database and could cause issues with subsequent test runs. Consider adding the user to cleanupEmails before the test runs, and let the cleanup fixture handle removal even if the deletion was successful (the cleanup will just be a no-op in that case).
| testApiClient, | ||
| }) => { | ||
| // Create and login as a verified user | ||
| const user = generateTestUser('delete-logout'); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user created for this test is also not added to cleanupEmails. If the test fails before account deletion, this user will be left in the database. The same issue exists in the 'should not allow login after account deletion' test at line 39. Add these users to cleanupEmails to ensure proper cleanup on test failure.
| page, | ||
| registerPage, | ||
| }) => { | ||
| const user = generateTestUser('invalid-email'); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable user.
| const user = generateTestUser('invalid-email'); |
| await registerPage.passwordInput.fill('Test@123'); | ||
|
|
||
| // Password strength indicator should become visible | ||
| const strengthVisible = await registerPage.isPasswordStrengthVisible(); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable strengthVisible.
| const strengthVisible = await registerPage.isPasswordStrengthVisible(); | |
| const strengthVisible = await registerPage.isPasswordStrengthVisible(); | |
| expect(strengthVisible).toBe(true); |
| @@ -0,0 +1,303 @@ | |||
| import { test, expect, generateTestUser, generateTestEmail } from '../../src/fixtures'; | |||
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import generateTestEmail.
| import { test, expect, generateTestUser, generateTestEmail } from '../../src/fixtures'; | |
| import { test, expect, generateTestUser } from '../../src/fixtures'; |
| @@ -0,0 +1,232 @@ | |||
| import { test, expect, generateTestUser, createAndLoginUser, loginUser } from '../../src/fixtures'; | |||
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import loginUser.
| const user = generateTestUser('update-first'); | ||
| cleanupEmails.push(user.email); | ||
|
|
||
| const createdUser = await createAndLoginUser(page, testApiClient, user); |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable createdUser.
Security improvements: - Add IP whitelist to Test API (localhost only) to prevent accidental exposure - Remove redundant @EnableWebSecurity annotation from TestApiSecurityConfig - Remove /api/test/** from unprotectedURIs (handled by TestApiSecurityConfig) Code quality fixes: - Add HTTP error handling to TestApiClient with descriptive error messages - Fix invalid Playwright selector 'visible=true' in UpdateUserPage - Remove invalid clear() method calls (fill() clears automatically) - Fix dialog handler in EventDetailsPage to use waitForEvent for reliability - Add missing test user cleanup in delete-account tests - Add missing assertion in change-password test - Update Playwright version in package.json to match lock file (^1.58.0) Cleanup: - Remove unused imports from 10 page object files - Remove unused variables and imports from 5 test files - Add warning log when ROLE_USER not found in TestDataController - Document foreign key constraint handling in deleteTestUser - Document test DB credentials as acceptable for local-only profile
Pull Request Review: Playwright E2E Test FrameworkOverviewThis PR adds a comprehensive Playwright E2E test suite with 81 tests covering all major user workflows. The implementation demonstrates strong architectural principles with Page Object Model, test fixtures, and a dedicated test API. This is a substantial and well-structured addition to the project. ✅ StrengthsArchitecture & Design
Code Quality
Security
🔴 Critical Issues1. Security: Test Profile Could Be Accidentally Enabled in ProductionLocation: Issue: While Recommendation:
@Component
@Profile("playwright-test")
public class TestProfileGuard implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
String env = System.getenv("ENVIRONMENT");
if ("production".equalsIgnoreCase(env) || "prod".equalsIgnoreCase(env)) {
throw new IllegalStateException(
"SECURITY: playwright-test profile MUST NOT be active in production!");
}
}
}2. Hardcoded Database Credentials in Config FileLocation: Issue: password: springuser
url: jdbc:mariadb://localhost:3306/springuser?createDatabaseIfNotExist=true
username: springuserWhile the comment acknowledges this is for local development, hardcoded credentials in committed files are a security anti-pattern that can lead to credential reuse and scanning by automated tools. Recommendation:
password: ${DB_PASSWORD:springuser}
username: ${DB_USERNAME:springuser}3. Incomplete User Deletion in Test APILocation: Issue: The comment acknowledges event registrations aren't deleted: // Note: Event registrations and other related entities are not deleted.
// If the user has event registrations, this may fail with foreign key constraint violation.This will cause test failures when tests create users who register for events. Recommendation: Properly cascade delete or manually delete related entities: // Delete event registrations first
eventRegistrationRepository.deleteByUser(user);
// Then delete verification and password reset tokens
VerificationToken verificationToken = verificationTokenRepository.findByUser(user);
// ... rest of deletion
|
Extends UserEmailService to allow disabling password reset emails during Playwright tests. When disabled, tokens are still created so tests can retrieve them via the Test API. - Adds @primary bean to override default UserEmailService - Controlled by app.mail.sendPasswordResetEmail config property - Generates secure tokens even when email sending is disabled
Regenerate lock file to match package.json Playwright version update from ^1.40.0 to ^1.58.0 per PR review feedback.
Pull Request Review: Playwright E2E Test FrameworkThis is an impressive and comprehensive test suite implementation! The PR adds 81 E2E tests with proper Page Object Model architecture. Here's my detailed review: 🎯 StrengthsArchitecture & Design
Code Quality
🔒 Security ConcernsCRITICAL: Test API Security
|
Summary
This PR adds a comprehensive Playwright-based E2E test suite with Page Object Model architecture for testing user flows in the Spring Demo Application.
Test Coverage
Framework Features
BasePage,LoginPage,RegisterPage,DeleteAccountPage, etc.New Files
Playwright Framework (
playwright/)playwright.config.ts- Configuration with webServer auto-startsrc/pages/*.ts- Page Object classessrc/fixtures/- Test fixtures and helperssrc/utils/test-api-client.ts- API client for test datatests/**/*.spec.ts- Test specificationsBackend Support
AdminController.java- Admin page with@PreAuthorizefor access control testsTestDataController.java- Test API endpoints (enabled only in test profile)TestApiSecurityConfig.java- Security config for test APIapplication-playwright-test.yml- Test profile configurationTest Plan
Running Tests
Or with the Gradle task: