diff --git a/.gitignore b/.gitignore index 7c4061197..063457edf 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ node_modules .DS_Store .idea coverage +.vscode diff --git a/grunt/helpers.js b/grunt/helpers.js index 7369f980b..249547335 100644 --- a/grunt/helpers.js +++ b/grunt/helpers.js @@ -223,8 +223,8 @@ module.exports = function(grunt) { // add root path if necessary, and point to course/config.json const configPath = path.join(path.resolve(root, configDir), coursedir, 'config.' + jsonext); - let buildConfig; + try { buildConfig = grunt.file.readJSON(configPath).build || {}; } catch (error) { diff --git a/jest.config.js b/jest.config.js index 521bb95e8..14ec0f60e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -156,14 +156,14 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: [ - '**/test/unit/**/*.js?(x)', - '!**/__mocks__/**/*.js?(x)' - ] + '**/test/unit/**/*.js?(x)' + ], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "/node_modules/" - // ], + testPathIgnorePatterns: [ + '/__mocks__/', + '/node_modules/' + ] // The regexp pattern or array of patterns that Jest uses to detect test files // testRegex: [], diff --git a/src/core b/src/core index e90414c74..b27a4e964 160000 --- a/src/core +++ b/src/core @@ -1 +1 @@ -Subproject commit e90414c74cdbb144cdabf4fd592e92bc5a790054 +Subproject commit b27a4e9641177f435e8fe95e4c4b5ec3a2e96994 diff --git a/test.js b/test.js index 2f0bb75ca..e6a18d7d5 100644 --- a/test.js +++ b/test.js @@ -44,20 +44,19 @@ async function waitForExec(command, ...args) { return await new Promise(resolve => exec([command, ...args].join(' '), { stdio: [0, 1, 2] }, resolve)); } -const shouldUseOutputDir = Boolean(process.env.npm_config_outputdir); -const outputDir = (process.env.npm_config_outputdir || './build/'); - -async function hasInstalledAndBuilt() { - const hasInstalled = await doFilesExist([ +async function hasInstalled() { + return await doFilesExist([ 'src/components/*', 'src/extensions/*', 'src/menu/*', 'src/theme/*' ]); - const hasBuilt = await doFilesExist([ - path.join(outputDir, 'index.html') +}; + +async function hasBuilt() { + return await doFilesExist([ + path.join(argumentValues.outputdir, 'index.html') ]); - return hasInstalled && hasBuilt; }; async function adaptInstall() { @@ -69,12 +68,12 @@ async function gruntDiff() { 'node', './node_modules/grunt/bin/grunt', 'diff', - shouldUseOutputDir && `--outputdir=${outputDir}` + Boolean(process.env.npm_config_outputdir) && `--outputdir=${argumentValues.outputdir}` ].filter(Boolean)); }; async function gruntServer() { - return backgroundSpawn('node', './node_modules/grunt/bin/grunt', 'server-silent', 'run', `--outputdir=${outputDir}`); + return backgroundSpawn('node', './node_modules/grunt/bin/grunt', 'server-silent', 'run', `--outputdir=${argumentValues.outputdir}`); }; async function waitForGruntServer() { @@ -82,11 +81,21 @@ async function waitForGruntServer() { }; async function cypressRun() { + if (argumentValues.testfiles) { + return asyncSpawn('node', './node_modules/cypress/bin/cypress', 'run', '--spec', `${argumentValues.testfiles}`); + } + return asyncSpawn('node', './node_modules/cypress/bin/cypress', 'run'); }; async function jestRun() { - config.testEnvironmentOptions.outputDir = outputDir; + config.testEnvironmentOptions.outputDir = argumentValues.outputdir; + + // Limit the tests if a certain set are passed in + if (argumentValues.testfiles) { + config.testMatch = argumentValues.testfiles.split(','); + } + return jest.runCLI(config, [process.cwd().replace(/\\/g, '/')]); }; @@ -94,17 +103,35 @@ async function jestClear() { return asyncSpawn('node', './node_modules/jest/bin/jest', '--clearCache'); }; +const acceptedArgs = [ + 'outputdir', + 'skipinstall', + 'testfiles' +]; + +const argumentValues = { + outputdir: (process.env.npm_config_outputdir || './build/'), + skipinstall: false, + testfiles: null +}; + const commands = { help: { name: 'help', description: 'Display this help screen', async start() { - console.log(` + const helpText = ` Usage: To run prepare with the unit and then e2e tests: $ npm test + To run prepare with the unit and then e2e tests without overwriting the ./src/ plugins: + $ npm test --skipinstall + + To run prepare with specif unit and/or e2e tests: + $ npm test --testfiles=**/globForTestsToRun/** + To run any of the available commands: $ npm test @@ -114,15 +141,22 @@ Usage: where is one of: ${Object.values(commands).map(({ name, description }) => ` ${name.padEnd(21, ' ')}${description}`).join('\n')} -`); +`; + console.log(helpText); } }, prepare: { name: 'prepare', description: 'Install and build Adapt ready for testing (runs automatically when requied)', async start() { - await adaptInstall(); - await gruntDiff(); + if ((argumentValues.skipinstall !== 'true') && !await hasInstalled()) { + console.log('Installing latest adapt plugins'); + await adaptInstall(); + } + if (!await hasBuilt()) { + console.log(`Performing course build to '${argumentValues.outputdir}'`); + await gruntDiff(); + } } }, e2e: { @@ -159,26 +193,39 @@ ${Object.values(commands).map(({ name, description }) => ` ${name.padEnd(21, const runTest = async () => { const parameters = process.argv.slice(2); const hasParameters = Boolean(parameters.length); - const [ commandName ] = parameters; + let [ passedArgs = '' ] = parameters; + const [ commandName ] = passedArgs.split(' '); const command = commands[commandName]; const isCommandNotFound = !command; + // Read the input for passed arguments that arent command names + passedArgs = passedArgs.trim().replaceAll('--', '').toLowerCase().split(' ').filter(name => isCommandNotFound || name !== commandName); + + // Update argumentValues array for later use while checking if the command is valid + const paramsRecognised = passedArgs.every(passedArg => { + const passedArgParts = passedArg.trim().split('='); + argumentValues[passedArgParts[0]] = passedArgParts[1]; + return acceptedArgs.includes(passedArgParts[0]); + }); + try { - if (isCommandNotFound && hasParameters) { - const e = new Error(`Unknown command "${commandName}", please check the documentation. $ npm test help`); + if (isCommandNotFound && hasParameters && !paramsRecognised) { + const e = new Error(`Unknown command/argument "${parameters[0]}", please check the documentation. $ npm test help`); console.error(e); return; } const isCommandHelp = (commandName === 'help'); const isCommandPrepare = (commandName === 'prepare'); - const shouldPrepare = (isCommandPrepare || (!isCommandHelp && !await hasInstalledAndBuilt())); + const shouldPrepare = (isCommandPrepare || !isCommandHelp); + if (shouldPrepare) { await commands.prepare.start(); if (isCommandPrepare) return; } - if (!hasParameters) { + // No specific command called - run tests by default + if (isCommandNotFound) { await commands.unit.start(); await commands.e2e.start(); process.exit(0);