diff --git a/.dockerignore b/.dockerignore index fa06a985d..9f734654d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,3 +9,5 @@ docker-compose*.yml scripts/ .env + +cypress/ diff --git a/.gitignore b/.gitignore index af1dfbaa0..b743c6d12 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,6 @@ dist # TEMORIRY static/uploads + +cypress/videos +cypress/screenshots/ diff --git a/.travis.yml b/.travis.yml index 76b4b532f..12b309bae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,10 +19,17 @@ before_install: install: - docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT -t humanconnection/nitro-web . - - docker-compose up -d + - docker-compose -f docker-compose.yml up -d + - git clone --depth=50 https://github.com/Human-Connection/Nitro-Backend.git ../Nitro-Backend + - git --work-tree=../Nitro-Backend checkout $TRAVIS_BRANCH || echo "Branch \`$TRAVIS_BRANCH\` does not exist, falling back to \`master\`" + - docker-compose -f ../Nitro-Backend/docker-compose.yml up -d + - yarn global add cypress wait-on script: - docker-compose exec webapp yarn run lint + - docker-compose -f ../Nitro-Backend/docker-compose.yml exec backend yarn run db:seed > /dev/null + - wait-on http://localhost:3000 + - cypress run --record --key $CYPRESS_TOKEN after_success: - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh diff --git a/cypress.json b/cypress.json new file mode 100644 index 000000000..1f453389b --- /dev/null +++ b/cypress.json @@ -0,0 +1,3 @@ +{ + "projectId": "qa7fe2" +} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 000000000..da18d9352 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} \ No newline at end of file diff --git a/cypress/integration/login/login.spec.js b/cypress/integration/login/login.spec.js new file mode 100644 index 000000000..33054bb7d --- /dev/null +++ b/cypress/integration/login/login.spec.js @@ -0,0 +1,73 @@ +/// + +const loginTestUser = function () { + // Visiting our app before each test removes any state build up from + cy.visit('http://localhost:3000/') + .get('.layout-blank') + .should('be.visible') + + cy.location('pathname') + .should('contain', '/login') + + cy.get('input[name=email]') + .as('inputEmail') + .should('be.empty') + .and('have.attr', 'placeholder', 'Deine E-Mail') + .trigger('focus') + .type('user@example.org') + + cy.get('input[name=password]') + .as('inputPassword') + .should('be.empty') + // .and('have.attr', 'placeholder', 'Dein Passwort') + .trigger('focus') + .type('1234') + + cy.get('button[name=submit]') + .as('submitButton') + .should('be.visible') + .and('not.be.disabled') + .click() + + cy.get('@submitButton') + .should('be.disabled') + // .next('.snackbar') + + cy.get('.layout-default') + + cy.location('pathname') + .should('eq', '/') +} + +const logout = function () { + cy.visit('http://localhost:3000/logout') + + cy.location('pathname') + .should('contain', '/login') + + cy.get('.layout-blank') + .should('be.visible') +} + +context('Authentication', () => { + it('Login Testuser', loginTestUser) + + it('Login & Logout', function () { + // login + loginTestUser() + + // logout + logout() + }) + + it('Still logged in after page-reload', function () { + // login + loginTestUser() + + cy.reload() + .get('.layout-default') + + // logout + // logout() + }) +}) diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 000000000..f7ef6e6ac --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,17 @@ +// *********************************************************** +// 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) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 000000000..c1f5a772e --- /dev/null +++ b/cypress/support/commands.js @@ -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) => { ... }) diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/cypress/support/index.js @@ -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') diff --git a/package.json b/package.json index 1bc27ed94..840b5cb91 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@vue/eslint-config-prettier": "^4.0.1", - "@vue/test-utils": "^1.0.0-beta.25", + "@vue/test-utils": "^1.0.0-beta.27", "babel-eslint": "^10.0.1", "babel-jest": "^23.6.0", "babel-preset-env": "^1.7.0", @@ -61,7 +61,7 @@ "eslint-plugin-vue": "^5.0.0", "jest": "^23.6.0", "node-sass": "^4.11.0", - "nodemon": "^1.11.0", + "nodemon": "^1.18.8", "nuxt-sass-resources-loader": "^2.0.5", "prettier": "1.14.3", "sass-loader": "^7.1.0", diff --git a/yarn.lock b/yarn.lock index d300f853a..ada26d566 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1160,10 +1160,10 @@ eslint-plugin-prettier "^3.0.0" prettier "^1.15.2" -"@vue/test-utils@^1.0.0-beta.25": - version "1.0.0-beta.26" - resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.26.tgz#1ae7e1dc2bef4f49f9dbfdfecad342d17d6c5c88" - integrity sha512-2bvTgdh4Rh9NqeIrH+rah6AjXUHYxFqLO+NoOMqWXYqSvk1PGgvI5o5sT6Pty4HklIReOZxWxsMpgnJFK9rW+A== +"@vue/test-utils@^1.0.0-beta.27": + version "1.0.0-beta.27" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.27.tgz#7e5f7b7180c00e28a4ca55c0ff0a7e754377fdb2" + integrity sha512-Lzrd4ZBkS70Tl8JbXbDrN/NcSaH9aZT6+7emU3QhTJ+CrorJpyFDA1dkvSIhH+rDTs8sHFbGeXjXV/qorXxtRw== dependencies: dom-event-types "^1.0.0" lodash "^4.17.4" @@ -7268,21 +7268,21 @@ node-sass@^4.11.0: stdout-stream "^1.4.0" "true-case-path" "^1.0.2" -nodemon@^1.11.0, nodemon@^1.18.6: - version "1.18.7" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.7.tgz#716b66bf3e89ac4fcfb38a9e61887a03fc82efbb" - integrity sha512-xuC1V0F5EcEyKQ1VhHYD13owznQbUw29JKvZ8bVH7TmuvVNHvvbp9pLgE4PjTMRJVe0pJ8fGRvwR2nMiosIsPQ== +nodemon@^1.18.6, nodemon@^1.18.8: + version "1.18.8" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.8.tgz#eb4c0052dc81395bdc503f3c8ae3cba86ca7146a" + integrity sha512-CgC/JdCf+CT7Z+K6wWaV30t8GU1DPtXpr/6PuXC1/LboXCmUQNKOaz0AEMjoWDTt2AdHOBFxgv41dyC0i79SbA== dependencies: chokidar "^2.0.4" debug "^3.1.0" ignore-by-default "^1.0.1" minimatch "^3.0.4" - pstree.remy "^1.1.2" + pstree.remy "^1.1.3" semver "^5.5.0" supports-color "^5.2.0" touch "^3.1.0" undefsafe "^2.0.2" - update-notifier "^2.3.0" + update-notifier "^2.5.0" "nopt@2 || 3": version "3.0.6" @@ -8637,10 +8637,10 @@ psl@^1.1.24, psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== -pstree.remy@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.2.tgz#4448bbeb4b2af1fed242afc8dc7416a6f504951a" - integrity sha512-vL6NLxNHzkNTjGJUpMm5PLC+94/0tTlC1vkP9bdU0pOHih+EujMjgMTwfZopZvHWRFbqJ5Y73OMoau50PewDDA== +pstree.remy@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.4.tgz#a03d5dbc06ba639fb6dd4874644c4bad9882ec21" + integrity sha512-3kSyTN/iTJMxtL87idnFgTyOp2vQ6B/49QcHUO26kh2M2qahlUivFI1zWJ9FRFPoB+KgcP820JMOuIhkBJAP3Q== public-encrypt@^4.0.0: version "4.0.3" @@ -10314,7 +10314,7 @@ upath@^1.0.5, upath@^1.1.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== -update-notifier@^2.3.0: +update-notifier@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==