I am looking for a way to overwrite expect method for TestController. My idea is existing tests whoever used t.expect method, I want to perform additional steps in those cases.
I came up with below sample code but testcafe runtime fails with below error
TypeError: Cannot read property '_expect$' of undefined
sample code attempting to override:
import { Selector } from "testcafe";
fixture`Getting Started`.page`http://devexpress.github.io/testcafe/example`;
test("My first test", async (t) => {
t = modify(t);
await t.typeText("#developer-name", "John Smith").click("#submit-button");
// Use the assertion to check if the actual header text is equal to the expected one
await t
.expect(Selector("#article-header").innerText)
.eql("Thank you, John Smith!");
});
function modify(t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expecte has been used");
return prevExpect(param);
};
return t;
}
Also, when using t.click(Selector(...).expect(...), It doesn't use my overwritten expect. How to make it work in the call chain as well?
Technically, it's possible to overwrite the expect method, but please note that this approach may lead to incorrect work and unexpected errors.
You need to modify your modify function as follows:
function modify (t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expect has been used");
return prevExpect.call(t, param);
};
return t;
}
As for the t.click(Selector(...).expect(...) issue, you call the expect method of Selector, but Selector does not have the expect method.
You need to add ) after Selector:
await t.click(Selector(...)).expect(...)
Related
I need to set negation for some text content and tried the code below but as it isn't stated in the docs I expected it to fail and it sure did, so I would like to know how could I possibly achieve negation in this case.
await expect(element(by.id('myElemId'))).not.toHaveText('some text')
Unfortunately I don' think Detox has the ability to use the .not property of expect
However you could so something like this:
First create a function that returns a boolean if a specific text phrase exists. We use the fact that if a value doesn't exist it will throw and error, by wrapping it in a try/catch we can return a boolean that we can then use in our tests.
async function hasText (id, text) {
try {
await expect(element(by.id(id))).toHaveText(text);
return true;
} catch (err) {
return false;
}
}
You can then use it in the following way throwing an error if it returns true for having the text.
it('should not have some text', async () => {
await expect(element(by.id('myElemId'))).toBeVisible();
let result = await hasText('myElemId', 'some text');
// so if the text exists it will return true, as we don't want it to exist then we can throw our own error.
if (result) {
throw new Error('Should not have some text, but did.');
}
});
I know that this is not an elegant solution to the problem, and it would be much nicer if Detox gave us the APIs we needed but I suppose that this could be used in a pinch.
As of Detox version 17.11.4 you can do this
await expect(element(by.id(options.testID))).toBeNotVisible()
or
await expect(element(by.text(options.text))).toBeNotVisible()
This is the correct way to do it using the recommended setup with Jest.
My CasperJS asserts seem to be overly strict. I have a function where I am trying to test the names of client logo images from an array, using Casperjs. However I do not seem to be able to use a variable from a forLoop in casperJS.
I understand there are probably hoisting issues that I am not accounting for, but this does not seem to be the primary problem. I have tried several things to resolve hoisting issues, such as immediately invoked functions, try catch blocks, and using ES6 term "Let" in my loop. None seem to work. Then I notice if I simply hard-code the string my variable should represent, and stick a console.log into my assert of a PASSING test, right before the return, the passing test fails.
Here is my failing code
var clients = 'https://www.google.com/';
var logoArray = ["images/logos/AC.png", "images/logos/Affiny.png", "images/logos/ffintus.png", "images/logos/agileAsset.png"]
function checkClientsArrayTest() {
casper.test.begin('The layout is as expected', 10, function suite(test) {
casper.start(clients, function () {
casper.then(function () {
for (var i = 0; i < logoArray.length; i++) {
try { throw i }
catch (ii) {
console.log(ii);
console.log(i);
test.assertEvalEquals(function () {
return document.querySelectorAll('div.client_logo a img')[ii].getAttribute('src')
.match(logoArray[ii]).toString();
}, logoArray[ii], 'Test searches for Client Logos in DOM.');
}
}
});
}).run(function () {
test.done();
});
});
}
If I change logoArray[ii] to a hardcoded string from the first index of the array, it passes. If I consolelog logoArray[ii], it seems to be what I expect. But if I pass a variable to the assert, or even stick a console.log inside of it, the test fails with the following
Running check for the layout of URL: https://www.google.com
0
0
FAIL Test searches for Client Logos in DOM.
type: assertEvalEquals
file: headlessTester.js
subject: null
fn: undefined
params: undefined
expected: "images/logos/AC.png"
Is this an issue of me getting hoisting wrong (shouldn't fail by sticking in a logger if this is the case afaik), or is this due to strictly structured asserts in CasperJS?
In my application, I have the following code.
case ADD_MOVEMENT:
let am_selectedTrainerMovements = state.selectedTrainerMovements;
state.trainerMovements.forEach(movement => {
if (movement.id === action.movement.id) {
am_selectedTrainerMovements.push(movement);
}
});
return {
...state,
selectedTrainerMovements: am_selectedTrainerMovements
};
break;
In the reducer I use this case. But this gives me an error saying "the push method cannot be invoked on immutable data structure"
What am I doing wrong here?
You set am_selectedTrainerMovements equal to state.selectedTrainerMovements and so you are just creating a new pointer to the exact same object. So when you call am_selectedTrainerMovements.push to are trying to change the state which is immutable.
You you need to clone state.selectedTrainerMovements, for instance:
let am_selectedTrainerMovements =
Object.assign({}, state. state.selectedTrainerMovements);
For some reason, my code is unable to retrieve the IAsyncOperation object that is returned upon calling captureFileAsync method of the Windows.Media.Capture.CameraCaptureUI() method. The IAsyncOperation object is returned according to this documentation. In that documentation link, it states:
Return value
Type: IAsyncOperation<StorageFile>
When this operationcompletes, a StorageFile object is returned.
So here is my code:
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 4, height: 3 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
appSession.InAsyncMode = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).done(function (file) {
if (file) {
self.addPage(URL.createObjectURL(file));
} else {
WinJS.log && WinJS.log("No photo captured.", "sample", "status");
}
}, function (err) {
// None taken
});
When I inspect the value of appSession.InAysncMode, I see that the function returns undefined. I suspect it returns undefined because the operation is not complete (i.e. the user has not yet created the photo, and it has not been saved to disc), but I need it in order to cancel out of the camera capture mode programmatically. Does anybody know why it would return undefined instead of the documented IAsyncOperation object?
Thanks!
For reference, here's the answer I posted on the MSDN forum.
To answer your ending question, you can cancel the capture UI by canceling the promise from dialog.captureFileAsync.
Your InAsyncMode flag is undefined because you're assigning to it the return value from captureFileAsync.done() which is, by definition, undefined. It has nothing to do with the API's success.
In the docs, when you see IAsyncOperation, what you get in JavaScript is a promise that will deliver as a result to the completed handler if it succeed. You never see IAsyncOperation or related interfaces in JavaScript directly. The documentation for WinRT is written to be language-neutral, so it's important to understand how those things show up in JS (as promises). In C# you don't see it either, as you just use the await keyword. It's mostly in C++ that you actually encounter the interface.
Anyway, you I believe you want is something along the lines of the code below, where you could eliminate IsAsyncMode in favor of just checking for a non-null promise:
appSession.capturePromise = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo);
appSession.IsAsyncMode = (appSession.capturePromise != null);
//This will close the capture UI after 5 seconds--replace with whatever logic you need
setTimeout(function () { appSession.capturePromise.cancel(); }, 5000);
appSession.capturePromise.done(function (file) {
if (file) {
} else {
}
}, function (err) {
appSession.IsAsyncMode = false;
appSession.capturePromise = null;
});
I dont think minInvocation or maxInvocation is equivalent to times() in Mockito. Is there?
Please see this questions: Major difference between: Mockito and JMockIt
which has not been answered yet by anyone.
Edit
I found the answer myself: Adding it here for others who need this answered:
The solution is to use DynamicPartialMocking and pass the object to the constructor of the Expectations or NonStrictExpectations and not call any function on that object.
Then in the Verifications section, call any function on the object for which you want to measure the number of invocations and set times = the value you want
new NonStrictExpectations(Foo.class, Bar.class, zooObj)
{
{
// don't call zooObj.method1() here
// Otherwise it will get stubbed out
}
};
new Verifications()
{
{
zooObj.method1(); times = N;
}
};
I found the answer myself: Adding it here for others who need this answered:
The solution is to use DynamicPartialMocking and pass the object to the constructor of the Expectations or NonStrictExpectations and not call any function on that object.
Then in the Verifications section, call any function on the object for which you want to measure the number of invocations and set times = the value you want
new NonStrictExpectations(Foo.class, Bar.class, zooObj)
{
{
// don't call zooObj.method1() here
// Otherwise it will get stubbed out
}
};
new Verifications()
{
{
zooObj.method1(); times = N;
}
};