Skip to content

Commit

Permalink
feat(test): Add Cypress integration test runner
Browse files Browse the repository at this point in the history
Introduce Cypress for e2e testing.

closes #943
  • Loading branch information
michaelw85 committed Feb 7, 2019
1 parent 1455a35 commit cabe6ce
Show file tree
Hide file tree
Showing 21 changed files with 299 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

module.exports = function(project) {
require('../../general/integration-test-runner/cypress')(project);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';
const ProjectItem = require('../../../../../project-item').ProjectItem;

module.exports = function(project) {
const cypressResourceFolder = 'test/cypress';
const isUsingTypescript = project.model.transpiler.id === 'typescript';

if (isUsingTypescript) {
project.addToDevDependencies(
'@cypress/webpack-preprocessor'
);
}

const testDirResources = [
ProjectItem.directory('fixtures').add(
ProjectItem.resource('example.json', `${cypressResourceFolder}/fixtures/example.json`)
),
ProjectItem.directory('integration').add(
ProjectItem.resource('app.e2e.ext', `${cypressResourceFolder}/integration/app.e2e.ext`, project.model.transpiler)
),
ProjectItem.directory('plugins').add(
ProjectItem.resource('index.js', `${cypressResourceFolder}/plugins/index.ext`, project.model.transpiler)
),
ProjectItem.directory('screenshots'),
ProjectItem.directory('support').add(
ProjectItem.resource('index.js', `${cypressResourceFolder}/support/index.js`),
ProjectItem.resource('commands.ext', `${cypressResourceFolder}/support/commands.ext`, project.model.transpiler)
),
ProjectItem.directory('videos')
];

if (isUsingTypescript) {
testDirResources.push(ProjectItem.resource('tsconfig.json', `${cypressResourceFolder}/tsconfig.json`));
}

project.addToTasks(
ProjectItem.resource('cypress.ext', 'tasks/cypress.ext', project.model.transpiler),
ProjectItem.resource('cypress.json', 'tasks/cypress.json')
).addToDevDependencies(
'cypress'
).addToContent(
ProjectItem.resource('cypress.json', 'content/cypress.json'),
project.tests.add(
project.e2eTests.add(...testDirResources)
)
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

module.exports = function(project) {
require('../../general/integration-test-runner/cypress')(project);
};
8 changes: 8 additions & 0 deletions lib/commands/new/new-application.json
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,14 @@
"id": "protractor",
"displayName": "Protractor"
}
},
{
"displayName": "Cypress",
"description": "Configure your app with Cypress",
"value": {
"id": "cypress",
"displayName": "Cypress"
}
}
]
},
Expand Down
4 changes: 3 additions & 1 deletion lib/dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"copy-webpack-plugin": "^4.5.2",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"@cypress/webpack-preprocessor": "^4.0.3",
"cypress": "^3.1.5",
"debounce": "^1.2.0",
"del": "^3.0.0",
"duplicate-package-checker-webpack-plugin": "^3.0.0",
Expand Down Expand Up @@ -103,4 +105,4 @@
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9",
"webpack-hot-middleware": "^2.24.3"
}
}
32 changes: 8 additions & 24 deletions lib/package-managers/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,18 @@ exports.NPM = class {
this.executableName = 'npm';
}

