Passing command line arguments to nightwatch.runner - nightwatch.js

I have a test setup that accepts dynamic values for predefined options (e.g: --foo="bar", --foo="car", etc) which works perfectly when run from the command line.
This works:
./node_modules/nightwatch/bin/nightwatch ./tests/test.js --env "production" --foo="bar"
However, I want to call the test from inside a node app, but can't quite seem to get the extra parameters passed into my test. My test initializes correctly, but then fails because I can't get any of the extra params.
try {
const nightwatch = require('nightwatch');
const argv = {
config: 'nightwatch.json',
test: 'test.js',
env: 'default',
foo: 'bar',
};
const done = function() {
console.log('nightwatch complete');
}; // your callback function
const settings = {};
nightwatch.runner(argv, done, settings);
} catch (error) {
console.log('Exception:' + error.message);
}
There seems to be absolutely no documentation for nightwatch.runner or nightwatch.cli so any help you can provide would be greatly appreciated.

It took a lot of poking around to see what gets set where, but finally I tried playing with the settings object and realized that I could override the globals param like so:
var settings = {
globals: {
foo: 'one',
bar: 'two'
}
};
This probably isn't the intended functionality of the settings object here, but it worked for me.
try {
const nightwatch = require('nightwatch');
const argv = {
config: 'nightwatch.json',
test: 'test.js',
env: 'default',
foo: 'bar',
};
const done = function() {
console.log('nightwatch complete');
}; // your callback function
var settings = {
globals: {
foo: 'one',
bar: 'two'
}
};
nightwatch.runner(argv, done, settings);
} catch (error) {
console.log('Exception:' + error.message);
}
If anyone who comes across this is interested, I posted a very simple version on github.

Related

Cypress origin command using dynamic data in a secondary origin

I am trying to follow the following code from the Cypress documentation.
cy.origin(
'supersecurelogons.com',
// Send the args here...
{ args: sentArgs },
// ...and receive them at the other end here!
({ username, password }) => {
cy.visit('/login')
cy.get('input#username').type(username)
cy.get('input#password').type(password)
cy.contains('button', 'Login').click()
}
)
The code that I am using is below. My problem is that both pathname & search are undefined, this means that the visit command is failing.
I was wondering what it is that I am doing wrong here, any help gratefully received.
const workaroundUrl = new URL('https://www.validurl.com/pathname?search=true');
const url = { pathname: workaroundUrl.pathname, search: workaroundUrl.search }
cy.origin(workaroundUrl.origin, { args: { url } }, ({ pathname, search }) => {
cy.visit(pathname + search);
});
I am using v10.4.0.
I think you need to match up the brackets (send and receive) like this
const workaroundUrl = new URL('https://www.validurl.com/pathname?search=true');
const url = { pathname: workaroundUrl.pathname, search: workaroundUrl.search }
cy.origin(workaroundUrl.origin, { args: {url} }, ({url}) => {
const { pathname, search } = url; // destructure the url arg
cy.visit(pathname + search);
});
That would make the example you mentioned incorrect.
I've used this pattern successfully origin - Usage
cy.origin('https://www.acme.com', { args: { hits } }, ({ hits }) => {

How to match partial nest properties passed to toHaveBeenCalledWith?

describe("Test", function() {
it("should pass", function() {
const callback = (data) => {};
const callBackSpy = jasmine.createSpy().and.callFake(callback);
const createData = (message) => {
return {
outerProp: "outerValue",
nestedObj: {
message: message,
prop1: "value1",
prop2: "value2"
}
};
};
const someApiCall = (callback) => {
setTimeout(callback(createData("test1")), 1000);
setTimeout(callback(createData("test2")), 2000);
setTimeout(callback(createData("hello world")), 5000);
};
someApiCall(callBackSpy);
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: {
prop1: "hello world"
}
})
);
});
});
I created a spy on a callback function which gets called multiple times with different parameters each time. The parameter is a complex nested object. I am looking for an object with a specific property.
If I specify all the properties like below, it works
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
outerProp: "outerValue",
nestedObj: {
message: "hello world",
prop1: "value1",
prop2: "value2"
}
})
);
But I don't know full properties. So, I am looking only for a specific property like below
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: {
message: "hello world"
}
})
);
Is there a way to make this work with a partial match?
You could try this.
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: jasmine.objectContaining({message: 'hello world'})
})
);
Another way would be to extract the arguments from the method call and test for specific nested attribute.
const arguments = callBackSpy.calls.argsFor(0);
expect(arguments[0]['nesedObject']['message'].toBe('hello world');

Issue while updating store from updater function of commitMutation

I have a mutation
mutation createQuoteLineMutation {
createQuoteLine {
quoteLine {
name
price
product {
name
}
}
}
}
My updater function is as below.
updater: (store) => {
const payload = store.getRootField('createQuoteLine');
const newQuoteLine = payload.getLinkedRecord('quoteLine');
const quote = store.getRoot().getLinkedRecord('getQuote');
const quoteLines = quote.getLinkedRecords('quoteLines') || [];
const newQuoteLines = [...quoteLines, newQuoteLine];
quote.setLinkedRecords(newQuoteLines, 'quoteLines');
}
This works fine for the first time, but the consequent mutations all the previously added quoteLines change to new one I'm assuming this is because newQuoteLine points to same object all the time.
adding below line at the end of updater function unlink quoteLine from createQuoteLine also does not work.
payload.setValue(null, 'quoteLine');
Any help in this regard is highly appreciated.
I have seen a quite similar problem, but I am not sure if it's the same. Try to pass an clientMutationId to the mutation, and increment it along.
const commit = (
input,
onCompleted: (response) => void,
) => {
const variables = {
input: {
...input,
clientMutationId: temp++,
},
};
commitMutation(Environment, {
mutation,
variables,
onCompleted,
onError: null,
updater: store => {
// ....
},
});
};
Try something like this and let me know if it fixes :).

