1
votes

I am using Mocha, Typescript and Cypress to write tests.
This is visualization of what I am trying to achieve (so far unsuccessfully :():

// this is in example-spec.ts file
context('Sharing variable test', function() {
  let ctx: string;

  beforeEach(function() {
    ctx = 'Value given in beforeEach';
  });

  console.log(ctx); // prints undefined
  consumeCtx(ctx);
});

// this is in separate example-template.ts file
export function consumeCtx(ctx: string) {
    console.log(ctx); // this is undefined
    // use ctx here
    describe('Testing my stuff', function () {
        it('should do something', function () {
          // use ctx here  
          cy.log('This is a test');
        });
      });
}

I would like I could somehow fill the ctx data in beforeEach and then use it after that through calling a function which accepts ctx as parameter.
The idea is to have 2 different spec files (e.g. example1-spec.ts and example2-spec.ts) which can be run separately.
But they still share the same test logic defined in example-template.ts file.
And the test data ctx specific to each spec file is provided in the spec file and then just passed to the common test logic in template file.
Is there a way to achieve this in the set up that I have created?
Is my approach completely wrong? How would you do it better?
Thanks!

[EDIT] This is how I reorganized it based on the answers:

In each spec file there is mocha structure.

context('Voucher tests', function () {
    let ctx: string;

    beforeEach(function () {
        ctx = 'Value given in beforeEach';
        cy.wrap(ctx).as('ctx');
    });

    describe('Logged in user', function () {
        it('valid voucher ', function () {
            cy.get<string>('@ctx').then((ctx) => {
                console.log(ctx); // should print the value of ctx now
                validCtxTest(ctx);
            });
        });

        it('invalid voucher ', function () {
            cy.get<string>('@ctx').then((ctx) => {
                console.log(ctx); // should print the value of ctx now
                invalidCtxTest(ctx);
            });
        });
    });
});  

And in separate template file I have the shared logic.

export function validCtxTest(ctx: string) {
  cy.log('Logic for valid test', ctx);
}

export function invalidCtxTest(ctx: string) {
  cy.log('Logic for invalid test', ctx);
}  
2

2 Answers

1
votes

I learnt this the hard way. But you need to wrap ctx, provide an alias, and then call that alias to be passed to your function. I am not a type script person, but hope this helps. [Edit: adding a working script and result]

context("blah",()=> {
    let ctx
    beforeEach( function()  {
        const uuid = () => Cypress._.random(0, 1e3)
        const id = uuid()
        ctx=`some random number ${id}`
        cy.wrap(ctx).as('ctx')
        
    })
    describe("Spec", () => {
        
        it("Test1", function()  {
            cy.get('@ctx').then(ctx=> {
                console.log(ctx)
            })
            
        })
    
        it("Test2", function()  {
            cy.get('@ctx').then(ctx=> {
                console.log(ctx)
            })
        })
    })
})

enter image description here

Also, if you are not planning to have multiple test in a spec file, or pass different value of ctx for each test under 1 spec file, then just ignore the Before hook. You can declare a variable inside your test and then wrap it up and call it anywhere you want in that test. For the next test, do the same. Its the same approach i have used in my project. fixtures help a lot in defining and passing test data, rather than variables.

0
votes

You have a mixture of synchronous and asynchronous code. The calls are not in the order you might expect from the test.

consumeCtx receives the initial value of ctx because it runs before the beforeEach().

To get the value of ctx inside the function use an alias and reference from this.

Test

import { consumeCtx } from '../support/consumeCtx'

context('Sharing variable test', function() {

  beforeEach(function() {
    const ctx = 'Value given in beforeEach';
    cy.wrap(ctx).as('ctx')
  });

  consumeCtx();
});

Function

export function consumeCtx() {
  describe('Testing my stuff', function () {
    it('should do something', function () {
      cy.log('This is a test: ', this.ctx);
    });
  });
}