Detox - Possible to Force Fail Test? - react-native

Is there a way to force a test to fail in Detox? I haven't found anything in the documentation that says this can be the case. I am comparing two IDs that are hidden in an element and screen of my app and if they don't match, I want to fail the test.
if (element.id === screen.id) {
do
}
else {
*fail test*
}
it(`should invite User`, async () => {}
Or is it as easy as just throwing an error? Thanks

Detox itself delegates test logic to a test runner.
Detox delegates the actual JavaScript test-code execution to a dedicated test-runner. It supports the popular Jest and Mocha out of the box.
If you are using jest as the underlying test runner, you could just use its fail method as follows.
if (element.id === screen.id) {
do
}
else {
fail('test fails');
}
In mocha you could use the following function.
assert.fail("actual", "expected", "Error message");
We could also abuse the detox high level api to achieve the same (but less readable).
await waitFor(element(by.id(notVisible.id))).toBeVisible().withTimeout(5);

Related

Mock or spyOn location.reload in angular unit testing

I have the function with location.reload(). How to write the angular unit test cases for test that reload functionality.
searchregion(){
location.reload();
}
I tried to written the test cases like below. But it shows error "Error: : could not find an object to spy upon reload()":
it('should test the reload functions', () =>{
spyOn(location, 'reload');
component.searchregion();
expect(location.reload).toHaveBeenCalled();
});
Can anyone please help me on this?

Detox with Split.IO

I found a jest mock for split.io for react-native. I am now trying to use this mock so that I do not receive network timeouts because split.io is trying to sync in the background. Here is the mock:
jest.mock('#splitsoftware/splitio-react-native', () => {
const splitio = jest.requireActual('#splitsoftware/splitio-react-native');
return {
...splitio,
SplitFactory: () => {
return splitio.SplitFactory({
core: {
authorizationKey: 'localhost',
},
// Mock your splits and treatments here
features: {},
sync: {
localhostMode: splitio.LocalhostFromObject(),
},
});
},
};
});
I currently put this in my detox init.js file, but it doesn't seem to be doing anything. The only way, so far, I have been able to get my tests to run is to just immediately destroy my SplitFactory as soon as I create it (not through the mock). Obviously, this isn't ideal since I'd have to change the code every time I wanted to run it. I tried creating a .mock.ts file, but that also didn't get read, and when I tried to adjust my metro.config.js, it just failed to run at all. Does anyone have any ideas of how I can get this to run properly in detox for iOS, or have experience with this?
I had the same issue with split.io and detox, when a particular split.io would block my tests indefinitely. The only work around i found was
await device.disableSynchronization();
found here

mocha programmatically set vue error handler

I find myself writing this at the start of pretty much all of my unit tests in mocha:
it('should do something', (done) => {
Vue.config.errorHandler = done;
// do something aynchronous
});
By default, Vue catches all errors itself and logs them to the console, so mocha can't see them. This code makes sure that thrown errors fail the tests.
Is there a way with mocha to do this without having to start every single async test with this line of code? If I have to write / use a plugin, that's fine.
Try:
Vue.config.errorHandler = function (err, vm, info) {
throw err
}
in your test entry.

Qunit beforeEach, afterEach - async

Since start(), stop() will be removed in Qunit 2.0, what is the alternative for async setups and teardowns via the beforeEach, afterEach methods? For instance, if I want the beforeEach to wait for a promise to be finished?
QUnit basically wants people to stop using the global methods (not just start() and stop(), but also test(), expect(), etc). So, as of version 1.16.0, you should always use either the global namespace (QUnit) or the assert API argument passed into the test() functions. This includes the new async control:
QUnit.test( "testing async action", function( assert ) { // <-- note the `assert` argument here
var done = assert.async(); // tell QUnit we're doing async actions and
// hold onto the function it returns for later
setTimeout(function() { // do some async stuff
assert.ok( true, "This happened 100 ms later!" );
done(); // using the function returned from `assert.async()` we
// tell QUnit we're don with async actions
}, 100);
});
If you are familiar with the old start() and stop() way of doing things, you should see that this is extremely similar, but more compartmentalized and extensible.
Because the async() method call is on the assert argument into the test, it cannot be used in the beforeEach() function. If you have an example of how you were doing that before, please post it and we can try to figure out how to git it into the new way.
UPDATE
My mistake previously, the assert object is being passed into the beforeEach and afterEach callbacks on modules, so you should be able to do the same logic that you would do for a test:
QUnit.module('set of tests', {
beforeEach: function(assert) {
var done = assert.async();
doSomethingAsync(function() {
done(); // tell QUnit you're good to go.
});
}
});
(tested in QUnit 1.17.1)
Seeing that nobody has answered the beforeEach/afterEach part: a test suite is supposed to run as soon as the page loads. When that is not immediately possible, then resort to configuring QUnit:
QUnit.config.autostart = false;
and continue with setting up your test suite (initializing tests, feeding them to QUnit, asynchronously waiting for some components to load, be it AJAX or anything else), your site, and finally, when it's ready, just run:
QUnit.start();
QUnit's docsite has it covered.
Ember Qunit, has once exists beforeEach/setup, afterEach/teardown co-exist for a little while.
See PR: https://github.com/emberjs/ember-qunit/pull/125

How to set jasmine for karma e2e for testing angular app?

I try to create e2e tests with karma and jasmine with yeoman. In my karma-e2e.conf.js I add jasmine:
files = [
JASMINE,
JASMINE_ADAPTER,
ANGULAR_SCENARIO,
ANGULAR_SCENARIO_ADAPTER,
'test/e2e/**/*.js'
];
A need async testing so I need to use runs, waits, waitsFor (https://github.com/pivotal/jasmine/wiki/Asynchronous-specs)
But if I try to use it:
it('test', function () {
runs(function () {
...
});
});
Scenatio test runner returns this:
TypeError: Cannot call method 'runs' of null
at runs (http://localhost:8080/adapter/lib/jasmine.js:562:32)
at Object.<anonymous> (http://localhost:8080/base/test/e2e/eduUser.js:42:3)
at Object.angular.scenario.SpecRunner.run (http://localhost:8080/adapter/lib/angular-scenario.js:27057:15)
at Object.run (http://localhost:8080/adapter/lib/angular-scenario.js:10169:18)
I don't know where the problem is. Can you help me please?
Angular e2e tests with Karma don't and can't use the JASMINE adapter. Instead you have the ANGULAR_SCENARIO_ADAPTER which has a similar feel to writing Jasmine tests.
All commands in the adapter's API are asynchronous anyway. For example element('#nav-items').count() doesn't return a number, it returns a Future object. Future objects are placed in a queue and executed asynchronously as the runner progresses. To quote the API docs:
expect(future).{matcher}:
[...] All API statements return a future object, which get a value assigned after they are executed.
If you need to run your own asynchronous test code, you can extend the adapter's DSL, this is easier than it might sound. The idea is that you return your own Future which can be evaluated by a matcher such as toBe(). There are some examples on how to do this in the e2e-tests.js Gist from Vojta. Just remember to call done(null, myRetrunValue); when your test code is successful (myRetrunValue is the value evaluated by your matcher). Or done('Your own error message'); if you want the test to fail.
UPDATE: In response to question below. To simulate a login, first add a function called login to the dsl:
angular.scenario.dsl('login', function() {
return function(selector) {
// #param {DOMWindow} appWindow The window object of the iframe (the application)
// #param {jQuery} $document jQuery wrapped document of the application
// #param {function(error, value)} done Callback that should be called when done
// (will basically call the next item in the queuue)
return this.addFutureAction('Logging in', function(appWindow, $document, done) {
// You can do normal jQuery/jqLite stuff here on $document, just call done() when your asynchronous tasks have completed
// Create some kind of listener to handle when your login is complete
$document.one('loginComplete', function(e){
done(null, true);
}).one('loginError', function(e){
done('Login error', false);
});
// Simulate the button click
var loginButton = $document.find(selector || 'button.login');
loginButton.click();
})
};
});
And then call:
beforeEach( function()
{
expect( login('button.login') ).toBeTruthy();
});