Session 14 – Testing - Cypress (E2E)
Note: security is not implemented properly (no route guards), this is done to focus on testing and avoid wasting time in signing up/logging in, and their related issues. Consequently, the logout button is deactivated.
1. Clone the following repository Repo.
2. Navigate to the project directory
3. Install dependencies
> npm install
4. Complete the information related to your database (db name, password) in the database.js file that is in the ../server directory
5. Run the backend
> npm run server
6. Run the front end
> npm run serve
7. Open Cypress
> npx cypress open
8. Open cypress/e2e/lab-14-tests.cy.js in your IDE.
9. Run task 1, i.e., run cypress and since it is the only uncommented test, it will run
// Test 1 - test the "add post" form it('Testing the “add Post” form', () => { cy.visit('http://localhost:8080/api/addpost') cy.contains('Add Post') cy.get('input').length > 2 cy.get('button').should('exist') cy.get('button').should('be.visible').and('be.enabled') })
10. Uncomment Task 2, then, in the dedicated space, add four test steps that do the following:
- Select ("get") the text input related to the "email", then, type "name@ut.ee" in it
- Select ("get") the text input related to the "password", then, type "123" in it
- The signup button should have the class "SignUp"
- The form should include a visible button. Note that the signup button is the only button on the page.
// Test 2 - Test the "Sign up" form when the password is not valid it('Testing the sign up form when password is not valid', () => { cy.visit('http://localhost:8080/api/signup') cy.get('label').length > 2 cy.get('input').length > 2 cy.get('button').should('exist') cy.get('button').should('have.css', 'display') cy.get('h3').should('contain', 'SignUp') // ------------------- // Your code goes here // ------------------- cy.contains('Password must be at least 8 characters and less than 16 characters, it must include a capital letter and at least one number') })
11. Uncomment Task 3, then, in the dedicated space, add a test step that locates the "add post" button, then, click it.
// Test 3 - Testing the "Add post" page it('Testing the "Add post" page', () => { cy.visit('http://localhost:8080/api/addpost') cy.wait(2000) cy.get('#title').type('new post') cy.wait(2000) cy.get('#body').type('new post') cy.wait(2000) // ------------------- // Your code goes here // ------------------- })
12. Uncomment Task 4, then, in the dedicated space, add a test step that locates the first post in the "all posts" page, then, click it.
//Test 4 - Testing the "all posts page and the link to the "a post" page" it('all posts page/link to a Post page', () => { cy.visit('http://localhost:8080/api/allposts') cy.wait(2000) // ------------------- // Your code goes here // ------------------- })
13. Uncomment Task 5, then, in the dedicated space, write the required test steps to modify the body of the post, locate the "update post" button, then, click it.
//Test 5 - Test modifying a post in the "a post" page" it('modifying a post', () => { cy.visit('http://localhost:8080/api/apost/231') cy.wait(2000) cy.get('#title').clear().type('next post title') // clear() will clear the text before writing an input cy.wait(2000) // ------------------- // Your code goes here // ------------------- })
14. Uncomment Task 6, then, write the required test steps to delete the first post (id = 1 assuming that you have such a post in your DB).
// Test 6 - Deleting a post in the "a post" page it('deleting a post', () => { // ------------------- // Your code goes here // ------------------- })
Basic API testing: Note: Cypress does not directly verify whether the response of the request to the API is correct, it will mainly care about a response, which is interpreted as ok by Cypress, i.e., the related test will pass. Therefore, we need to do that based on our knowledge of the expected returned value.
15. Uncomment Task 7, try to understand it, then, run it and check the results.
//Test 7 - testing Get all request from an API for and check the returned ID it("Get all posts", function() { cy.request("GET", "http://localhost:3000/api/posts", {}).then((res) => { cy.log(res.body) expect(res.body['0']).have.property('id') // a simple way to verify that we have a correct returned value let post = res.body assert.isArray(post, 'value is array') //another way to verify that we have a correct returned value }); })
16. Uncomment Task 8, try to understand what we are doing to verify the returned result, then, run it and check the results.
// Test 8 - testing Get request from an API for a post based on its ID, and check the returned ID it("Get a post based on its id", function() { let postId = 1 //Change the value to an id of a post in your database cy.request("GET", `http://localhost:3000/api/posts/${postId}`, {}).then((res) => { cy.log(res.body.id) expect(res.body.id).to.equal(postId) // expect(res.body.title).to.equal('Post 1') //post title in my database }); })
17. Uncomment Task 9, try to understand what we are doing to verify the returned result, then, run it and check the results.
//Test 9 - testing Post request to an API it("Add post request", function() { cy.request('POST', 'http://localhost:3000/api/posts', { "title": "Post 4", "body": "Post body 4", "urllink": "Post 4 urllink" }) .then((res) => { cy.log(res.body) let post = res.body.rows['0'].id expect(post).to.not.be.null; // to guarantee that the post has been added cy.log('post is added') }); })
18. Uncomment Task 10, try to write a test case for a Put request to the API. As you should know, such test case should be almost similar to the Post request test case.
// Test 10 - testing Update request to an API it("Update a post request", function() { // ------------------- // Your code goes here // ------------------- })
19. Based on the previous request, try to write a test case for deleting a post from the API
// Test 11 - testing Delete request to an API it("Delete a post request", function() { // ------------------- // Your code goes here // ------------------- })