Search code examples
javascriptreactjscypresschaispy

Trying to expect a function to be called with Cypress and Sinon


I am using the MERN stack and the Cypress testing library for my web app. I am trying to expect a function to be called from within the Dashboard component, but I am getting the error Attempted to wrap undefined property as function.

Dashboard.js

function reminderNotification(data) {
    

      const invoiceDue = moment.unix(data.due_date);
      const reminderDate = invoiceDue.subtract(2, 'days');
      const reminderConverted = reminderDate.format(' MMMM Do YYYY');
      const currentDate = moment();
      const currentDateConverted = currentDate.format(' MMMM Do YYYY');
      
    
        if(reminderConverted === currentDateConverted ) {
          return (
            
           NotificationManager.warning(`${data.id} is due in 2 days: Please visit the Dashboard 😃`, 'Invoices Due', 2000)
          )
         } else {
           console.log('[card] No invoices are due at this time');
         }
  return;    
  };

  // Orders invoices by newest to oldest
   data.sort(biggestToSmallest);
   paidData.sort(biggestToSmallest);

  function card(data) {
    
    // Converting epoch seconds to human readable date
    const invoiceCreated = moment.unix(data.created);
    const invoiceCreatedConverted = invoiceCreated.format(' MMMM Do YYYY');
    const invoiceDue = moment.unix(data.due_date);
    const invoiceDueConverted = invoiceDue.format(' MMMM Do YYYY');
    
    // Executing the function to convert amout due.
    const amountDue = decimalInsert(data.amount_due);
    
   
    // Shows a notification when data from database has been loaded
    return(
      <Card>
        
        { data ? showNotification("bl") : null}
            <CardHeader stats icon>
              <CardIcon color="success">
                <Icon>content_copy</Icon>
              </CardIcon>
              <h5 className={classes.cardCategory}> <strong>Invoice Id:</strong> {!data ? 'Loading...' : data.id}</h5>
              <h5 className={classes.cardTitle}>
              <strong>Invoice Created: </strong> {!data ? 'Loading...' : invoiceCreatedConverted}
              </h5>
              <h5 className={classes.cardTitle}> <strong>Invoice Due: </strong>{!data ? 'Loading...' : invoiceDueConverted}</h5>
              <h5 className={classes.cardTitle}> <strong>Amount Due: </strong>{!data ? 'Loading...' : amountDue}</h5>
            </CardHeader>
            <CardFooter stats>
              <div className={classes.stats}>
              <Button variant="contained" color="primary" onClick={() => {window.location.assign(data.hosted_invoice_url)}}>
                Pay Now
              </Button>
              <Button variant="contained" color="default" onClick={() => {window.location.assign(data.invoice_pdf)}}>
                Download Invoice
              </Button>
              </div>
            </CardFooter>
            {userPreferenceGet() === true ?  reminderNotification(data) : console.log('{User Settings} User has chosen to not have reminders')}
          </Card>
    );

Dashboard.spec.js

describe('Authentication', function () {

  beforeEach(function () {
    cy.loginByAuth0Api(
      Cypress.env('auth0_username'),
      Cypress.env('auth0_password')
    )
  })
  
     it('shows dashboard', function () {


      cy.get('.jss8').should('be.visible')
     });

    it('Reminder notifications dont show', function () {

      cy.get('#notificationNo').click().should(() => {
        let storage = localStorage.getItem('notification')
        cy.log(storage);
        expect(storage).to.deep.equal('false');
      });
     });   

     it('Reminder notifications show', function () {

      cy.get('#notificationYes').click().should(() => {
        let storage = localStorage.getItem('notification')
        
        cy.log(storage);
        expect(storage).to.deep.equal('true');
        let object = {
        
        }
        cy.spy(object, 'reminderNotification').withArgs('data');
        expect(object.reminderNotification).to.be.called;
      }); 
   });
  })


Solution

  • Your object variable is empty, that's why the error message. Let's suppose the object method returns a string. Then you could do next to spy on the object's function:

    let object = {
      reminderNotification(msg) {
        return msg;
      }
    }
    const spyObject = cy.spy(object, 'reminderNotification');
    const spyWithArgs = spyObject.withArgs('data');
    object.reminderNotification('data');
    expect(spyObject).to.be.called;
    expect(spyWithArgs).to.be.called;
    expect(spyObject.returnValues[0]).to.eq('data');