11import type { createWatchSession } from '../tools/weapp-tailwindcss-scripts/src/watch-hmr-regression/session'
22import type { CliOptions , WatchCase } from '../tools/weapp-tailwindcss-scripts/src/watch-hmr-regression/types'
3- import type { FrameworkSupportCase } from './frameworkSupportMatrix'
43import process from 'node:process'
54import {
5+ createStyleMutationPayload ,
66 waitForCompileSettled ,
77 waitForOutputFilesUpdated ,
88} from '../tools/weapp-tailwindcss-scripts/src/watch-hmr-regression/mutations'
99import {
10- appendTrailingSnippet ,
1110 findCssRuleBody ,
12- insertBeforeClosingTag ,
1311 normalizeCssDeclaration ,
1412 waitFor ,
1513 writeFilePreserveEol ,
@@ -35,49 +33,39 @@ function getRollbackTimeoutMs(options: CliOptions) {
3533 return Math . min ( options . timeoutMs , readNumberEnv ( 'E2E_IDE_ROLLBACK_TIMEOUT_MS' , 30_000 ) )
3634}
3735
38- function createIdeStyleSnippet ( entry : FrameworkSupportCase , marker : string ) {
39- const selector = `.${ marker } `
40- const functionSelector = `.${ marker } -theme`
41- const color = entry . tailwindcss === 'v4' ? '#14532d' : '#1d4ed8'
42- const lines = [
43- `${ selector } { @apply font-bold text-center bg-[#123456] px-[12px]; color: ${ color } ; }` ,
44- `${ functionSelector } { padding: theme('spacing.2'); margin-left: theme('spacing.3'); }` ,
45- ]
46- if ( entry . tailwindcss === 'v4' ) {
47- lines . unshift ( '@reference "tailwindcss";' )
48- }
49- return lines . join ( '\n' )
50- }
51-
52- function mutateStyleSource ( source : string , snippet : string ) {
53- if ( source . includes ( '</style>' ) ) {
54- return insertBeforeClosingTag ( source , '</style>' , snippet )
55- }
56- return appendTrailingSnippet ( source , snippet )
57- }
58-
59- function assertStyleOutput ( watchCase : WatchCase , content : string , marker : string ) {
60- const applyRule = findCssRuleBody ( content , `.${ marker } ` )
36+ function assertStyleOutput (
37+ watchCase : WatchCase ,
38+ content : string ,
39+ payload : ReturnType < typeof createStyleMutationPayload > ,
40+ ) {
41+ const applyRule = findCssRuleBody ( content , payload . styleNeedle )
6142 if ( ! applyRule ) {
62- throw new Error ( `[${ watchCase . label } ] IDE style HMR output is missing @apply rule . ${ marker } ` )
43+ throw new Error ( `[${ watchCase . label } ] IDE style HMR output is missing style rule ${ payload . styleNeedle } ` )
6344 }
6445 const normalizedApplyRule = normalizeCssDeclaration ( applyRule )
65- for ( const expected of [ 'font-weight:' , 'text-align:' , 'background-color:' , 'padding-left:' , 'padding-right:' ] ) {
46+ for ( const expected of payload . expectedApplyDeclarations ) {
6647 if ( ! normalizedApplyRule . includes ( normalizeCssDeclaration ( expected ) ) ) {
6748 throw new Error ( `[${ watchCase . label } ] IDE style HMR @apply output is missing declaration ${ expected } ` )
6849 }
6950 }
7051
71- const functionRule = findCssRuleBody ( content , `.${ marker } -theme` )
72- if ( ! functionRule ) {
73- throw new Error ( `[${ watchCase . label } ] IDE style HMR output is missing Tailwind function rule .${ marker } -theme` )
52+ if ( ! payload . functionNeedle ) {
53+ return
7454 }
75- if ( functionRule . includes ( 'theme(' ) ) {
76- throw new Error ( `[${ watchCase . label } ] IDE style HMR did not resolve Tailwind theme() function` )
55+
56+ const functionRule = findCssRuleBody ( content , payload . functionNeedle )
57+ if ( ! functionRule ) {
58+ throw new Error ( `[${ watchCase . label } ] IDE style HMR output is missing Tailwind function rule ${ payload . functionNeedle } ` )
7759 }
60+
7861 const normalizedFunctionRule = normalizeCssDeclaration ( functionRule )
79- for ( const expected of [ 'padding' , 'margin-left' ] ) {
80- if ( ! normalizedFunctionRule . includes ( `${ expected } :` ) ) {
62+ for ( const forbidden of payload . forbiddenFunctionFragments ) {
63+ if ( functionRule . includes ( forbidden ) ) {
64+ throw new Error ( `[${ watchCase . label } ] IDE style HMR did not resolve Tailwind function fragment ${ forbidden } ` )
65+ }
66+ }
67+ for ( const expected of payload . expectedFunctionDeclarations ) {
68+ if ( ! normalizedFunctionRule . includes ( normalizeCssDeclaration ( expected ) ) ) {
8169 throw new Error ( `[${ watchCase . label } ] IDE style HMR function output is missing declaration ${ expected } ` )
8270 }
8371 }
@@ -89,16 +77,15 @@ function resolveUpdatedStyleFiles(watchCase: WatchCase, baselineMtimes: Map<stri
8977}
9078
9179export async function runIdeStyleHotUpdate (
92- entry : FrameworkSupportCase ,
9380 options : CliOptions ,
9481 watchCase : WatchCase ,
9582 session : ReturnType < typeof createWatchSession > ,
9683 sourceOriginal : string ,
9784) {
9885 const sourceFile = watchCase . styleMutation . sourceFile
9986 process . stdout . write ( `[e2e:ide] ${ watchCase . label } style HMR mutate ${ sourceFile } \n` )
100- const marker = `tw-ide-style- ${ watchCase . name } - ${ Date . now ( ) . toString ( ) . slice ( - 6 ) } `
101- const mutatedSource = mutateStyleSource ( sourceOriginal , createIdeStyleSnippet ( entry , marker ) )
87+ const payload = createStyleMutationPayload ( watchCase )
88+ const mutatedSource = watchCase . styleMutation . mutate ( sourceOriginal , payload )
10289 const { artifacts : baselineArtifacts , mtimes : baselineMtimes } = await collectArtifactMtimes ( watchCase )
10390 const mutationStartedAt = Date . now ( )
10491
@@ -110,19 +97,19 @@ export async function runIdeStyleHotUpdate(
11097 options ,
11198 session ,
11299 mutationStartedAt ,
113- async ( ) => hasAnyNeedle ( await readArtifacts ( watchCase ) , [ marker ] ) ,
100+ async ( ) => hasAnyNeedle ( await readArtifacts ( watchCase ) , [ payload . styleNeedle ] ) ,
114101 )
115102
116103 let changedArtifacts : string [ ] = [ ]
117104 await waitFor (
118105 async ( ) => {
119106 const currentArtifacts = await readArtifacts ( watchCase )
120- const styleArtifacts = currentArtifacts . filter ( item => item . kind === 'style' && item . content . includes ( marker ) )
107+ const styleArtifacts = currentArtifacts . filter ( item => item . kind === 'style' && item . content . includes ( payload . styleNeedle ) )
121108 if ( styleArtifacts . length === 0 || countChangedArtifacts ( baselineArtifacts , currentArtifacts ) === 0 ) {
122109 return false
123110 }
124111 for ( const artifact of styleArtifacts ) {
125- assertStyleOutput ( watchCase , artifact . content , marker )
112+ assertStyleOutput ( watchCase , artifact . content , payload )
126113 }
127114 changedArtifacts = summarizeChangedArtifacts ( baselineArtifacts , currentArtifacts )
128115 return true
@@ -144,11 +131,11 @@ export async function runIdeStyleHotUpdate(
144131 await writeFilePreserveEol ( sourceFile , sourceOriginal , sourceOriginal )
145132 await waitForCompileSettled ( watchCase , options , session , rollbackStartedAt )
146133 await waitFor (
147- async ( ) => ! hasAnyNeedle ( await readArtifacts ( watchCase ) , [ marker ] ) ,
134+ async ( ) => ! hasAnyNeedle ( await readArtifacts ( watchCase ) , [ payload . styleNeedle ] ) ,
148135 {
149136 timeoutMs : getRollbackTimeoutMs ( options ) ,
150137 pollMs : options . pollMs ,
151- message : `[${ watchCase . label } ] IDE style HMR marker was not removed after rollback: ${ marker } ` ,
138+ message : `[${ watchCase . label } ] IDE style HMR marker was not removed after rollback: ${ payload . styleNeedle } ` ,
152139 onTick : session . ensureRunning ,
153140 } ,
154141 rollbackStartedAt ,
0 commit comments