0

I'm using cypress to test my backend node api.

I would like to reset my Db to a clean state in my before function. This involves using axios (therefore receiving promises) to send post, put & delete requests to my json-server "db".

I'm familiar with the commands file of cypress (already using it for my login function), but I don't seem to manage to make it work for my "reset db" behavior.

I therefore simplified the problem until posting my user in the "it" function, but it still does not work

cypress test:

const axios = require('axios')

describe('Auth', function() {
  beforeEach(function() {
    cy.visit('http://localhost:8080')
  })

  describe('login with non existing user', function() {
    it('should show an error message', function() {      
      cy.login('non.existing.user@example.com', 'password')
      cy.get('#app > div.container > div > div > div > div > div > form > div.alert.form-group.alert-danger')
        .should('have.text', 'Invalid Credentials')
    })
  })


  describe('login with an invalid password', function() {
    it('should show an error message', async function() {
      cy.putUserToDb('existingUser', 'existing.user@test.test', 'Existing User', 'password')
      cy.login('existing.user@test.test', 'pass')
      cy.get('#app > div.container > div > div > div > div > div > form > div.alert.form-group.alert-danger')
        .should('have.text', 'Invalid Credentials')
    })
  })
})

cypress commands:

const axios = require('axios')
const bcrypt = require('bcrypt')

Cypress.Commands.add("login", (email, password) => {
  cy.contains('Log In')
    .click()
  cy.url()
    .should('include', '/signin')
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(1) > input')
    .clear()
    .type(email)
    .should('have.value', email)
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(2) > input')
    .clear()
    .type(password)
    .should('have.value', password)
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(3) > button')
    .click()
})

Cypress.Commands.add("putUserToDb", async (id, email, name, password) => {
  const jsonServerUrl = 'http://localhost:5000'
  console.log(`${jsonServerUrl}/users/${id}`)
  await axios
    .put(`${jsonServerUrl}/users/${id}`, {
      email: email,
      name: name,
      password: bcrypt.hashSync(password)
    })
})

I get this error in cypress:

tests?p=cypress\integration\auth.js-872:37810 Uncaught Uncaught TypeError: Cannot read property '_handle' of undefined

This error originated from your test code, not from Cypress.

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

Cypress could not associate this error to any specific test.

We dynamically generated a new test to display this failure.

Check your console for the stack trace or click this message to see where it originated from.
    at http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:37810:16
    at Array.forEach (<anonymous>)
    at module.exports (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:37809:36)
    at Object.<anonymous> (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:35419:1)
    at Object.249._process (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:35719:4)
    at o (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:1:265)
    at http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:1:316
    at Object.<anonymous> (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:32284:11)
    at Object.242.../package.json (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:32473:4)
    at o (http://localhost:59099/__cypress/tests?p=cypress\integration\auth.js-872:1:265)

Would you know how to properly reset my Db before a set of tests?

Thanks in advance!

laurent exsteens
  • 431
  • 1
  • 5
  • 13
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – jonrsharpe Aug 05 '19 at 20:57
  • @jonrsharpe Not sure this is where the problem is. After my edit, you can see I now use and async function and wait for axios to finish, but I still get the same error.... – laurent exsteens Aug 06 '19 at 21:37

1 Answers1

0

I finally understood where the problem was: it was simply the bcrypt library that was using underlying C libraries, therefore working in node, but not in the browser. Replacing it by bcryptjs solved my problem.

Afterwards, my tests where not properly working due to my putUserToDb command not returning a Cypress Promise.

After fixing that problem, my code now looks like this:

command.js:

import axios from 'axios'
import bcrypt from 'bcryptjs'

Cypress.Commands.add("login", (email, password) => {
  cy.contains('Log In')
    .click()
  cy.url()
    .should('include', '/signin')
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(1) > input')
    .clear()
    .type(email)
    .should('have.value', email)
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(2) > input')
    .clear()
    .type(password)
    .should('have.value', password)
  cy.get('#app > div.container > div > div > div > div > div > form > div:nth-child(3) > button')
    .click()
})

Cypress.Commands.add("putUserToDb", (id, email, name, password) => {
  const jsonServerUrl = 'http://localhost:5000'
  return new Cypress.Promise((resolve, reject) => {
     axios.put(`${jsonServerUrl}/users/${id}`, {
      id: id,
      email: email,
      name: name,
      password: bcrypt.hashSync(password)
    })
    .then((data) => {
      resolve()
    })
    .catch((err) => {
      reject(err)
    })
  })
})

auth.js:

describe('Auth', function() {
  before(() => {
    cy.putUserToDb('existingUser', 'existing.user@test.test', 'Existing User', 'password')
  })

  beforeEach(function() {
    cy.visit('http://localhost:8080')
  })

  describe('login with non existing user', function() {
    it('should show an error message', function() {
      cy.login('non.existing.user@example.com', 'password')
      cy.get('#app > div.container > div > div > div > div > div > form > div.alert.form-group.alert-danger')
        .should('have.text', 'Invalid Credentials')
    })
  })


  describe('login with an invalid password', function() {
    it('should show an error message', function() {
      cy.login('existing.user@test.test', 'pass')
      cy.get('#app > div.container > div > div > div > div > div > form > div.alert.form-group.alert-danger')
        .should('have.text', 'Invalid Credentials')
    })
  })
})
laurent exsteens
  • 431
  • 1
  • 5
  • 13