#!/usr/bin/env node /** * External dependencies. */ const fs = require( 'fs' ); const path = require( 'path' ); const sprintf = require( 'sprintf-js' ).sprintf; /** * Internal dependencies. */ const { resolvePackage, resolvePackagePath, } = require( '../utils' ); const { createLocalE2ePath, confirm, confirmLocalCopy, confirmLocalDelete, getPackageData, installDefaults, } = require( '../utils/scaffold' ); const args = process.argv.slice( 2 ); const command = args[0]; let packageName = null; if (args[1].substr(0, 2) !== '--') { packageName = args[1]; } // Allow multiple spec file extensions and formats. let testExtension = 'test.js'; let testFormat = ''; let force = false; for ( let a = 1; a < args.length; a++ ) { if (args[a] === '--force') { force = true; continue; } // These arguments take a value, eg: --format foo const nextArg = a + 1; if ( nextArg >= args.length ) { break; } switch ( args[ a ] ) { case '--format': testFormat = args[ nextArg ]; break; case '--ext': testExtension = args[ nextArg ]; break; } } /** * Install the test scripts and sample default.json configuration */ if ( command == 'install' ) { // Install some environment defaults if no package is requested. if ( ! packageName ) { installDefaults(force); return; } // `package` is a reserved word const pkg = resolvePackage( packageName ).name; if ( ! pkg.length ) { //@todo add error message return; } const { packageSlug, testSpecs, defaultJson, initializeSh } = getPackageData( pkg ); // Write sample default.json if ( defaultJson ) { const defaultJsonName = `config${path.sep}default-${packageSlug}.json`; createLocalE2ePath( 'config' ); if ( confirmLocalCopy( defaultJsonName, defaultJson, pkg, force ) ) { console.log( `Created sample test configuration to 'tests/e2e/${defaultJsonName}'.` ); } } // Write sample initialize.sh if ( initializeSh ) { const defaultInitName = `docker${path.sep}${packageSlug}.sh`; createLocalE2ePath( 'docker' ); if ( confirmLocalCopy( defaultInitName, initializeSh, pkg, force ) ) { console.log( `Created sample test container initialization script to 'tests/e2e/${defaultInitName}'.` ); } } if ( ! testSpecs ) { return; } // Write test files const testsSpecFile = resolvePackagePath( testSpecs, pkg ); const specs = fs.readFileSync( testsSpecFile ); const tests = JSON.parse( specs ); const { active, deprecated } = tests; if ( active && active.length ) { const blankLine = ''; const eol = "\n"; const autoGenerate = sprintf( '/* This file was auto-generated by the command `npx wc-e2e install %s`. */', packageName ); let importLineFormat; let overwriteFiles; let confirmPrompt; if ( testFormat.toLowerCase() == 'cjs' ) { importLineFormat = sprintf( "const {%%s} = require( '%s' );", pkg ); } else { importLineFormat = sprintf( "import {%%s} from '%s';", pkg ); } // Create the specs folder if not present let specFolderPath = createLocalE2ePath( 'specs' ); // Loop through folders and files to write test scripts. for ( let f = 0; f < active.length; f++ ) { if ( overwriteFiles == 'q' ) { overwriteFiles = ''; break; } const testFolder = active[ f ]; const { testFiles } = testFolder; if ( ! testFiles || ! testFiles.length ) { continue; } let specFolder; if ( testFolder.name.length ) { specFolder = createLocalE2ePath( `specs${path.sep}${testFolder.name}` ); } else { specFolder = specFolderPath; } // Create the test files. for ( let t = 0; t < testFiles.length; t++ ) { const testFile = testFiles[ t ]; if ( ! testFile.functions.length ) { continue; } const testFileName = `${testFolder.name}${path.sep}${testFile.name}.${testExtension}`; const testFilePath = `${specFolder}${path.sep}${testFile.name}.${testExtension}`; // Check to see if file exists. if ( fs.existsSync( testFilePath ) ) { if ( overwriteFiles != 'a' ) { confirmPrompt = `${testFileName} already exists. Overwrite? [y]es/[n]o/[a]ll/[q]uit: `; overwriteFiles = confirm( confirmPrompt, 'anqy' ); overwriteFiles = overwriteFiles.toLowerCase(); } if ( overwriteFiles == 'q' ) { break; } if ( overwriteFiles != 'a' && overwriteFiles != 'y' ) { continue; } } console.log( 'Writing tests/e2e/specs/' + testFileName ); let buffer = [ autoGenerate ]; let testSeparator, testTerminator, importPrefix; // Add the import line. if ( testFile.functions.length > 3 ) { testSeparator = ',' + eol; testTerminator = eol; importPrefix = eol; } else { testSeparator = ', '; testTerminator = ' '; importPrefix = ' '; } const testImport = testFile.functions.join( testSeparator ) + testTerminator; buffer.push( sprintf( importLineFormat, importPrefix + testImport ), blankLine ); // Add test function calls and write the file let functionCalls = testFile.functions.map( functionName => functionName + '();' ); buffer.push( ...functionCalls, blankLine ); fs.writeFileSync( testFilePath, buffer.join( eol ) ); } } } // @todo: deprecated files. } else if ( command == 'uninstall' ) { if ( ! packageName ) { // @todo: write error message return; } const pkg = resolvePackage( packageName ).name; const { packageSlug, testSpecs, defaultJson, initializeSh } = getPackageData( pkg ); // Delete sample default.json if ( defaultJson ) { const defaultJsonName = `config${path.sep}default-${packageSlug}.json`; confirmLocalDelete( defaultJsonName ); } // Delete sample initialize.sh if ( initializeSh ) { const defaultInitName = `docker${path.sep}${packageSlug}.sh`; confirmLocalDelete( defaultInitName ); } if ( ! testSpecs ) { return; } const testsSpecFile = resolvePackagePath( testSpecs, pkg ); const specs = fs.readFileSync( testsSpecFile ); const tests = JSON.parse( specs ); const { active } = tests; if ( ! active || ! active.length ) { return; } // Loop through folders and files to delete test scripts. for ( let f = 0; f < active.length; f++ ) { const testFolder = active[ f ]; const { testFiles } = testFolder; if ( ! testFiles || ! testFiles.length ) { continue; } const specFolder = testFolder.name.length ? `specs${path.sep}${testFolder.name}` : 'specs'; for ( let t = 0; t < testFiles.length; t++ ) { const testFile = testFiles[ t ]; const testFilePath = `${specFolder}${path.sep}${testFile.name}.${testExtension}`; confirmLocalDelete( testFilePath ); } } }