-->

Use helper modules for repeated, ordered tasks whe

2019-06-10 12:27发布

问题:

I'm trying to create a module that will fill in form inputs when functional testing, and I'd like to be able to call it from multiple test suites.

Pseudo code for the helper file (helper.js)

module.exports = {
    fillForm: function() {
        this.findByCssSelector('#firstname')
            .click()
            .pressKeys('John')
            .end()
    },
    anotherFunction: function() {
        // more code
    }
}

In the spec for the functional test, I load that module as helper and I can see it execute. However, it seems I can't use this syntax and guarantee that the chained steps execute in the defined order:

'Test filling form data': function() {
    return this.remote
                .get(require(toUrl(url))
                // should happen first
                .then(helper.fillForm)
                // should happen second
                .then(helper.anotherFunction)
                // only after the above should the click happen
                .findByCsSelector('#submit')
                 // click evt should show the #someElement element
                .click()                     
                .findByCssSelector('#someElement')
                .getComputedStyle('display')
                .then(style) {
                     // assertions here
    }

It seems that the promise chaining allows the click event to happen before the then callbacks have executed. Is this sort of flow possible with intern?

UPDATE:

For the moment, working around this with this sort of code:

var remote = initTest.call(this, url);
return helpers.fillForm1Data.call(remote)
    .otherChainedMethodsHere()
    .moreChainedMethods()
.then() {
    // assertion code here

where the initTest method does url fetching, window sizing, clearing data, and the fillForm1Data does as you'd expect. But the syntax is pretty ugly this way.

回答1:

Your helper is not returning any value so it is treated as a synchronous callback and the next thing in the chain is executed immediately. You also cannot return this from a promise helper or it will cause a deadlock (because the Command promise will be waiting for itself to resolve—Intern will throw an error instead if you try to do this), so you need to create a new Command and return that if you want to use the chained Command interface within your helper:

module.exports = {
    fillForm: function() {
        return new this.constructor(this.session)
            .findByCssSelector('#firstname')
            .click()
            .pressKeys('John');
    },
    anotherFunction: function() {
        // more code
    }
};

You can also just return from this.session instead if you don’t care about the convenience of the Command API and can deal with normal promise callback chains:

module.exports = {
    fillForm: function() {
        var session = this.session;
        return session.findByCssSelector('#firstname')
          .then(function (element) {
            return element.click();
          })
          .then(function () {
            return session.pressKeys('John');
          });
    },
    anotherFunction: function() {
        // more code
    }
};