@@ -34,12 +34,18 @@ const fixtures = [
3434 templateDisplayName : string ;
3535} > ;
3636
37- type RouteBasePath = "css" | "rsc-server-first-css" ;
37+ type RouteBasePath =
38+ | "css-with-links-export"
39+ | "css-with-floated-link"
40+ | "rsc-server-first-route" ;
3841const getRouteBasePaths = ( templateName : TemplateName ) => {
39- if ( templateName . includes ( "rsc" ) ) {
40- return [ "css" , "rsc-server-first-css" ] as const satisfies RouteBasePath [ ] ;
41- }
42- return [ "css" ] as const satisfies RouteBasePath [ ] ;
42+ return [
43+ "css-with-links-export" ,
44+ "css-with-floated-link" ,
45+ ...( templateName . includes ( "rsc" )
46+ ? ( [ "rsc-server-first-route" ] as const )
47+ : [ ] ) ,
48+ ] as const satisfies RouteBasePath [ ] ;
4349} ;
4450
4551const files = ( { templateName } : { templateName : TemplateName } ) => ( {
@@ -112,7 +118,7 @@ const files = ({ templateName }: { templateName: TemplateName }) => ({
112118 ...Object . assign (
113119 { } ,
114120 ...getRouteBasePaths ( templateName ) . map ( ( routeBasePath ) => {
115- const isServerFirstRoute = routeBasePath === "rsc-server-first-css " ;
121+ const isServerFirstRoute = routeBasePath === "rsc-server-first-route " ;
116122 const exportName = isServerFirstRoute ? "ServerComponent" : "default" ;
117123
118124 return {
@@ -162,14 +168,17 @@ const files = ({ templateName }: { templateName: TemplateName }) => ({
162168 return null;
163169 }
164170
165- export function links() {
166- return [{ rel: "stylesheet", href: postcssLinkedStyles }];
171+ ${
172+ routeBasePath === "css-with-links-export"
173+ ? `export function links() { return [{ rel: "stylesheet", href: postcssLinkedStyles }]; }`
174+ : ""
167175 }
168176
169177 function TestRoute() {
170178 return (
171179 <>
172180 <input />
181+ ${ routeBasePath !== "css-with-links-export" ? `<link rel="stylesheet" href={postcssLinkedStyles} precedence="default" />` : "" }
173182 <div id="entry-client" className="entry-client">
174183 <div id="css-modules" className={cssModulesStyles.index}>
175184 <div id="css-postcss-linked" className="${ routeBasePath } -postcss-linked">
@@ -517,11 +526,6 @@ async function hmrWorkflow({
517526 base ?: string ;
518527 templateName : TemplateName ;
519528} ) {
520- if ( templateName . includes ( "rsc" ) ) {
521- // TODO: Fix CSS HMR support in RSC Framework mode
522- return ;
523- }
524-
525529 for ( const routeBase of getRouteBasePaths ( templateName ) ) {
526530 let pageErrors : Error [ ] = [ ] ;
527531 page . on ( "pageerror" , ( error ) => pageErrors . push ( error ) ) ;
@@ -532,8 +536,6 @@ async function hmrWorkflow({
532536
533537 let input = page . locator ( "input" ) ;
534538 await expect ( input ) . toBeVisible ( ) ;
535- await input . type ( "stateful" ) ;
536- await expect ( input ) . toHaveValue ( "stateful" ) ;
537539
538540 let edit = createEditor ( cwd ) ;
539541 let modifyCss = ( contents : string ) =>
@@ -544,34 +546,57 @@ async function hmrWorkflow({
544546 "NEW_PADDING_INJECTED_VIA_POSTCSS" ,
545547 ) ;
546548
547- await Promise . all ( [
548- edit ( `app/routes/${ routeBase } /styles-bundled.css` , modifyCss ) ,
549- edit ( `app/routes/${ routeBase } /styles.module.css` , modifyCss ) ,
550- edit ( `app/routes/${ routeBase } /styles-vanilla-global.css.ts` , modifyCss ) ,
551- edit ( `app/routes/${ routeBase } /styles-vanilla-local.css.ts` , modifyCss ) ,
552- edit ( `app/routes/${ routeBase } /styles-postcss-linked.css` , modifyCss ) ,
553- ] ) ;
554-
555- await Promise . all (
556- [
557- "#css-bundled" ,
558- "#css-postcss-linked" ,
559- "#css-modules" ,
560- "#css-vanilla-global" ,
561- "#css-vanilla-local" ,
562- ] . map (
563- async ( selector ) =>
564- await expect ( page . locator ( selector ) ) . toHaveCSS (
565- "padding" ,
566- NEW_PADDING ,
567- ) ,
568- ) ,
569- ) ;
549+ const testCases = [
550+ { file : "styles-bundled.css" , selector : "#css-bundled" } ,
551+ // TODO: Fix HMR for CSS Modules in server-first routes in RSC Framework mode
552+ ...( routeBase === "rsc-server-first-route"
553+ ? [ ]
554+ : [ { file : "styles.module.css" , selector : "#css-modules" } ] ) ,
555+ // TODO: Fix HMR for `?url` CSS imports in RSC Framework mode: https://github.com/vitejs/vite-plugin-react/issues/772
556+ // Once fixed, check if this also fixes HMR for Vanilla Extract
557+ ...( templateName . includes ( "rsc" )
558+ ? [ ]
559+ : [
560+ {
561+ file : "styles-postcss-linked.css" ,
562+ selector : "#css-postcss-linked" ,
563+ } ,
564+ {
565+ file : "styles-vanilla-global.css.ts" ,
566+ selector : "#css-vanilla-global" ,
567+ } ,
568+ {
569+ file : "styles-vanilla-local.css.ts" ,
570+ selector : "#css-vanilla-local" ,
571+ } ,
572+ ] ) ,
573+ ] as const satisfies Array < {
574+ file : string ;
575+ selector : string ;
576+ } > ;
577+
578+ for ( const { file, selector } of testCases ) {
579+ const routeFile = `app/routes/${ routeBase } /${ file } ` ;
580+ await input . fill ( routeFile ) ;
581+ await edit ( routeFile , modifyCss ) ;
582+ await expect (
583+ page . locator ( selector ) ,
584+ `CSS update for ${ routeFile } ` ,
585+ ) . toHaveCSS ( "padding" , NEW_PADDING ) ;
586+
587+ // TODO: Fix state preservation when changing CSS Modules in RSC Framework mode
588+ if ( templateName . includes ( "rsc" ) && file === "styles.module.css" ) {
589+ continue ;
590+ }
570591
571- // Ensure CSS updates were handled by HMR
572- await expect ( input ) . toHaveValue ( "stateful" ) ;
592+ // Ensure CSS updates were handled by HMR
593+ await expect ( input , `State preservation for ${ routeFile } ` ) . toHaveValue (
594+ routeFile ,
595+ ) ;
596+ }
573597
574- if ( routeBase === "css" ) {
598+ // RSC Framework mode doesn't support custom entries yet
599+ if ( ! templateName . includes ( "rsc" ) ) {
575600 // The following change triggers a full page reload, so we check it after all the checks for HMR state preservation
576601 await edit ( "app/entry.client.css" , modifyCss ) ;
577602 await expect ( page . locator ( "#entry-client" ) ) . toHaveCSS (
0 commit comments