Pass data from one step to the next synchronously












1















Running Cypress 3.1.1 with cypress-cucumber-preprocessor 1.5.1. I need to pass some static data from one step to another (in the same scenario/test). I can do this using an alias, like this:
cy.wrap(someString).as('myString'), but then I have to access it asynchronously:



cy.get('@myString').then(myString => ...)



This is rather cumbersome, particularly when I have to pass multiple values, requiring multiple wrapped closures, for no apparent benefit. (Currently I'm working around this by aliasing an object, but I shouldn't need to do this.)



How can I pass primitive values from one step to another synchronously?



I thought I might be able to simply set this.myString='' to set the value on the Mocha shared context object, but in that case, the property exists but is set to undefined when accessed in later steps.



Even creating my own context variable with let outside of the step definition does not work. Is this simply a limitation of Cypress and/or the cypress-cucumber-preprocessor?










share|improve this question























  • I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

    – Phillipe Bojorquez
    Nov 28 '18 at 2:22


















1















Running Cypress 3.1.1 with cypress-cucumber-preprocessor 1.5.1. I need to pass some static data from one step to another (in the same scenario/test). I can do this using an alias, like this:
cy.wrap(someString).as('myString'), but then I have to access it asynchronously:



cy.get('@myString').then(myString => ...)



This is rather cumbersome, particularly when I have to pass multiple values, requiring multiple wrapped closures, for no apparent benefit. (Currently I'm working around this by aliasing an object, but I shouldn't need to do this.)



How can I pass primitive values from one step to another synchronously?



I thought I might be able to simply set this.myString='' to set the value on the Mocha shared context object, but in that case, the property exists but is set to undefined when accessed in later steps.



Even creating my own context variable with let outside of the step definition does not work. Is this simply a limitation of Cypress and/or the cypress-cucumber-preprocessor?










share|improve this question























  • I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

    – Phillipe Bojorquez
    Nov 28 '18 at 2:22
















1












1








1








Running Cypress 3.1.1 with cypress-cucumber-preprocessor 1.5.1. I need to pass some static data from one step to another (in the same scenario/test). I can do this using an alias, like this:
cy.wrap(someString).as('myString'), but then I have to access it asynchronously:



cy.get('@myString').then(myString => ...)



This is rather cumbersome, particularly when I have to pass multiple values, requiring multiple wrapped closures, for no apparent benefit. (Currently I'm working around this by aliasing an object, but I shouldn't need to do this.)



How can I pass primitive values from one step to another synchronously?



I thought I might be able to simply set this.myString='' to set the value on the Mocha shared context object, but in that case, the property exists but is set to undefined when accessed in later steps.



Even creating my own context variable with let outside of the step definition does not work. Is this simply a limitation of Cypress and/or the cypress-cucumber-preprocessor?










share|improve this question














Running Cypress 3.1.1 with cypress-cucumber-preprocessor 1.5.1. I need to pass some static data from one step to another (in the same scenario/test). I can do this using an alias, like this:
cy.wrap(someString).as('myString'), but then I have to access it asynchronously:



cy.get('@myString').then(myString => ...)



This is rather cumbersome, particularly when I have to pass multiple values, requiring multiple wrapped closures, for no apparent benefit. (Currently I'm working around this by aliasing an object, but I shouldn't need to do this.)



How can I pass primitive values from one step to another synchronously?



I thought I might be able to simply set this.myString='' to set the value on the Mocha shared context object, but in that case, the property exists but is set to undefined when accessed in later steps.



Even creating my own context variable with let outside of the step definition does not work. Is this simply a limitation of Cypress and/or the cypress-cucumber-preprocessor?







cucumberjs cypress






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 20:17









hackelhackel

634716




634716













  • I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

    – Phillipe Bojorquez
    Nov 28 '18 at 2:22





















  • I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

    – Phillipe Bojorquez
    Nov 28 '18 at 2:22



















I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

– Phillipe Bojorquez
Nov 28 '18 at 2:22







I am unsure if this should be a comment or not, but I feel like you have to use .its and .invoke to do this with any measure of control. docs.cypress.io/api/commands/invoke.html#Examples docs.cypress.io/api/commands/its.html#Requests

– Phillipe Bojorquez
Nov 28 '18 at 2:22














2 Answers
2






active

oldest

votes


















0














This not a complete answer, but you can set javascript variables in a before(() => {}) statement, and they will be available to use within any nested it(..., () => {}) statements.



For example, I have one set of tests checking two versions of the same app written in different frameworks. So I need to know the framework being tested, and load different fixtures.



To do this I use the following



const framework = Cypress.env('FRAMEWORK')
let config;

