@@ -3,13 +3,17 @@ import { expect, test } from '@nuxt/test-utils/playwright'
33test . describe ( 'Create Command' , ( ) => {
44 test . describe ( 'Visibility' , ( ) => {
55 test ( '/vite - should show create command (same maintainers)' , async ( { page, goto } ) => {
6- await goto ( '/vite' , { waitUntil : 'domcontentloaded' } )
6+ await goto ( '/vite' , { waitUntil : 'hydration' } )
7+
8+ await expect ( page . locator ( 'h1' ) ) . toContainText ( 'vite' , { timeout : 15000 } )
79
8- // Create command section should be visible (SSR)
9- // Use specific container to avoid matching README code blocks
10- const createCommandSection = page . locator ( '.group\\/createcmd' )
11- await expect ( createCommandSection ) . toBeVisible ( )
12- await expect ( createCommandSection . locator ( 'code' ) ) . toContainText ( / c r e a t e v i t e / i)
10+ // Create command is loaded via API (packageAnalysis), wait for it
11+ // All PM variants are rendered; npm is visible by default
12+ const createCommandRow = page
13+ . locator ( '[data-pm-cmd="npm"]' )
14+ . filter ( { hasText : / c r e a t e v i t e / i } )
15+ await expect ( createCommandRow ) . toBeVisible ( )
16+ await expect ( createCommandRow . locator ( 'code' ) ) . toContainText ( / c r e a t e v i t e / i)
1317
1418 // Link to create-vite should be present (uses sr-only text, so check attachment not visibility)
1519 await expect ( page . locator ( 'a[href="/create-vite"]' ) ) . toBeAttached ( )
@@ -19,58 +23,81 @@ test.describe('Create Command', () => {
1923 page,
2024 goto,
2125 } ) => {
22- await goto ( '/next' , { waitUntil : 'domcontentloaded' } )
26+ await goto ( '/next' , { waitUntil : 'hydration' } )
27+
28+ // Wait for package page to load
29+ await expect ( page . locator ( 'h1' ) ) . toContainText ( 'next' , { timeout : 15000 } )
2330
24- // Create command section should be visible (SSR)
25- // Use specific container to avoid matching README code blocks
26- const createCommandSection = page . locator ( '.group\\/createcmd' )
27- await expect ( createCommandSection ) . toBeVisible ( )
28- await expect ( createCommandSection . locator ( 'code' ) ) . toContainText ( / c r e a t e n e x t - a p p / i)
31+ // Create command is loaded via API
32+ const createCommandRow = page
33+ . locator ( '[data-pm-cmd="npm"]' )
34+ . filter ( { hasText : / c r e a t e n e x t - a p p / i } )
35+ await expect ( createCommandRow ) . toBeVisible ( { timeout : 15000 } )
36+ await expect ( createCommandRow . locator ( 'code' ) ) . toContainText ( / c r e a t e n e x t - a p p / i)
2937
30- // Link to create-next-app should be present (uses sr-only text, so check attachment not visibility)
38+ // Link to create-next-app should be present
3139 await expect ( page . locator ( 'a[href="/create-next-app"]' ) ) . toBeAttached ( )
3240 } )
3341
3442 test ( '/nuxt - should show create command (same maintainer, same org)' , async ( {
3543 page,
3644 goto,
3745 } ) => {
38- await goto ( '/nuxt' , { waitUntil : 'domcontentloaded' } )
39-
40- // Create command section should be visible (SSR)
41- // nuxt has create-nuxt package, so command is "npm create nuxt"
42- // Use specific container to avoid matching README code blocks
43- const createCommandSection = page . locator ( '.group\\/createcmd' )
44- await expect ( createCommandSection ) . toBeVisible ( )
45- await expect ( createCommandSection . locator ( 'code' ) ) . toContainText ( / c r e a t e n u x t / i)
46+ await goto ( '/nuxt' , { waitUntil : 'hydration' } )
47+
48+ // Wait for package page to load (longer timeout for network flakiness)
49+ await expect ( page . locator ( 'h1' ) ) . toContainText ( 'nuxt' , { timeout : 15000 } )
50+
51+ // Create command is loaded via API, wait for it
52+ const createCommandRow = page
53+ . locator ( '[data-pm-cmd="npm"]' )
54+ . filter ( { hasText : / c r e a t e n u x t / i } )
55+ await expect ( createCommandRow ) . toBeVisible ( { timeout : 15000 } )
56+ await expect ( createCommandRow . locator ( 'code' ) ) . toContainText ( / c r e a t e n u x t / i)
4657 } )
4758
4859 test ( '/color - should NOT show create command (different maintainers)' , async ( {
4960 page,
5061 goto,
5162 } ) => {
52- await goto ( '/color' , { waitUntil : 'domcontentloaded ' } )
63+ await goto ( '/color' , { waitUntil : 'hydration ' } )
5364
54- // Wait for package to load
65+ // Wait for package page to load
5566 await expect ( page . locator ( 'h1' ) . filter ( { hasText : 'color' } ) ) . toBeVisible ( )
5667
57- // Create command section should NOT be visible (different maintainers)
58- const createCommandSection = page . locator ( '.group\\/createcmd' )
59- await expect ( createCommandSection ) . not . toBeVisible ( )
68+ // Wait for API to complete (install command should be visible)
69+ await expect ( page . locator ( '[data-pm-cmd="npm"]' ) . first ( ) ) . toBeVisible ( )
70+
71+ // Give time for any create command to appear, then verify it doesn't
72+ await page . waitForTimeout ( 1000 )
73+
74+ // Create command should NOT exist (different maintainers)
75+ const createCommandRow = page
76+ . locator ( '[data-pm-cmd="npm"]' )
77+ . filter ( { hasText : / \b c r e a t e c o l o r \b / i } )
78+ await expect ( createCommandRow ) . toHaveCount ( 0 )
6079 } )
6180
6281 test ( '/lodash - should NOT show create command (no create-lodash exists)' , async ( {
6382 page,
6483 goto,
6584 } ) => {
66- await goto ( '/lodash' , { waitUntil : 'domcontentloaded ' } )
85+ await goto ( '/lodash' , { waitUntil : 'hydration ' } )
6786
68- // Wait for package to load
87+ // Wait for package page to load
6988 await expect ( page . locator ( 'h1' ) . filter ( { hasText : 'lodash' } ) ) . toBeVisible ( )
7089
71- // Create command section should NOT be visible (no create-lodash exists)
72- const createCommandSection = page . locator ( '.group\\/createcmd' )
73- await expect ( createCommandSection ) . not . toBeVisible ( )
90+ // Wait for API to complete (install command should be visible)
91+ await expect ( page . locator ( '[data-pm-cmd="npm"]' ) . first ( ) ) . toBeVisible ( )
92+
93+ // Give time for any create command to appear, then verify it doesn't
94+ await page . waitForTimeout ( 1000 )
95+
96+ // Create command should NOT exist (no create-lodash exists)
97+ const createCommandRow = page
98+ . locator ( '[data-pm-cmd="npm"]' )
99+ . filter ( { hasText : / \b c r e a t e l o d a s h \b / i } )
100+ await expect ( createCommandRow ) . toHaveCount ( 0 )
74101 } )
75102 } )
76103
@@ -79,19 +106,22 @@ test.describe('Create Command', () => {
79106 await goto ( '/vite' , { waitUntil : 'hydration' } )
80107
81108 // Wait for package analysis API to load (create command requires this)
82- // First ensure the package page has loaded
83- await expect ( page . locator ( 'h1' ) ) . toContainText ( 'vite' )
109+ // First ensure the package page has loaded (longer timeout for network flakiness)
110+ await expect ( page . locator ( 'h1' ) ) . toContainText ( 'vite' , { timeout : 15000 } )
84111
85- // Find the create command container (wait longer for API response)
86- const createCommandContainer = page . locator ( '.group\\/createcmd' )
87- await expect ( createCommandContainer ) . toBeVisible ( { timeout : 15000 } )
112+ // Find the create command row (npm variant) - it contains "create vite" in code
113+ // The component renders all PM variants; npm is visible by default
114+ const createCommandRow = page
115+ . locator ( '[data-pm-cmd="npm"]' )
116+ . filter ( { hasText : / c r e a t e v i t e / i } )
117+ await expect ( createCommandRow ) . toBeVisible ( { timeout : 15000 } )
88118
89119 // Copy button should initially be hidden (opacity-0)
90- const copyButton = createCommandContainer . locator ( 'button' )
120+ const copyButton = createCommandRow . locator ( 'button' )
91121 await expect ( copyButton ) . toHaveCSS ( 'opacity' , '0' )
92122
93123 // Hover over the container
94- await createCommandContainer . hover ( )
124+ await createCommandRow . hover ( )
95125
96126 // Copy button should become visible
97127 await expect ( copyButton ) . toHaveCSS ( 'opacity' , '1' )
@@ -107,12 +137,18 @@ test.describe('Create Command', () => {
107137
108138 await goto ( '/vite' , { waitUntil : 'hydration' } )
109139
110- // Find and hover over the create command container
111- const createCommandContainer = page . locator ( '.group\\/createcmd' )
112- await createCommandContainer . hover ( )
140+ // Wait for h1 to confirm page loaded (longer timeout for network flakiness)
141+ await expect ( page . locator ( 'h1' ) ) . toContainText ( 'vite' , { timeout : 15000 } )
142+
143+ // Find and hover over the create command row (npm variant), wait for API
144+ const createCommandRow = page
145+ . locator ( '[data-pm-cmd="npm"]' )
146+ . filter ( { hasText : / c r e a t e v i t e / i } )
147+ await expect ( createCommandRow ) . toBeVisible ( { timeout : 15000 } )
148+ await createCommandRow . hover ( )
113149
114150 // Click the copy button
115- const copyButton = createCommandContainer . locator ( 'button' )
151+ const copyButton = createCommandRow . locator ( 'button' )
116152 await copyButton . click ( )
117153
118154 // Button text should change to "copied!"
@@ -131,16 +167,17 @@ test.describe('Create Command', () => {
131167 test ( 'hovering install command shows copy button' , async ( { page, goto } ) => {
132168 await goto ( '/lodash' , { waitUntil : 'hydration' } )
133169
134- // Find the install command container
135- const installCommandContainer = page . locator ( '.group\\/installcmd' )
136- await expect ( installCommandContainer ) . toBeVisible ( )
170+ // Find the npm install command row (npm is the default, so it's visible)
171+ // The component uses group/cmd class for each command row
172+ const installCommandRow = page . locator ( '[data-pm-cmd="npm"]' ) . first ( )
173+ await expect ( installCommandRow ) . toBeVisible ( )
137174
138- // Copy button should initially be hidden
139- const copyButton = installCommandContainer . locator ( 'button' )
175+ // Copy button should initially be hidden (opacity-0)
176+ const copyButton = installCommandRow . locator ( 'button' )
140177 await expect ( copyButton ) . toHaveCSS ( 'opacity' , '0' )
141178
142179 // Hover over the container
143- await installCommandContainer . hover ( )
180+ await installCommandRow . hover ( )
144181
145182 // Copy button should become visible
146183 await expect ( copyButton ) . toHaveCSS ( 'opacity' , '1' )
@@ -156,12 +193,12 @@ test.describe('Create Command', () => {
156193
157194 await goto ( '/lodash' , { waitUntil : 'hydration' } )
158195
159- // Find and hover over the install command container
160- const installCommandContainer = page . locator ( '.group\\/installcmd' )
161- await installCommandContainer . hover ( )
196+ // Find and hover over the npm install command row (npm is the default)
197+ const installCommandRow = page . locator ( '[data-pm-cmd="npm"]' ) . first ( )
198+ await installCommandRow . hover ( )
162199
163200 // Click the copy button
164- const copyButton = installCommandContainer . locator ( 'button' )
201+ const copyButton = installCommandRow . locator ( 'button' )
165202 await copyButton . click ( )
166203
167204 // Button text should change to "copied!"
0 commit comments