generator-jhipster-playwright 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,15 @@
9
9
 
10
10
  This is a JHipster blueprint. It overrides the `cypress` sub-generator and writes Playwright files instead of Cypress files for generated applications.
11
11
 
12
- Verified against freshly generated React, Angular, and Vue JHipster applications — all tests passing, no failures or flakiness.
12
+ ### Supported Matrix
13
+
14
+ | Framework | JWT | Session | OAuth2 |
15
+ |-----------|-----|---------|--------|
16
+ | React | Yes | Yes | Yes |
17
+ | Angular | Yes | Yes | Yes |
18
+ | Vue | Yes | Yes | Yes |
19
+
20
+ All 9 combinations are verified in CI against freshly generated JHipster applications. OAuth2 tests run against a Keycloak instance.
13
21
 
14
22
  ## Installation
15
23
 
@@ -59,6 +67,7 @@ application {
59
67
  config {
60
68
  baseName myApp
61
69
  clientFramework react
70
+ authenticationType jwt
62
71
  testFrameworks [cypress]
63
72
  }
64
73
  }
@@ -86,6 +95,12 @@ npx playwright test
86
95
 
87
96
  The generated `playwright.config.ts` starts the frontend dev server automatically. The Spring Boot backend still needs to be running before the tests execute.
88
97
 
98
+ For OAuth2 applications, a Keycloak instance must be running before the backend starts:
99
+
100
+ ```bash
101
+ docker compose -f src/main/docker/keycloak.yml up -d
102
+ ```
103
+
89
104
  ### Generated Output
90
105
 
91
106
  The blueprint writes:
@@ -97,6 +112,8 @@ The blueprint writes:
97
112
 
98
113
  For Angular applications, the blueprint also adds `@popperjs/core` to the generated app dependencies so the generated frontend has the required Popper peer dependency available.
99
114
 
115
+ For Angular session-auth applications, a custom `proxy.config.playwright.mjs` is generated to avoid proxying lazy-loaded route chunks.
116
+
100
117
  ## Local Development
101
118
 
102
119
  To work on the blueprint locally:
@@ -8,7 +8,7 @@
8
8
  * - clientFrameworkAngular, clientFrameworkReact, clientFrameworkVue
9
9
  */
10
10
  import type { Page, APIRequestContext, APIResponse } from '@playwright/test';
11
- import { expect, request as pwRequest } from '@playwright/test';
11
+ import { expect } from '@playwright/test';
12
12
 
13
13
  // ***********************************************
14
14
  // Begin Specific Selector Attributes
@@ -153,14 +153,30 @@ export async function login(page: Page, request: APIRequestContext, username: st
153
153
  await waitForAppShell(page);
154
154
  }
155
155
  <%_ } else if (authenticationTypeOauth2) { _%>
156
+ // Session cookies captured after browser OAuth2 login for API requests.
157
+ let _sessionCookie: string | undefined;
158
+ let _xsrfToken: string | undefined;
159
+
156
160
  /**
157
161
  * Perform authenticated API request (OAuth2).
162
+ * Uses session cookies captured from the browser after login.
158
163
  */
159
164
  export async function authenticatedRequest(
160
165
  request: APIRequestContext,
161
166
  data: { method?: string; url: string; data?: unknown },
162
167
  ): Promise<APIResponse> {
163
- return request.fetch(data.url, { method: data.method ?? 'GET', data: data.data });
168
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
169
+ if (_sessionCookie) {
170
+ headers['Cookie'] = _sessionCookie;
171
+ }
172
+ if (_xsrfToken) {
173
+ headers['X-XSRF-TOKEN'] = _xsrfToken;
174
+ }
175
+ return request.fetch(data.url, {
176
+ method: data.method ?? 'GET',
177
+ data: data.data,
178
+ headers,
179
+ });
164
180
  }
165
181
 
166
182
  /**
@@ -188,6 +204,10 @@ export async function login(page: Page, request: APIRequestContext, username: st
188
204
  }
189
205
  await page.waitForURL('**/', { timeout: 15000 });
190
206
  await waitForAppShell(page);
207
+ // Capture session cookies so authenticatedRequest() can make API calls.
208
+ const cookies = await page.context().cookies();
209
+ _sessionCookie = cookies.map(c => `${c.name}=${c.value}`).join('; ');
210
+ _xsrfToken = cookies.find(c => c.name === 'XSRF-TOKEN')?.value;
191
211
  }
192
212
  <%_ } else { _%>
193
213
  /**
@@ -19,9 +19,14 @@ import {
19
19
 
20
20
  async function clickDropdownItem(menu: Locator, item: string): Promise<void> {
21
21
  await expect(menu).toBeVisible();
22
- await menu.click();
23
22
  const itemLocator = menu.locator(item);
24
- await expect(itemLocator).toBeVisible();
23
+ // Retry open-then-check: the dropdown can close due to animation or re-render.
24
+ await expect(async () => {
25
+ if (!(await itemLocator.isVisible())) {
26
+ await menu.click();
27
+ }
28
+ await expect(itemLocator).toBeVisible();
29
+ }).toPass({ timeout: 10_000 });
25
30
  await itemLocator.click();
26
31
  }
27
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-jhipster-playwright",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "JHipster Playwright E2E blueprint - replaces Cypress with Playwright for end-to-end testing",
5
5
  "keywords": [
6
6
  "yeoman-generator",