diff --git a/cypress/integration/Authentication.feature b/cypress/integration/Authentication.feature deleted file mode 100644 index 271c85152..000000000 --- a/cypress/integration/Authentication.feature +++ /dev/null @@ -1,24 +0,0 @@ -Feature: Authentication - As an user - I want to sign in - In order to be able to posts and do other contributions as myself - Furthermore I want to be able to stay logged in and logout again - - Background: - Given I have an user account - - Scenario: Log in - When I navigate to page "login" - And I fill in my credentials - And I click on "submit button" - Then I am logged in as "Peter Pan" - - Scenario: Refresh and stay logged in - Given I am logged in - When I refresh the page - Then I am logged in as "Peter Pan" - - Scenario: Log out - Given I am logged in - When I log out - Then I am on page "login" diff --git a/cypress/integration/PersistentLinks.feature b/cypress/integration/PersistentLinks.feature index 3b12b902f..89f9d9654 100644 --- a/cypress/integration/PersistentLinks.feature +++ b/cypress/integration/PersistentLinks.feature @@ -9,14 +9,14 @@ Feature: Persistent Links | Name | yes | no | no | Search, self-description | Background: - Given I have an user account - And I am logged in - And the following "users" are in the database: - | id | name | slug | - | MHNqce98y1 | Stephen Hawking | thehawk | + Given the following "users" are in the database: + | slug | email | password | id | name | termsAndConditionsAgreedVersion | + | thehawk | hawk@example.org | abcd | MHNqce98y1 | Stephen Hawking | 0.0.4 | + | narrator | narrator@example.org | 1234 | narrator | Nathan Narrator | 0.0.4 | And the following "posts" are in the database: | id | title | slug | | bWBjpkTKZp | 101 Essays that will change the way you think | 101-essays | + And I am logged in as "narrator" Scenario Outline: Link with healable information is valid and gets auto-completed When I navigate to page "" diff --git a/cypress/integration/Post.Comment.feature b/cypress/integration/Post.Comment.feature index adfc9f358..6eb5f52bb 100644 --- a/cypress/integration/Post.Comment.feature +++ b/cypress/integration/Post.Comment.feature @@ -4,14 +4,17 @@ Feature: Comments on post To be able to express my thoughts and emotions about these, discuss, and add give further information. Background: - Given I have an user account - And I am logged in + Given the following "users" are in the database: + | slug | email | password | id | name | termsAndConditionsAgreedVersion | + | peter-pan| peter@pan.com | abcd | id-of-peter-pan| Peter Pan | 0.0.4 | + | narrator | narrator@example.org | 1234 | narrator | Nathan Narrator | 0.0.4 | And the following "posts" are in the database: | id | title | slug | authorId | | bWBjpkTKZp | 101 Essays that will change the way you think | 101-essays | id-of-peter-pan | And the following "comments" are in the database: | postId | content | authorId | | bWBjpkTKZp | @peter-pan reply to me | id-of-peter-pan | + And I am logged in as "narrator" Scenario: Comment creation Given I navigate to page "post/bWBjpkTKZp/101-essays" diff --git a/cypress/integration/Post.Create.feature b/cypress/integration/Post.Create.feature index 76742fffb..e8d3947f2 100644 --- a/cypress/integration/Post.Create.feature +++ b/cypress/integration/Post.Create.feature @@ -4,8 +4,10 @@ Feature: Create a post To say something to everyone in the community Background: - Given I have an user account - And I am logged in + Given the following "users" are in the database: + | slug | email | password | id | name | termsAndConditionsAgreedVersion | + | narrator | narrator@example.org | 1234 | narrator | Nathan Narrator | 0.0.4 | + And I am logged in as "narrator" And I navigate to page "landing" Scenario: Create a post diff --git a/cypress/integration/Post.Images.feature b/cypress/integration/Post.Images.feature index 0e734989a..d00f5f9f9 100644 --- a/cypress/integration/Post.Images.feature +++ b/cypress/integration/Post.Images.feature @@ -4,11 +4,13 @@ Feature: Upload/Delete images on posts So that I can personalize my posts Background: - Given I have an user account - And I am logged in + Given the following "users" are in the database: + | slug | email | password | id | name | termsAndConditionsAgreedVersion | + | narrator | narrator@example.org | 1234 | narrator | Nathan Narrator | 0.0.4 | And the following "posts" are in the database: - | authorId | id | title | content | - | id-of-peter-pan | p1 | Post to be updated | successfully updated | + | authorId | id | title | content | + | narrator | p1 | Post to be updated | successfully updated | + And I am logged in as "narrator" And I navigate to page "landing" Scenario: Create a Post with a Teaser Image @@ -17,6 +19,7 @@ Feature: Upload/Delete images on posts And I add all required fields And I click on "save button" Then I am on page ".../new-post" + And I wait for 750 milliseconds And the post was saved successfully with the "new" teaser image Scenario: Update a Post to add an image @@ -25,6 +28,7 @@ Feature: Upload/Delete images on posts And I click on "save button" Then I see a toaster with "Saved!" And I am on page ".../post-to-be-updated" + And I wait for 750 milliseconds Then the post was saved successfully with the "updated" teaser image Scenario: Add image, then add a different image @@ -40,6 +44,7 @@ Feature: Upload/Delete images on posts And I add all required fields And I click on "save button" Then I am on page ".../new-post" + And I wait for 750 milliseconds And the "new" post was saved successfully without a teaser image Scenario: Delete existing image @@ -48,4 +53,5 @@ Feature: Upload/Delete images on posts Then I should be able to remove the image And I click on "save button" Then I am on page ".../post-to-be-updated" + And I wait for 750 milliseconds And the "updated" post was saved successfully without a teaser image \ No newline at end of file diff --git a/cypress/integration/Post.feature b/cypress/integration/Post.feature index bec4b67c7..a02398714 100644 --- a/cypress/integration/Post.feature +++ b/cypress/integration/Post.feature @@ -4,11 +4,14 @@ Feature: See a post And to see the whole content of it Background: - Given I have an user account - And I am logged in + Given the following "users" are in the database: + | slug | email | password | id | name | termsAndConditionsAgreedVersion | + | peter-pan| peter@pan.com | abcd | id-of-peter-pan| Peter Pan | 0.0.4 | + | narrator | narrator@example.org | 1234 | narrator | Nathan Narrator | 0.0.4 | And the following "posts" are in the database: | id | title | slug | authorId | content | | aBcDeFgHiJ | previously created post | previously-created-post | id-of-peter-pan | with some content | + And I am logged in as "narrator" Scenario: See a post on the landing page When I navigate to page "landing" diff --git a/cypress/integration/User.Authentication.feature b/cypress/integration/User.Authentication.feature new file mode 100644 index 000000000..aaa7e1415 --- /dev/null +++ b/cypress/integration/User.Authentication.feature @@ -0,0 +1,26 @@ +Feature: User authentication + As an user + I want to sign in + In order to be able to posts and do other contributions as myself + Furthermore I want to be able to stay logged in and logout again + + Background: + Given the following "users" are in the database: + | email | password | id | name | slug | termsAndConditionsAgreedVersion | + | peterpan@example.org | 1234 | id-of-peter-pan | Peter Pan | peter-pan | 0.0.4 | + + Scenario: Log in + When I navigate to page "login" + And I fill in my credentials "peterpan@example.org" "1234" + And I click on "submit button" + Then I am logged in with username "Peter Pan" + + Scenario: Refresh and stay logged in + Given I am logged in as "peter-pan" + When I refresh the page + Then I am logged in with username "Peter Pan" + + Scenario: Log out + Given I am logged in as "peter-pan" + When I log out + Then I am on page "login" diff --git a/cypress/integration/Authentication/I_am_logged_in_as_{string}.js b/cypress/integration/User.Authentication/I_am_logged_in_with_username_{string}.js similarity index 57% rename from cypress/integration/Authentication/I_am_logged_in_as_{string}.js rename to cypress/integration/User.Authentication/I_am_logged_in_with_username_{string}.js index c516fbb92..4383282bd 100644 --- a/cypress/integration/Authentication/I_am_logged_in_as_{string}.js +++ b/cypress/integration/User.Authentication/I_am_logged_in_with_username_{string}.js @@ -1,6 +1,7 @@ import { Then } from "cypress-cucumber-preprocessor/steps"; -Then("I am logged in as {string}", name => { +Then("I am logged in with username {string}", name => { cy.get(".avatar-menu").click(); cy.get(".avatar-menu-popover").contains(name); + cy.get(".avatar-menu").click(); // Close menu again }); \ No newline at end of file diff --git a/cypress/integration/Authentication/I_refresh_the_page.js b/cypress/integration/User.Authentication/I_refresh_the_page.js similarity index 100% rename from cypress/integration/Authentication/I_refresh_the_page.js rename to cypress/integration/User.Authentication/I_refresh_the_page.js diff --git a/cypress/integration/User.ChangePassword.feature b/cypress/integration/User.ChangePassword.feature new file mode 100644 index 000000000..5e275c1df --- /dev/null +++ b/cypress/integration/User.ChangePassword.feature @@ -0,0 +1,55 @@ +Feature: User change password + As a user + I want to change my password in my settings + For security, e.g. if I exposed my password by accident + + Login via email and password is a well-known authentication procedure and you + can assure to the server that you are who you claim to be. Either if you + exposed your password by acccident and you want to invalidate the exposed + password or just out of an good habit, you want to change your password. + + Background: + Given the following "users" are in the database: + | email | password | id | name | slug | termsAndConditionsAgreedVersion | + | peterpan@example.org | exposed | id-of-peter-pan | Peter Pan | peter-pan | 0.0.4 | + And I am logged in as "peter-pan" + And I navigate to page "settings" + And I click on "security menu" + + Scenario: Incorrect Old Password + When I fill the password form with: + | Your old password | incorrect | + | Your new password | secure | + | Confirm new password | secure | + And I submit the form + And I see a "failure toaster" message: + """ + Old password is not correct + """ + + Scenario: Incorrect Password Repeat + When I fill the password form with: + | Your old password | exposed | + | Your new password | secure | + | Confirm new password | eruces | + And I cannot submit the form + + Scenario: Change my password + Given I navigate to page "settings" + And I click on "security menu" + When I fill the password form with: + | Your old password | exposed | + | Your new password | secure | + | Confirm new password | secure | + And I submit the form + And I see a "success toaster" message: + """ + Password successfully changed! + """ + And I log out + Then I fill in my credentials "peterpan@example.org" "exposed" + And I click on "submit button" + And I cannot login anymore + But I fill in my credentials "peterpan@example.org" "secure" + And I click on "submit button" + And I can login successfully diff --git a/cypress/integration/User.ChangePassword/I_can_login_successfully.js b/cypress/integration/User.ChangePassword/I_can_login_successfully.js new file mode 100644 index 000000000..d1a62cc4d --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_can_login_successfully.js @@ -0,0 +1,7 @@ +import { Then } from "cypress-cucumber-preprocessor/steps"; + +Then("I can login successfully", () => { + // cy.reload(); + cy.get(".iziToast-wrapper") + .should("contain", "You are logged in!"); +}); \ No newline at end of file diff --git a/cypress/integration/User.ChangePassword/I_cannot_login_anymore.js b/cypress/integration/User.ChangePassword/I_cannot_login_anymore.js new file mode 100644 index 000000000..ff381d891 --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_cannot_login_anymore.js @@ -0,0 +1,7 @@ +import { Then } from "cypress-cucumber-preprocessor/steps"; + +Then("I cannot login anymore", password => { + //cy.reload(); + cy.get(".iziToast-wrapper") + .should("contain", "Incorrect email address or password."); +}); \ No newline at end of file diff --git a/cypress/integration/User.ChangePassword/I_cannot_submit_the_form.js b/cypress/integration/User.ChangePassword/I_cannot_submit_the_form.js new file mode 100644 index 000000000..657d38bd8 --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_cannot_submit_the_form.js @@ -0,0 +1,6 @@ +import { When } from "cypress-cucumber-preprocessor/steps"; + +When("I cannot submit the form", () => { + cy.get("button[type=submit]") + .should('be.disabled'); +}); \ No newline at end of file diff --git a/cypress/integration/User.ChangePassword/I_fill_the_password_form_with.js b/cypress/integration/User.ChangePassword/I_fill_the_password_form_with.js new file mode 100644 index 000000000..69345ecc6 --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_fill_the_password_form_with.js @@ -0,0 +1,11 @@ +import { When } from "cypress-cucumber-preprocessor/steps"; + +When("I fill the password form with:", table => { + table = table.rowsHash(); + cy.get("input[id=oldPassword]") + .type(table["Your old password"]) + .get("input[id=password]") + .type(table["Your new password"]) + .get("input[id=passwordConfirmation]") + .type(table["Confirm new password"]); +}); \ No newline at end of file diff --git a/cypress/integration/User.ChangePassword/I_see_a_{string}_message.js b/cypress/integration/User.ChangePassword/I_see_a_{string}_message.js new file mode 100644 index 000000000..90ddf0bd3 --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_see_a_{string}_message.js @@ -0,0 +1,5 @@ +import { Then } from "cypress-cucumber-preprocessor/steps"; + +Then("I see a {string} message:", (type, message) => { + cy.contains(message); +}); \ No newline at end of file diff --git a/cypress/integration/User.ChangePassword/I_submit_the_form copy.js b/cypress/integration/User.ChangePassword/I_submit_the_form copy.js new file mode 100644 index 000000000..18349cff8 --- /dev/null +++ b/cypress/integration/User.ChangePassword/I_submit_the_form copy.js @@ -0,0 +1,5 @@ +import { When } from "cypress-cucumber-preprocessor/steps"; + +When("I submit the form", () => { + cy.get("form").submit(); +}); \ No newline at end of file diff --git a/cypress/integration/common/.steps.js b/cypress/integration/common/.steps.js index 85415da67..a59082b1b 100644 --- a/cypress/integration/common/.steps.js +++ b/cypress/integration/common/.steps.js @@ -88,7 +88,7 @@ Given("my user account has the role {string}", role => { cy.factory().build("user", { role, ...termsAndConditionsAgreedVersion, - }, loginCredentials); + }, /*loginCredentials*/ 'TODO'); }); When("I log out", cy.logout); @@ -157,10 +157,6 @@ Given("we have the following posts in our database:", table => { }) }) -Then("I see a success message:", message => { - cy.contains(message); -}); - When("I click on the avatar menu in the top right corner", () => { cy.get(".avatar-menu").click(); }); @@ -189,52 +185,6 @@ Then( } ); -Given("I am logged in with these credentials:", table => { - loginCredentials = table.hashes()[0]; - cy.factory().build("user", { - ...termsAndConditionsAgreedVersion, - name: loginCredentials.email, - }, loginCredentials); - cy.neode() - .first("User", { - name: loginCredentials.email, - }) - .then(user => { - return new Cypress.Promise((resolve, reject) => { - return user.toJson().then((user) => resolve(user)) - }) - }) - .then(user => cy.login(user)) -}); - -When("I fill the password form with:", table => { - table = table.rowsHash(); - cy.get("input[id=oldPassword]") - .type(table["Your old password"]) - .get("input[id=password]") - .type(table["Your new passsword"]) - .get("input[id=passwordConfirmation]") - .type(table["Confirm new password"]); -}); - -When("submit the form", () => { - cy.get("form").submit(); -}); - -Then("I cannot login anymore with password {string}", password => { - cy.reload(); - const { email } = loginCredentials - cy.manualLogin({ email, password }) - .get(".iziToast-wrapper").should("contain", "Incorrect email address or password."); -}); - -Then("I can login successfully with password {string}", password => { - cy.reload(); - const { email } = loginCredentials - cy.manualLogin({ email, password }) - .get(".iziToast-wrapper").should("contain", "You are logged in!"); -}); - When("open the notification menu and click on the first item", () => { cy.get(".notifications-menu").invoke('show').click(); // "invoke('show')" because of the delay for show the menu cy.get(".notification .link") diff --git a/cypress/integration/common/I_am_logged_in.js b/cypress/integration/common/I_am_logged_in.js deleted file mode 100644 index e0412971d..000000000 --- a/cypress/integration/common/I_am_logged_in.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Given } from "cypress-cucumber-preprocessor/steps"; -import narrator from "../data/narrator"; - -Given("I am logged in", () => { - cy.neode() - .first("User", { name: narrator.name }) - .then(user => { - return new Cypress.Promise((resolve, reject) => { - return user.toJson().then((user) => resolve(user)) - }) - }) - .then(user => cy.login(user)) -}); \ No newline at end of file diff --git a/cypress/integration/common/I_am_logged_in_as_{string}.js b/cypress/integration/common/I_am_logged_in_as_{string}.js new file mode 100644 index 000000000..96d1c28ab --- /dev/null +++ b/cypress/integration/common/I_am_logged_in_as_{string}.js @@ -0,0 +1,18 @@ +import { Given } from "cypress-cucumber-preprocessor/steps"; +import encode from '../../../backend/src/jwt/encode' + +Given("I am logged in as {string}", slug => { + cy.neode() + .first("User", { slug }) + .then(user => { + return new Cypress.Promise((resolve, reject) => { + if(!user) { + return reject(`User ${email} not found in database`) + } + return user.toJson().then((user) => resolve(user)) + }) + }) + .then(user => { + cy.setCookie('ocelot-social-token', encode(user)) + }) +}); \ No newline at end of file diff --git a/cypress/integration/common/I_click_on_{string}.js b/cypress/integration/common/I_click_on_{string}.js index 50e864c29..a1cd16bd6 100644 --- a/cypress/integration/common/I_click_on_{string}.js +++ b/cypress/integration/common/I_click_on_{string}.js @@ -8,6 +8,7 @@ When("I click on {string}", element => { 'the first post': '.post-teaser:first-child', 'comment button': 'button[type=submit]', 'reply button': '.reply-button', + 'security menu': 'a[href="/settings/security"]', } cy.get(elementSelectors[element]) diff --git a/cypress/integration/common/I_fill_in_my_credentials_{string}_{string}.js b/cypress/integration/common/I_fill_in_my_credentials_{string}_{string}.js new file mode 100644 index 000000000..e2227f454 --- /dev/null +++ b/cypress/integration/common/I_fill_in_my_credentials_{string}_{string}.js @@ -0,0 +1,12 @@ +import { When } from "cypress-cucumber-preprocessor/steps"; + +When("I fill in my credentials {string} {string}", (email,password) => { + cy.get("input[name=email]") + .trigger("focus") + .type('{selectall}{backspace}') + .type(email) + .get("input[name=password]") + .trigger("focus") + .type('{selectall}{backspace}') + .type(password); +}); \ No newline at end of file diff --git a/cypress/integration/common/I_have_an_user_account.js b/cypress/integration/common/I_have_an_user_account.js deleted file mode 100644 index 776a7752c..000000000 --- a/cypress/integration/common/I_have_an_user_account.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Given } from "cypress-cucumber-preprocessor/steps"; -import narrator from '../data/narrator' -import loginCredentials from '../data/loginCredentials' - -Given("I have an user account", () => { - cy.factory().build("user", narrator, loginCredentials); -}); \ No newline at end of file diff --git a/cypress/integration/Authentication/I_log_out.js b/cypress/integration/common/I_log_out.js similarity index 81% rename from cypress/integration/Authentication/I_log_out.js rename to cypress/integration/common/I_log_out.js index bc3d7e64c..51605f17e 100644 --- a/cypress/integration/Authentication/I_log_out.js +++ b/cypress/integration/common/I_log_out.js @@ -1,7 +1,8 @@ import { When } from "cypress-cucumber-preprocessor/steps"; When("I log out", () => { - // cy.get(".avatar-menu").click(); + cy.get(".avatar-menu") + .click(); cy.get(".avatar-menu-popover") .find('a[href="/logout"]') .click(); diff --git a/cypress/integration/data/loginCredentials.js b/cypress/integration/data/loginCredentials.js deleted file mode 100644 index 939295511..000000000 --- a/cypress/integration/data/loginCredentials.js +++ /dev/null @@ -1,6 +0,0 @@ -const loginCredentials = { - email: "peterpan@example.org", - password: "1234" -} - -export default loginCredentials diff --git a/cypress/integration/data/narrator.js b/cypress/integration/data/narrator.js deleted file mode 100644 index 7bf74099a..000000000 --- a/cypress/integration/data/narrator.js +++ /dev/null @@ -1,8 +0,0 @@ -const narrator = { - id: 'id-of-peter-pan', - name: "Peter Pan", - slug: "peter-pan", - termsAndConditionsAgreedVersion: '0.0.4', -} - -export default narrator diff --git a/cypress/support/commands.js b/cypress/support/commands.js index a1e3ebc2a..eb91b800f 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -18,7 +18,6 @@ import helpers from "./helpers"; import { GraphQLClient, request } from 'graphql-request' import { gql } from '../../backend/src/helpers/jest' import config from '../../backend/src/config' -import encode from '../../backend/src/jwt/encode' const switchLang = name => { cy.get(".locale-menu").click(); @@ -51,24 +50,6 @@ Cypress.Commands.add("switchLanguage", (name, force) => { } }); -Cypress.Commands.add("login", user => { - const token = encode(user) - cy.setCookie('ocelot-social-token', token) -}); - -/*Cypress.Commands.add("manualLogin", ({ email, password }) => { - cy.visit(`/login`) - .get("input[name=email]") - .trigger("focus") - .type(email) - .get("input[name=password]") - .trigger("focus") - .type(password) - .get("button[name=submit]") - .as("submitButton") - .click(); -});*/ - Cypress.Commands.add("logout", () => { cy.visit(`/logout`); cy.location("pathname").should("contain", "/login"); // we're out