diff --git a/cypress/CICD_Info.md b/cypress/CICD_Info.md new file mode 100644 index 000000000..217b79be1 --- /dev/null +++ b/cypress/CICD_Info.md @@ -0,0 +1,34 @@ +# CI/CD Pipeline Information + +This project utilises Cypress, Github Actions and Cypress Cloud. + +- Cypress is used to run the integration tests, including some end-to-end testing. + +- Github Actions runs these tests on every successful pull request. + +- Cypress Cloud stores the test data and allows for tracking and analytics in our bug reporting. + +At the moment, the project is not deployed in production, We aim to implement continuos development once this has been achieved. + + +## Pipeline steps: + +1. A pull request is made and successfully merged with main branch. +2. Github Actions triggers and installs Node.js. +3. Github Actions installs a MongoDB, installs the project dependencies and makes a build. +4. Unit tests are run using Jest. +5. The test server starts and Cypress begins its test run. +6. The Cypress test begins by attempting a signup and creating an admin profile, which is then used for later tests. +7. At the end of the tests, the test database is dropped. +8The test run completes and test data is stored in Cypress Cloud for analysis. + +At this point we aim to implement the automatic deployment to Render. + +## Test Scope + +As written in the test plan, we aim for the Cypress Integration tests to have total coverage of functionality, +as well as some coverage for performance if we have time. + +We utilise random data generation for login, as well as + + diff --git a/cypress/integration/user_can_create_post.js b/cypress/integration/user_can_create_post.js deleted file mode 100644 index 4b6f73cac..000000000 --- a/cypress/integration/user_can_create_post.js +++ /dev/null @@ -1,28 +0,0 @@ -// Feature: Posts Page - -// As a logged-in user, -// I want to be able to see posts, See comments on posts, and number of likes, So that I can connect with friends. - - - -describe("User can create a post", () => { - it("A signed in user can create a post and see it displayed", () => { - - - // sign in - cy.visit("/"); - cy.get('a.global-button[href="/sessions/new"]').click() - cy.get("#email").type("admin@example.com"); - cy.get("#password").type("Password!123"); - cy.get("#submit").click(); - - cy.url().should("include", "/posts"); - - cy.contains("New post").click(); - - cy.get("#new-post-form").find('[type="text"]').type("Hello, world!"); - cy.get("#new-post-form").submit(); - - cy.get(".posts").should("contain", "Hello, world!"); - }); - }); \ No newline at end of file diff --git a/cypress/integration/user_can_login.js b/cypress/integration/user_can_login.js index 18c3e5613..1d5d8299a 100644 --- a/cypress/integration/user_can_login.js +++ b/cypress/integration/user_can_login.js @@ -6,18 +6,36 @@ // And be able to enter my account details, So that I can be taken to my homepage -describe("Login - this test fails without an admin user", () => { +describe("Login", () => { + + it("A user signs in and is redirected to /posts", () => { + // sign in + cy.signIn(); + cy.url().should("include", "/posts"); + + }); + + + + + it("A user attempts to sign in with incorrect details", () => { + // sign in cy.visit("/"); - cy.get('a.global-button[href="/sessions/new"]').click() - cy.get("#email").type("admin@example.com"); + cy.get('a.global-button[href="/sessions/new"]').click(); + cy.get("#email").type("wrongemail@example.com"); cy.get("#password").type("Password!123"); cy.get("#submit").click(); - - cy.url().should("include", "/posts"); + + cy.url().should("not.include", "/posts"); }); + + + + + }); \ No newline at end of file diff --git a/cypress/integration/user_can_logout.js b/cypress/integration/user_can_logout.js index a4064fdc1..57259b209 100644 --- a/cypress/integration/user_can_logout.js +++ b/cypress/integration/user_can_logout.js @@ -9,16 +9,13 @@ describe("Logout", () => { // sign in - cy.visit("/"); - cy.get('a.global-button[href="/sessions/new"]').click() - cy.get("#email").type("admin@example.com"); - cy.get("#password").type("Password!123"); - cy.get("#submit").click(); + cy.signIn(); cy.url().should("include", "/posts"); - cy.get("#logout").click(); + cy.get('input[type="submit"][value="Log Out"].global-button.logout').click(); + cy.url().should("not.include", "/posts"); }); diff --git a/cypress/integration/user_can_see_and_create_post.js b/cypress/integration/user_can_see_and_create_post.js new file mode 100644 index 000000000..ec8e4c052 --- /dev/null +++ b/cypress/integration/user_can_see_and_create_post.js @@ -0,0 +1,71 @@ +// Feature: Posts Page + +// As a logged-in user, +// I want to be able to see posts, See comments on posts, and number of likes, So that I can connect with friends. + + + +describe("Posts", () => { + + + + + it("A signed in user can create a post and see it displayed", () => { + + + // sign in + cy.signIn(); + + cy.url().should("include", "/posts"); + + //create a new post + cy.get('a.global-button.new-post-link[href="/posts/new"]').click(); + cy.get('#message').type('Hello, World!'); + cy.get('input[type="submit"][value="Submit"]').click(); + + cy.get(".posts").should("contain", "Hello, world!"); + }); + + + + + + it("A signed in user cannot create an empty post", () => { + + + // sign in + cy.signIn(); + + cy.url().should("include", "/posts"); + + cy.get('a.global-button.new-post-link[href="/posts/new"]').click(); + + //submit without typing anything + cy.get('input[type="submit"][value="Submit"]').click(); + + //should not take you back to posts at this point + cy.url().should("not.include", "/posts"); + }); + + + + + + + + it("A signed in user can see the like count on a post", () => { + + + // sign in + cy.signIn(); + + cy.url().should("include", "/posts"); + + cy.get('ul.posts li').should('contain', '0 Likes'); + + }); + + + + + }); \ No newline at end of file diff --git a/cypress/integration/user_can_see_posts.js b/cypress/integration/user_can_see_posts.js deleted file mode 100644 index 128fa0cda..000000000 --- a/cypress/integration/user_can_see_posts.js +++ /dev/null @@ -1,28 +0,0 @@ -// Feature: Posts Page - -// As a logged-in user, -// I want to be able to see posts, See comments on posts, and number of likes, So that I can connect with friends. - - - -describe("User can see posts", () => { - it("A user signs in and can see a post on their homepage", () => { - - - // sign in - cy.visit("/"); - cy.get('a.global-button[href="/sessions/new"]').click() - cy.get("#email").type("admin@example.com"); - cy.get("#password").type("Password!123"); - cy.get("#submit").click(); - - cy.url().should("include", "/posts"); - - cy.contains("New post").click(); - - cy.get("#new-post-form").find('[type="text"]').type("Hello, world!"); - cy.get("#new-post-form").submit(); - - cy.get(".posts").should("contain", "Hello, world!"); - }); - }); \ No newline at end of file diff --git a/cypress/integration/user_can_see_posts_count_on_post.js b/cypress/integration/user_can_see_posts_count_on_post.js deleted file mode 100644 index f86f72655..000000000 --- a/cypress/integration/user_can_see_posts_count_on_post.js +++ /dev/null @@ -1,33 +0,0 @@ -//THIS TEST NEEDS DEVELOPMENT - UNSURE WHAT POSTS?LIKES COUNT WILL LOOK LIKE IN FINAL PROJECT - - - -describe("Timeline", () => { - it("can see likes count on a new post", () => { - - - cy.visit("/users/new"); - cy.get("#email").type("john@example.com"); - cy.get("#password").type("password!123"); - cy.get("#confirm-password").type("password!123"); - cy.get("#first-name").type("John") - cy.get("#last-name").type("Doe") - cy.get("#submit").click(); - cy.get("#email").type("john@example.com"); - cy.get("#password").type("password!123"); - cy.get("#submit").click(); - - // submit a post - cy.visit("/posts"); - cy.contains("New post").click(); - - cy.get("#new-post-form").find('[type="text"]').type("Hello, world!"); - cy.get("#new-post-form").submit(); - - cy.get(".posts").should("contain", "Hello, world!"); - - // Assert that we can see the likes count - cy.get(".posts").should("contain", "0 likes"); - }); - }); - diff --git a/cypress/integration/user_can_sign_up_spec.js b/cypress/integration/user_can_sign_up_spec.js index 895c430d4..cc53eeac0 100644 --- a/cypress/integration/user_can_sign_up_spec.js +++ b/cypress/integration/user_can_sign_up_spec.js @@ -16,6 +16,8 @@ const chance = new Chance(); describe("Signup", () => { + + it("A user navigates from homepage to signup and creates a new account", () => { const new_email = chance.email(); @@ -23,14 +25,54 @@ describe("Signup", () => { cy.visit("/"); cy.get('a.global-button[href="/users/new"]').click() cy.get("#email").type(new_email); - cy.get("#password").type("password!234"); - cy.get("#confirm-password").type("password!234"); + cy.get("#password").type("Password!234"); + cy.get("#confirm-password").type("Password!234"); cy.get("#first-name").type("Mrtest") cy.get("#last-name").type("Testtest") cy.get("#submit").click(); cy.url().should("include", "/posts"); }); + + + + it("A user navigates from homepage to signup and creates a new account with mismatched passwords", () => { + const new_email = chance.email(); + + // sign up + cy.visit("/"); + cy.get('a.global-button[href="/users/new"]').click(); + cy.get("#email").type(new_email); + cy.get("#password").type("Password!234"); + cy.get("#confirm-password").type("Password!345"); + cy.get("#first-name").type("Mrtest") + cy.get("#last-name").type("Testtest") + cy.get("#submit").click(); + + cy.url().should("not.include", "/posts"); + }); + + + + it("A user navigates from homepage to signup and creates a new account with an email that already exists", () => { + const new_email = chance.email(); + + // sign up + cy.visit("/"); + cy.get('a.global-button[href="/users/new"]').click(); + cy.get("#email").type("admin@example.com"); + cy.get("#password").type("Password!234"); + cy.get("#confirm-password").type("Password!345"); + cy.get("#first-name").type("Mrtest") + cy.get("#last-name").type("Testtest") + cy.get("#submit").click(); + + cy.url().should("not.include", "/posts"); + }); + + + + }); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index d9b4f87a9..8950c22bf 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -11,10 +11,24 @@ // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) -module.exports = function() { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config -} +//module.exports = function() { +// // `on` is used to hook into various events Cypress emits +// // `config` is the resolved Cypress config +//} + + +const mongoose = require('mongoose'); + +module.exports = (on) => { + on('task', { + async clearDb() { + await mongoose.connect('mongodb://0.0.0.0/acebook_test'); + await mongoose.connection.db.dropDatabase(); + await mongoose.connection.close(); + return null; + } + }); +}; diff --git a/cypress/support/commands.js b/cypress/support/commands.js index c1f5a772e..8884f9c76 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -23,3 +23,24 @@ // // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) + + +const mongoose = require('mongoose'); + +Cypress.Commands.add('clearDb', () => { + return cy.task('clearDb').then(() => { + return new Promise((resolve) => { + mongoose.connection.once('open', () => { + resolve(); + }); + }); + }); +}); + +Cypress.Commands.add('signIn', () => { + cy.visit("/"); + cy.get('a.global-button[href="/sessions/new"]').click(); + cy.get("#email").type("admin@example.com"); + cy.get("#password").type("Password!123"); + cy.get("#submit").click(); +}); \ No newline at end of file diff --git a/cypress/support/index.js b/cypress/support/index.js index c935d9f76..e89b0c4ab 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -21,15 +21,19 @@ require('./commands') before(() => { - const email = "admin@example.com"; - const password = "Password!123"; - - cy.visit("/"); - cy.get('a.global-button[href="/users/new"]').contains('Sign Up').click(); - cy.get("#email").type(email); - cy.get("#password").type(password); - cy.get("#confirm-password").type(password); - cy.get("#first-name").type("Mrtest"); - cy.get("#last-name").type("Testtest"); - cy.get("#submit").click(); - }); \ No newline at end of file + const email = "admin@example.com"; + const password = "Password!123"; + + cy.visit("/"); + cy.get('a.global-button[href="/users/new"]').contains('Sign Up').click(); + cy.get("#email").type(email); + cy.get("#password").type(password); + cy.get("#confirm-password").type(password); + cy.get("#first-name").type("Mrtest"); + cy.get("#last-name").type("Testtest"); + cy.get("#submit").click(); +}); + +after(() => { + cy.clearDb(); // Clear the database after all the tests +}); \ No newline at end of file