diff --git a/app/config.js b/app/config.js index 4fcd4e86..e72f4676 100644 --- a/app/config.js +++ b/app/config.js @@ -51,7 +51,68 @@ module.exports = { name: 'includeJQuery', message: 'Would you like to include jQuery?', default: true, - when: answers => !answers.features.includes('includeBootstrap') + when: answers => + answers.features && !answers.features.includes('includeBootstrap') + }, + { + type: 'confirm', + name: 'includeTest', + message: 'Would you like to add testing?', + default: true + }, + { + type: 'checkbox', + name: 'testsWanted', + message: 'Which type of test would you like to cover?', + when: answers => answers.includeTest, + choices: [ + { + name: 'End to end (e2e)', + value: 'includeE2e', + checked: true + }, + { + name: 'Unit Test', + value: 'includeUnit', + checked: true + } + ] + }, + { + type: 'list', + name: 'unitTestFramework', + message: 'Which test framework would you like to use?', + when: answers => + answers.includeTest && + answers.testsWanted && + answers.testsWanted.includes('includeUnit'), + choices: [ + { + name: 'Jest', + value: 'jest', + checked: true + }, + { + name: 'Ava', + value: 'ava', + checked: true + }, + { + name: 'Jasmine', + value: 'jasmine', + checked: true + }, + { + name: 'Mocha (Testing driven design)', + value: 'mochaTdd', + checked: true + }, + { + name: 'Mocha (Behaviour Driven Design)', + value: 'mochaBdd', + checked: true + } + ] } ], dirsToCreate: ['app/images', 'app/fonts'], diff --git a/app/index.js b/app/index.js index d04d7b47..c6ee8f4e 100644 --- a/app/index.js +++ b/app/index.js @@ -15,19 +15,9 @@ module.exports = class extends Generator { initializing() { this.pkg = require('../package.json'); - if (this.options['skip-test-framework']) { return; } - - this.composeWith( - require.resolve( - `generator-${this.options['test-framework']}/generators/app` - ), - { - 'skip-install': this.options['skip-install'] - } - ); } prompting() { @@ -41,7 +31,9 @@ module.exports = class extends Generator { return this.prompt(config.prompts).then(answers => { const features = answers.features; + const testsWanted = answers.testsWanted; const hasFeature = feat => features && features.includes(feat); + const hasTest = type => testsWanted && testsWanted.includes(type); // manually deal with the response, get back and store the results. // we change a bit this way of doing to automatically do this in the self.prompt() method. @@ -50,6 +42,10 @@ module.exports = class extends Generator { this.includeModernizr = hasFeature('includeModernizr'); this.includeAnalytics = hasFeature('includeAnalytics'); this.includeJQuery = answers.includeJQuery; + this.includeE2e = hasTest('includeE2e'); + this.includeUnit = hasTest('includeUnit'); + this.includeTest = this.includeE2e || this.includeUnit; + this.unitTestFramework = answers.unitTestFramework; }); } @@ -61,10 +57,13 @@ module.exports = class extends Generator { version: this.pkg.version, includeSass: this.includeSass, includeBootstrap: this.includeBootstrap, - testFramework: this.options['test-framework'], includeJQuery: this.includeJQuery, includeModernizr: this.includeModernizr, - includeAnalytics: this.includeAnalytics + includeAnalytics: this.includeAnalytics, + includeTest: this.includeTest, + includeE2e: this.includeE2e, + includeUnit: this.includeUnit, + unitTestFramework: this.unitTestFramework }; const copy = (input, output) => { @@ -98,6 +97,18 @@ module.exports = class extends Generator { copy('modernizr.json', 'modernizr.json'); } + if (this.includeE2e) { + copy('demo_cypress.js', 'cypress/integration/index_spec.js'); + } + + if (this.includeUnit && this.unitTestFramework === 'jest') { + copy('demo_jest.js', '__test__/main.test.js'); + } + + if (this.includeUnit && this.unitTestFramework === 'ava') { + copy('demo_ava.js', '__test__/main.test.js'); + } + let cssFile = `main.${this.includeSass ? 'scss' : 'css'}`; copyTpl(cssFile, `app/styles/${cssFile}`, templateData); } diff --git a/app/templates/_package.json b/app/templates/_package.json index 0d1e1ea4..505ed22f 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -15,11 +15,20 @@ <%_ } -%> }, "devDependencies": { + <%_ if (includeUnit && unitTestFramework === 'ava') { -%> + "ava": "^2.0.0", + <%_ } -%> "@babel/core": "^7.4.5", "@babel/preset-env": "^7.4.5", "autoprefixer": "^9.5.1", "browser-sync": "^2.26.5", "cross-env": "^5.2.0", + <%_ if (includeE2e) { -%> + "cypress": "^3.3.1", + <%_ } -%> + <%_ if (includeUnit && unitTestFramework === 'ava') { -%> + "esm": "^3.2.25", + <%_ } -%> "cssnano": "^4.1.10", "del": "^4.1.1", "gulp": "^4.0.2", @@ -39,21 +48,61 @@ "gulp-sass": "^4.0.2", <%_ } -%> "gulp-size": "^3.0.0", + <%_ if (includeUnit && unitTestFramework === 'jest') { -%> + "jest": "^24.8.0", + <%_ } -%> "gulp-sourcemaps": "^2.6.5", "gulp-uglify": "^3.0.2", "gulp-useref": "^3.1.6", <%_ if (includeModernizr) { -%> "mkdirp": "^0.5.1", <%_ } -%> - "mocha": "^6.1.4", - "yargs": "13.2.4" + <%_ if (includeUnit && unitTestFramework === 'ava') { -%> + "nyc": "^14.1.1", + <%_ } -%> + <%_ if (includeE2e) { -%> + "start-server-and-test": "^1.9.1", + <%_ } -%> + "yargs": "12.0.5" }, + <%_ if (includeUnit && unitTestFramework === 'ava') { -%> + "ava": { + "files": [ + "__test__/**/*.js" + ], + "require": [ + "esm" + ] + }, + <%_ } -%> "scripts": { + <%_ if (includeUnit && unitTestFramework === "ava") { -%> + "test:unit": "ava --verbose", + "test:unit-coverage": "nyc ava", + "test:unit-watch": "ava --verbose --watch", + <%_ } -%> + <%_ if (includeUnit && unitTestFramework === "jest") { -%> + "test:unit": "jest", + "test:unit-coverage": "jest --coverage", + "test:unit-watch": "jest --watchAll", + <%_ } -%> + <%_ if (includeE2e) { -%> + "test:e2e-open": "cypress open", + "test:e2e": "start-server-and-test start http://localhost:9000 test:e2e-open", + <%_ } -%> "serve:test": "cross-env NODE_ENV=test gulp serve", "serve:dist": "cross-env NODE_ENV=production gulp serve", "start": "gulp serve", "build": "cross-env NODE_ENV=production gulp", - "test": "npm run serve:test", + <%_ if (includeE2e && !includeUnit) { -%> + "test": "npm run test:e2e", + <%_ } -%> + <%_ if (includeUnit && !includeE2e) { -%> + "test": "npm run test:unit", + <%_ } -%> + <%_ if (includeE2e && includeUnit) { -%> + "test": "npm run test:unit && npm run test:e2e", + <%_ } -%> "tasks": "gulp --tasks" }, "browserslist": [ diff --git a/app/templates/babelrc b/app/templates/babelrc index a29ac998..59ffdf46 100644 --- a/app/templates/babelrc +++ b/app/templates/babelrc @@ -1,5 +1,9 @@ { "presets": [ - "@babel/preset-env" + ["@babel/preset-env", { + "targets": { + "esmodules": true + } + }] ] -} +} \ No newline at end of file diff --git a/app/templates/demo_ava.js b/app/templates/demo_ava.js new file mode 100644 index 00000000..aafd702f --- /dev/null +++ b/app/templates/demo_ava.js @@ -0,0 +1,6 @@ +import test from 'ava'; +import { greeting } from '../app/scripts/main.js' + +test('Say Allo!', t => { + t.is(greeting(), '\'Allo \'Allo!'); +}); \ No newline at end of file diff --git a/app/templates/demo_cypress.js b/app/templates/demo_cypress.js new file mode 100644 index 00000000..50b3f2da --- /dev/null +++ b/app/templates/demo_cypress.js @@ -0,0 +1,14 @@ +describe('My First Test', function() { + beforeEach(() => { + cy.visit('http://localhost:9000') + }) + it('Should body exist', function() { + cy.get('body') + .should('be.visible') + }) + + it('Should contains title', function(){ + cy.get("h1") + .should('have.text', `'Allo, 'Allo!`) + }) + }) \ No newline at end of file diff --git a/app/templates/demo_jest.js b/app/templates/demo_jest.js new file mode 100644 index 00000000..fb481b5b --- /dev/null +++ b/app/templates/demo_jest.js @@ -0,0 +1,5 @@ +import { greeting } from '../app/scripts/main.js' + +test('Say Allo!', () => { + expect(greeting()).toBe('\'Allo \'Allo!'); +}); \ No newline at end of file diff --git a/app/templates/index.html b/app/templates/index.html index ed9664f8..3e418190 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -116,7 +116,11 @@