install(packages, workingDirectory) {
if (!workingDirectory) workingDirectory = process.cwd();

install(packages = [], workingDirectory = process.cwd()) {
return new Promise((resolve, reject) => {
let executablePath = this.getExecutablePath(workingDirectory);
let cmd = this.installCommand(executablePath, packages);

let installProcess = childProcess.exec(cmd, {cwd: workingDirectory}, (error, stdout, stderr) => {
if (error) {
reject(error);
return;
}

resolve();
});

installProcess.stdout.on('data', data => console.log(data));
childProcess.spawn(
this.getExecutablePath(workingDirectory),
['install', ...packages],
{ stdio: 'inherit', cwd: workingDirectory }
)
.on('close', () => resolve())
.on('error', error => reject(error));
});
}

installCommand(executablePath, packages) {
let cmd = `"${executablePath}" install`;
if (packages && packages.length > 0) {
cmd += ` ${packages.join(' ')}`;
}
return cmd;
}

getExecutablePath(directory) {
try {
return npmWhich(directory).sync(this.executableName);
Expand Down
9 changes: 0 additions & 9 deletions lib/package-managers/yarn.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,11 @@

const npm = require('./npm').default;


exports.Yarn = class extends npm {
constructor() {
super();
this.executableName = 'yarn';
}

installCommand(executablePath, packages) {
let cmd = `"${executablePath}"`;
if (packages && packages.length > 0) {
cmd += ` add ${packages.join(' ')}`;
}
return cmd;
}
};

exports.default = exports.Yarn;
9 changes: 9 additions & 0 deletions lib/resources/content/cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"baseUrl": "http://localhost:8080",
"fixturesFolder": "test/e2e/fixtures",
"integrationFolder": "test/e2e/integration",
"pluginsFile": "test/e2e/plugins/index.js",
"screenshotsFolder": "test/e2e/screenshots",
"supportFile": "test/e2e/support/index.js",
"videosFolder": "test/e2e/videos"
}
13 changes: 11 additions & 2 deletions lib/resources/content/tsconfig.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
"experimentalDecorators": true,
"allowJs": true,
"moduleResolution": "node",
"lib": ["es2017", "dom"],
"lib": [
"es2017",
"dom"
],
"baseUrl": "src"
// @endif
// @if bundler.id='webpack'
Expand All @@ -27,7 +30,8 @@
"baseUrl": "src",
"skipLibCheck": true,
"lib": [
"es2017", "dom"
"es2017",
"dom"
]
// @endif
},
Expand All @@ -36,6 +40,11 @@
"./test/**/*.ts",
"./custom_typings/**/*.d.ts"
],
// @if integrationTestRunner.id='cypress' && transpiler.id='typescript'
"exclude": [
"./test/e2e/**/*.ts"
],
// @endif
"atom": {
"rewriteTsconfig": false
}
Expand Down
10 changes: 10 additions & 0 deletions lib/resources/tasks/cypress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import cypress from 'cypress';
import { CLIOptions } from 'aurelia-cli';

export default () => {
if (CLIOptions.hasFlag('run')) {
cypress.run();
} else {
cypress.open();
}
}
11 changes: 11 additions & 0 deletions lib/resources/tasks/cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "cypress",
"description": "Open Cypress to start developing tests. Start the application before running this task.",
"flags": [
{
"name": "run",
"description": "Perfom a testrun and reports the results.",
"type": "boolean"
}
]
}
10 changes: 10 additions & 0 deletions lib/resources/tasks/cypress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as cypress from 'cypress';
import { CLIOptions } from 'aurelia-cli';

export default () => {
if (CLIOptions.hasFlag('run')) {
cypress.run();
} else {
cypress.open();
}
}
5 changes: 5 additions & 0 deletions lib/resources/test/cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "[email protected]",
"body": "Fixtures are a great way to mock data for responses to routes"
}
13 changes: 13 additions & 0 deletions lib/resources/test/cypress/integration/app.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe('Aurelia skeleton app', () => {
beforeEach(() => {
cy.visit('/');
});

it('should load the page and display the initial page title', () => {
cy.title().should('equal', 'Aurelia Navigation Skeleton');
});

it('should display greeting', () => {
cy.get('h1').contains('Hello World!');
});
});
13 changes: 13 additions & 0 deletions lib/resources/test/cypress/integration/app.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe('Aurelia skeleton app', () => {
beforeEach(() => {
cy.visit('/');
});

it('should load the page and display the initial page title', () => {
cy.title().should('equal', 'Aurelia Navigation Skeleton');
});

it('should display greeting', () => {
cy.get('h1').contains('Hello World!');
});
});
20 changes: 20 additions & 0 deletions lib/resources/test/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

module.exports = (on, config) => {

// bind to the event we care about
on('<event>', (arg1, arg2) => {
// plugin stuff here
})
}
34 changes: 34 additions & 0 deletions lib/resources/test/cypress/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

const wp = require('@cypress/webpack-preprocessor')

module.exports = (on) => {
const options = {
webpackOptions: {
resolve: {
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
options: { transpileOnly: true }
}
]
}
},
}
on('file:preprocessor', wp(options))
}
25 changes: 25 additions & 0 deletions lib/resources/test/cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
25 changes: 25 additions & 0 deletions lib/resources/test/cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
20 changes: 20 additions & 0 deletions lib/resources/test/cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
Loading

0 comments on commit cabe6ce

Please sign in to comment.