2021-05-24 17:18:56 -05:00
import fs from 'fs' ;
import path from 'path' ;
import { fileURLToPath } from 'url' ;
2021-06-10 11:30:48 -05:00
import http from 'http' ;
2021-05-24 17:18:56 -05:00
import { suite } from 'uvu' ;
import execa from 'execa' ;
import del from 'del' ;
2021-06-10 11:30:48 -05:00
import glob from 'tiny-glob' ;
2021-05-24 17:18:56 -05:00
import * as assert from 'uvu/assert' ;
2021-06-08 10:12:07 -05:00
import { TEMPLATES } from '../dist/templates.js' ;
2021-05-24 17:18:56 -05:00
2021-06-10 11:30:48 -05:00
// config
const GITHUB _SHA = process . env . GITHUB _SHA || execa . sync ( 'git' , [ 'rev-parse' , 'HEAD' ] ) . stdout ; // process.env.GITHUB_SHA will be set in CI; if testing locally execa() will gather this
const MAX _TEST _TIME = 60000 ; // maximum time a test may take (60s)
const TIMER = { } ; // keep track of every test’ s run time (uvu requires manual setup for this)
const FIXTURES _DIR = path . join ( fileURLToPath ( path . dirname ( import . meta . url ) ) , 'fixtures' ) ;
2021-05-24 17:18:56 -05:00
2021-06-10 11:30:48 -05:00
// helper
async function fetch ( url ) {
return new Promise ( ( resolve ) => {
http
. get ( url , ( res ) => {
let body = '' ;
res . on ( 'data' , ( chunk ) => {
body += chunk ;
} ) ;
res . on ( 'end' , ( ) => resolve ( { statusCode : res . statusCode , body } ) ) ;
} )
. on ( 'error' , ( err ) => {
reject ( err ) ;
} ) ;
} ) ;
}
// test
const CreateAstro = suite ( 'npm init astro' ) ;
2021-05-24 17:18:56 -05:00
CreateAstro . before ( async ( ) => {
2021-06-10 11:30:48 -05:00
// clean install dir
await del ( FIXTURES _DIR ) ;
await fs . promises . mkdir ( FIXTURES _DIR ) ;
// install all templates & deps before running tests
await Promise . all (
TEMPLATES . map ( async ( { value : template } ) => {
const templateDir = path . join ( FIXTURES _DIR , template ) ;
await execa ( '../../create-astro.mjs' , [ templateDir , '--template' , template , '--commit' , GITHUB _SHA , '--force-overwrite' ] , {
cwd : FIXTURES _DIR ,
} ) ;
await execa ( 'yarn' , [ '--frozen-lockfile' , '--silent' ] , { cwd : templateDir } ) ;
} )
) ;
2021-05-24 17:18:56 -05:00
} ) ;
2021-06-10 11:30:48 -05:00
// enforce MAX_TEST_TIME
CreateAstro . before . each ( ( { _ _test _ _ } ) => {
if ( TIMER [ _ _test _ _ ] ) throw new Error ( ` Test " ${ _ _test _ _ } " already declared ` ) ;
TIMER [ _ _test _ _ ] = setTimeout ( ( ) => {
throw new Error ( ` " ${ _ _test _ _ } " did not finish within allowed time ` ) ;
} , MAX _TEST _TIME ) ;
} ) ;
CreateAstro . after . each ( ( { _ _test _ _ } ) => {
clearTimeout ( TIMER [ _ _test _ _ ] ) ;
} ) ;
2021-05-25 17:16:49 -05:00
2021-06-10 11:30:48 -05:00
for ( let n = 0 ; n < TEMPLATES . length ; n ++ ) {
const template = TEMPLATES [ n ] . value ;
const templateDir = path . join ( FIXTURES _DIR , template ) ;
2021-05-24 17:18:56 -05:00
2021-06-10 11:30:48 -05:00
CreateAstro ( ` ${ template } (install) ` , async ( ) => {
2021-05-24 17:18:56 -05:00
const DOES _HAVE = [ '.gitignore' , 'package.json' , 'public' , 'src' ] ;
2021-06-10 11:30:48 -05:00
const DOES _NOT _HAVE = [ '.git' , 'meta.json' ] ;
2021-05-24 17:18:56 -05:00
// test: template contains essential files & folders
for ( const file of DOES _HAVE ) {
2021-06-10 11:30:48 -05:00
assert . ok ( fs . existsSync ( path . join ( templateDir , file ) ) , ` missing ${ file } ` ) ;
2021-05-24 17:18:56 -05:00
}
// test: template DOES NOT contain files supposed to be stripped away
for ( const file of DOES _NOT _HAVE ) {
2021-06-10 11:30:48 -05:00
assert . not . ok ( fs . existsSync ( path . join ( templateDir , file ) ) , ` failed to clean up ${ file } ` ) ;
}
} ) ;
CreateAstro ( ` ${ template } (dev) ` , async ( ) => {
// start dev server
const port = 3000 + n ; // start new port per test
const devServer = execa ( 'yarn' , [ 'start' , '--port' , port ] , { cwd : templateDir } ) ;
await new Promise ( ( resolve ) => {
setTimeout ( ( ) => resolve ( ) , 15000 ) ;
} ) ; // give dev server flat 15s to set up
// TODO: try to ping dev server ASAP rather than waiting flat 15s
// ping dev server
const { statusCode , body } = await fetch ( ` http://localhost: ${ port } ` ) ;
// expect 200 to be returned with some response
assert . equal ( statusCode , 200 , 'didn’ t respond with 200' ) ;
assert . ok ( body , 'returned empty response' ) ;
// clean up
devServer . kill ( ) ;
} ) ;
CreateAstro ( ` ${ template } (build) ` , async ( ) => {
const MUST _HAVE _FILES = [ 'index.html' , '_astro' ] ;
// build template
await execa ( 'yarn' , [ 'build' ] , { cwd : templateDir } ) ;
// scan build dir
const builtFiles = await glob ( '**/*' , { cwd : path . join ( templateDir , 'dist' ) } ) ;
for ( const file of MUST _HAVE _FILES ) {
assert . ok ( builtFiles . includes ( file ) , ` didn’ t build ${ file } ` ) ;
2021-05-24 17:18:56 -05:00
}
} ) ;
}
2021-06-10 11:30:48 -05:00
// run tests
2021-05-24 17:18:56 -05:00
CreateAstro . run ( ) ;