before(function() {
cy.fixture('frameworks').then(fixture => {
config = fixture[framework]
})
})


Then I can use config in tests,



cy.visit(config.pageUrl)

it('should have a title', () => {
cy.title().should('contain', config.title)
});


You can use before() in many places in the test suite, generally after a describe() or context() and the variables defined within are available in a 'normal' javascript way.






share|improve this answer
























  • Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

    – hackel
    Nov 27 '18 at 21:35











  • That must cramp your style somewhat. What about given()?

    – Hiram K. Hackenbacker
    Dec 2 '18 at 10:02



















0














Here is a slightly more complicated (and not fully tested) method. A custom command can be added to save values to a global object.



In the Cypress test runner, all the tests seem to run sequentially, but you may have to be careful if using CI and parallel execution.



In /support/commands.js



export const testStore = {}

Cypress.Commands.add('saveAs', { prevSubject: true }, (value, propName) => {
console.log('saveAs', value, propName)
testStore[propName] = value;
return value;
})


In myTest.spec.js



import { testStore } from '../support/commands.js'
...

it('should have a title', () => {
cy.title()
.saveAs('title') // save for next test
.should('contain', 'myTitle) // this test's expectation
});

it('should test something else', () => {
cy.get('.myElement').contains(testStore.title);
});





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382024%2fpass-data-from-one-step-to-the-next-synchronously%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    This not a complete answer, but you can set javascript variables in a before(() => {}) statement, and they will be available to use within any nested it(..., () => {}) statements.



    For example, I have one set of tests checking two versions of the same app written in different frameworks. So I need to know the framework being tested, and load different fixtures.



    To do this I use the following



    const framework = Cypress.env('FRAMEWORK')
    let config;

    before(function() {
    cy.fixture('frameworks').then(fixture => {
    config = fixture[framework]
    })
    })


    Then I can use config in tests,



    cy.visit(config.pageUrl)

    it('should have a title', () => {
    cy.title().should('contain', config.title)
    });


    You can use before() in many places in the test suite, generally after a describe() or context() and the variables defined within are available in a 'normal' javascript way.






    share|improve this answer
























    • Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

      – hackel
      Nov 27 '18 at 21:35











    • That must cramp your style somewhat. What about given()?

      – Hiram K. Hackenbacker
      Dec 2 '18 at 10:02
















    0














    This not a complete answer, but you can set javascript variables in a before(() => {}) statement, and they will be available to use within any nested it(..., () => {}) statements.



    For example, I have one set of tests checking two versions of the same app written in different frameworks. So I need to know the framework being tested, and load different fixtures.



    To do this I use the following



    const framework = Cypress.env('FRAMEWORK')
    let config;

    before(function() {
    cy.fixture('frameworks').then(fixture => {
    config = fixture[framework]
    })
    })


    Then I can use config in tests,



    cy.visit(config.pageUrl)

    it('should have a title', () => {
    cy.title().should('contain', config.title)
    });


    You can use before() in many places in the test suite, generally after a describe() or context() and the variables defined within are available in a 'normal' javascript way.






    share|improve this answer
























    • Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

      – hackel
      Nov 27 '18 at 21:35











    • That must cramp your style somewhat. What about given()?

      – Hiram K. Hackenbacker
      Dec 2 '18 at 10:02














    0












    0








    0







    This not a complete answer, but you can set javascript variables in a before(() => {}) statement, and they will be available to use within any nested it(..., () => {}) statements.



    For example, I have one set of tests checking two versions of the same app written in different frameworks. So I need to know the framework being tested, and load different fixtures.



    To do this I use the following



    const framework = Cypress.env('FRAMEWORK')
    let config;

    before(function() {
    cy.fixture('frameworks').then(fixture => {
    config = fixture[framework]
    })
    })


    Then I can use config in tests,



    cy.visit(config.pageUrl)

    it('should have a title', () => {
    cy.title().should('contain', config.title)
    });


    You can use before() in many places in the test suite, generally after a describe() or context() and the variables defined within are available in a 'normal' javascript way.






    share|improve this answer













    This not a complete answer, but you can set javascript variables in a before(() => {}) statement, and they will be available to use within any nested it(..., () => {}) statements.



    For example, I have one set of tests checking two versions of the same app written in different frameworks. So I need to know the framework being tested, and load different fixtures.



    To do this I use the following



    const framework = Cypress.env('FRAMEWORK')
    let config;

    before(function() {
    cy.fixture('frameworks').then(fixture => {
    config = fixture[framework]
    })
    })


    Then I can use config in tests,



    cy.visit(config.pageUrl)

    it('should have a title', () => {
    cy.title().should('contain', config.title)
    });


    You can use before() in many places in the test suite, generally after a describe() or context() and the variables defined within are available in a 'normal' javascript way.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 19 '18 at 22:00









    Hiram K. HackenbackerHiram K. Hackenbacker

    33717




    33717













    • Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

      – hackel
      Nov 27 '18 at 21:35











    • That must cramp your style somewhat. What about given()?

      – Hiram K. Hackenbacker
      Dec 2 '18 at 10:02



















    • Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

      – hackel
      Nov 27 '18 at 21:35











    • That must cramp your style somewhat. What about given()?

      – Hiram K. Hackenbacker
      Dec 2 '18 at 10:02

















    Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

    – hackel
    Nov 27 '18 at 21:35





    Thanks, but I don't believe the before() hook is supported in cypress-cucumber-preprocessor step definitions. Unfortunately declaring the variable outside (like you did with config) doesn't work in this case.

    – hackel
    Nov 27 '18 at 21:35













    That must cramp your style somewhat. What about given()?

    – Hiram K. Hackenbacker
    Dec 2 '18 at 10:02





    That must cramp your style somewhat. What about given()?

    – Hiram K. Hackenbacker
    Dec 2 '18 at 10:02













    0














    Here is a slightly more complicated (and not fully tested) method. A custom command can be added to save values to a global object.



    In the Cypress test runner, all the tests seem to run sequentially, but you may have to be careful if using CI and parallel execution.



    In /support/commands.js



    export const testStore = {}

    Cypress.Commands.add('saveAs', { prevSubject: true }, (value, propName) => {
    console.log('saveAs', value, propName)
    testStore[propName] = value;
    return value;
    })


    In myTest.spec.js



    import { testStore } from '../support/commands.js'
    ...

    it('should have a title', () => {
    cy.title()
    .saveAs('title') // save for next test
    .should('contain', 'myTitle) // this test's expectation
    });

    it('should test something else', () => {
    cy.get('.myElement').contains(testStore.title);
    });





    share|improve this answer




























      0














      Here is a slightly more complicated (and not fully tested) method. A custom command can be added to save values to a global object.



      In the Cypress test runner, all the tests seem to run sequentially, but you may have to be careful if using CI and parallel execution.



      In /support/commands.js



      export const testStore = {}

      Cypress.Commands.add('saveAs', { prevSubject: true }, (value, propName) => {
      console.log('saveAs', value, propName)
      testStore[propName] = value;
      return value;
      })


      In myTest.spec.js



      import { testStore } from '../support/commands.js'
      ...

      it('should have a title', () => {
      cy.title()
      .saveAs('title') // save for next test
      .should('contain', 'myTitle) // this test's expectation
      });

      it('should test something else', () => {
      cy.get('.myElement').contains(testStore.title);
      });





      share|improve this answer


























        0












        0








        0







        Here is a slightly more complicated (and not fully tested) method. A custom command can be added to save values to a global object.



        In the Cypress test runner, all the tests seem to run sequentially, but you may have to be careful if using CI and parallel execution.



        In /support/commands.js



        export const testStore = {}

        Cypress.Commands.add('saveAs', { prevSubject: true }, (value, propName) => {
        console.log('saveAs', value, propName)
        testStore[propName] = value;
        return value;
        })


        In myTest.spec.js



        import { testStore } from '../support/commands.js'
        ...

        it('should have a title', () => {
        cy.title()
        .saveAs('title') // save for next test
        .should('contain', 'myTitle) // this test's expectation
        });

        it('should test something else', () => {
        cy.get('.myElement').contains(testStore.title);
        });





        share|improve this answer













        Here is a slightly more complicated (and not fully tested) method. A custom command can be added to save values to a global object.



        In the Cypress test runner, all the tests seem to run sequentially, but you may have to be careful if using CI and parallel execution.



        In /support/commands.js



        export const testStore = {}

        Cypress.Commands.add('saveAs', { prevSubject: true }, (value, propName) => {
        console.log('saveAs', value, propName)
        testStore[propName] = value;
        return value;
        })


        In myTest.spec.js



        import { testStore } from '../support/commands.js'
        ...

        it('should have a title', () => {
        cy.title()
        .saveAs('title') // save for next test
        .should('contain', 'myTitle) // this test's expectation
        });

        it('should test something else', () => {
        cy.get('.myElement').contains(testStore.title);
        });






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 '18 at 22:47









        Hiram K. HackenbackerHiram K. Hackenbacker

        33717




        33717






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382024%2fpass-data-from-one-step-to-the-next-synchronously%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)