chai-as-promised should.eventually.equal not passing

I am trying to write a minimum working example of chai-as-promised in order to understand how it is working when testing functions that return a promise.
I have the following function:
simple.test = async (input) => {
return input;
};
and the following test function:
chai.use(sinonChai);
chai.use(chaiAsPromised);
const { expect } = chai;
const should = chai.should();
describe('#Test', () => {
it('test', () => {
expect(simple.test(1)).should.eventually.equal(1);
});
});
However, testing this results in the test not passing, but in a very long error, which is pasted here: https://pastebin.com/fppecStx
Question: Is there something wrong about the code, or what seems to be the problem here?
First: Your mixing expect and should. If you want to use should for assertion, you don't need expect.
Second: To tell mocha that a test is async you have to either call done, return a Promise or use async/await.
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinonChai = require('sinon-chai');
const should = chai.should();
chai.use(sinonChai);
chai.use(chaiAsPromised);
// Function to test
const simple = {
test: async (input) => {
return input;
}
}
// Test
describe('#Test', () => {
it('test', () => {
return simple.test(1).should.eventually.equal(1);
});
});

Jasmine: how to check that array contains an object?

This check used to pass:
expect(array).toContain(value)
Array:
[
{"_t":"user","id":1073970419,"email":"email3#example.org","name":"Spectator"},
{"_t":"user","id":4464992042,"email":"email4#example.org","name":"Collaborator"},
{"_t":"user","id":1978569710,"email":"email5#example.org","name":"Manage"}
]
Value:
{"_t":"user","id":1978569710,"email":"email5#example.org","name":"Manage"}
But no longer passes. Whats the new way to write the same test?
The syntax you need is:
const obj = {"_t":"user","id":1978569710,"email":"email5#example.org","name":"Manage"};
expect(array).toContain(jasmine.objectContaining(obj));
See fiddle: https://jsfiddle.net/bblackwo/4o5u5Lmo/16/
It won't contain that object (remember, two objects with the same properties are not the same object for the purposes of equality), so toContain will never pass.
You need to use another test, like toEqual or (if you only want to check for a subset of properties), toEqual combined with jasmine.objectContaining.
Here's the toEqual example from the Jasmine documentation on that page:
describe("The 'toEqual' matcher", function() {
it("works for simple literals and variables", function() {
var a = 12;
expect(a).toEqual(12);
});
it("should work for objects", function() {
var foo = {
a: 12,
b: 34
};
var bar = {
a: 12,
b: 34
};
expect(foo).toEqual(bar);
});
});
Note now foo equals bar.
Here's their example using jasmine.objectContaining:
describe("jasmine.objectContaining", function() {
var foo;
beforeEach(function() {
foo = {
a: 1,
b: 2,
bar: "baz"
};
});
it("matches objects with the expect key/value pairs", function() {
expect(foo).toEqual(jasmine.objectContaining({
bar: "baz"
}));
expect(foo).not.toEqual(jasmine.objectContaining({
c: 37
}));
});
// ...
});
Note how the object with several properties matches the partial object supplied to jasmine.objectContaining.
#T.J.Crowder already explained precisely the problem. Just to help you a tad more, if you want to adapt your example, you'd need something like this:
var userA = {"_t":"user","id":1978569710,"email":"email5#example.org","name":"Manage"}
array =
[
{"_t":"user","id":1073970419,"email":"email3#example.org","name":"Spectator"},
{"_t":"user","id":4464992042,"email":"email4#example.org","name":"Collaborator"},
userA
]
expect(array).toContain(userA);

Resources