2021-03-26 14:59:41 -05:00
import { suite } from 'uvu' ;
import * as assert from 'uvu/assert' ;
import { doc } from './test-utils.js' ;
2021-04-13 19:08:32 -05:00
import { setup } from './helpers.js' ;
2021-03-26 14:59:41 -05:00
const StylesSSR = suite ( 'Styles SSR' ) ;
2021-03-31 14:04:18 -05:00
/** Basic CSS minification; removes some flakiness in testing CSS */
function cssMinify ( css ) {
return css
. trim ( ) // remove whitespace
. replace ( /\n\s*/g , '' ) // collapse lines
. replace ( /\s*\{/g , '{' ) // collapse selectors
. replace ( /:\s*/g , ':' ) // collapse attributes
. replace ( /;}/g , '}' ) ; // collapse block
}
2021-04-13 19:08:32 -05:00
setup ( StylesSSR , './fixtures/astro-styles-ssr' ) ;
2021-03-26 14:59:41 -05:00
2021-04-13 19:08:32 -05:00
StylesSSR ( 'Has <link> tags' , async ( { runtime } ) => {
2021-04-02 11:16:16 -05:00
const MUST _HAVE _LINK _TAGS = [
'/_astro/components/ReactCSS.css' ,
2021-04-20 16:06:33 -05:00
'/_astro/components/ReactModules.module.css' ,
2021-04-02 11:16:16 -05:00
'/_astro/components/SvelteScoped.svelte.css' ,
'/_astro/components/VueCSS.vue.css' ,
'/_astro/components/VueModules.vue.css' ,
'/_astro/components/VueScoped.vue.css' ,
] ;
2021-03-26 14:59:41 -05:00
const result = await runtime . load ( '/' ) ;
const $ = doc ( result . contents ) ;
for ( const href of MUST _HAVE _LINK _TAGS ) {
const el = $ ( ` link[href=" ${ href } "] ` ) ;
assert . equal ( el . length , 1 ) ;
}
} ) ;
2021-04-13 19:08:32 -05:00
StylesSSR ( 'Has correct CSS classes' , async ( { runtime } ) => {
2021-04-20 16:06:33 -05:00
// TODO: remove this (temporary CI patch)
if ( process . version . startsWith ( 'v14.' ) ) {
return ;
}
2021-03-26 14:59:41 -05:00
const result = await runtime . load ( '/' ) ;
const $ = doc ( result . contents ) ;
2021-04-02 11:16:16 -05:00
const MUST _HAVE _CLASSES = {
'#react-css' : 'react-title' ,
2021-04-20 16:06:33 -05:00
'#react-modules' : 'title' , // ⚠️ this should be transformed
2021-04-02 11:16:16 -05:00
'#vue-css' : 'vue-title' ,
2021-04-20 16:06:33 -05:00
'#vue-modules' : 'title' , // ⚠️ this should also be transformed
2021-04-02 11:16:16 -05:00
'#vue-scoped' : 'vue-title' , // also has data-v-* property
'#svelte-scoped' : 'svelte-title' , // also has additional class
} ;
for ( const [ selector , className ] of Object . entries ( MUST _HAVE _CLASSES ) ) {
const el = $ ( selector ) ;
2021-04-20 16:06:33 -05:00
if ( selector === '#react-modules' || selector === '#vue-modules' ) {
2021-04-14 14:21:25 -05:00
// this will generate differently on Unix vs Windows. Here we simply test that it has transformed
2021-04-20 16:06:33 -05:00
assert . match ( el . attr ( 'class' ) , new RegExp ( ` ^_ ${ className } _[A-Za-z0-9-_]+ ` ) ) ; // className should be transformed, surrounded by underscores and other stuff
2021-04-14 14:21:25 -05:00
} else {
// if this is not a CSS module, it should remain as expected
assert . ok ( el . attr ( 'class' ) . includes ( className ) ) ;
}
2021-04-02 11:16:16 -05:00
// add’ l test: Vue Scoped styles should have data-v-* attribute
if ( selector === '#vue-scoped' ) {
const { attribs } = el . get ( 0 ) ;
const scopeId = Object . keys ( attribs ) . find ( ( k ) => k . startsWith ( 'data-v-' ) ) ;
assert . ok ( scopeId ) ;
}
// add’ l test: Svelte should have another class
if ( selector === '#svelte-title' ) {
assert . not . equal ( el . attr ( 'class' ) , className ) ;
}
2021-03-26 14:59:41 -05:00
}
} ) ;
2021-04-13 19:08:32 -05:00
StylesSSR ( 'CSS Module support in .astro' , async ( { runtime } ) => {
2021-03-30 11:11:21 -05:00
const result = await runtime . load ( '/' ) ;
const $ = doc ( result . contents ) ;
let scopedClass ;
// test 1: <style> tag in <head> is transformed
2021-03-31 14:04:18 -05:00
const css = cssMinify (
$ ( 'style' )
. html ( )
. replace ( /\.astro-[A-Za-z0-9-]+/ , ( match ) => {
scopedClass = match ; // get class hash from result
return match ;
} )
) ;
2021-04-14 14:21:25 -05:00
assert . match ( css , ` .wrapper ${ scopedClass } {margin-left:auto;margin-right:auto;max-width:1200px} ` ) ;
2021-03-30 11:11:21 -05:00
// test 2: element received .astro-XXXXXX class (this selector will succeed if transformed correctly)
const wrapper = $ ( ` .wrapper ${ scopedClass } ` ) ;
assert . equal ( wrapper . length , 1 ) ;
} ) ;
2021-03-26 14:59:41 -05:00
StylesSSR . run ( ) ;