Karma/Jasmine how to call a method on an angularjs Factory - karma-jasmine

I need some help getting this test to run. I've spent way to much time on it.
So i am stuck and need some help?
I simply have a factory method, that has one method and i keep getting [Unable to get property 'method1' of undefined or null reference ] errors from Karma.
(function () {
'use strict';
var first = function () {
var method1 = function () {
return 'yes';
};
return {
method1: method1
};
};
angular.module('app').factory('first', [first]);
})();
and here are my attempts to call method1.
describe('Test Suite', function () {
describe('Factory Test', function () {
beforeEach(function () {
module('app');
});
var service;
//beforeEach(inject(function (_first_) {
// service = _first_;
// console.log(JSON.stringify(_first_, null, 4));
//}));
beforeEach(inject(function ($injector) {
service = $injector.get('first');
console.log(JSON.stringify(service, null, 4));
}));
//beforeEach(function () {
// angular.mock.inject(function ($injector) {
// service = $injector.get('first');
// })
//});
describe('calling method1', function () {
var output = service.method1();
expect(output).toBe('yes');
});
});
});
and my output from Karma
IE 11.0.0 (Windows 10 0.0.0) Test Suite Factory Test calling method1 encountered a declaration exception FAILED
TypeError: Unable to get property 'method1' of undefined or null reference
at Anonymous function (tests/firstTest.spec.js:31:13)
at Anonymous function (tests/firstTest.spec.js:30:9)
at Anonymous function (tests/firstTest.spec.js:4:5)
IE 11.0.0 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.135 secs)
IE 11.0.0 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.14 secs / 0.135 secs)

argh, stupid me.
I forgot to add the it("", function(){}) stuff.
thanks

Related

Cypress spy on multiple calls of the same method

I'm trying to check that a method was not called again after a certain action.
My test:
it('if query is less than 3 symbols, api call is not made', () => {
cy.spy(foo, 'bar').as('bar');
cy.get('input').type('12').then(() => {
cy.get('#bar').its('callCount').then(res => {
expect(res).to.eq(1); // a basic check after mounted hook
});
});
});
My component:
async mounted(): Promise<void> {
await this.foo.bar();
}
async getSearchResults(): Promise<void> {
if (this.searchQuery.length < 3) {
return;
}
await this.foo.bar();
}
The problem is that bar was already called on mount, and it could have been called multiple times before, if query length was valid. I was thinking about saving bar's callCount to a variable and checking it after call, but that looks ugly. Kinda stuck here, any ideas are welcome.
It's not an issue. The call count is started at the point you set up the spy, not when the component is mounted.
Try this:
const foo = {
bar: () => console.log('bar called')
}
it('starts with a clean callcount', () => {
foo.bar() // make a call
cy.spy(foo, 'bar').as('bar'); // callCount === 0 on setup
cy.get('#bar')
.its('callCount')
.should('eq', 0) // passes
});
Even if you have some callcount from another test, you can always reset it before the current test:
it('allows reset of spy callCount', () => {
cy.spy(foo, 'bar').as('bar'); // callCount === 0 on setup
foo.bar() // make a call, count is now 1
cy.get('#bar').invoke('resetHistory') // remove prior calls
cy.get('#bar')
.its('callCount')
.should('eq', 0) // passes
});
I believe you can get the initial call count, and then wrap your test in that.
it('if query is less than 3 symbols, api call is not made', () => {
cy.spy(foo, 'bar').as('bar');
cy.get('#bar').its('callCount').then((initRes) => {
cy.get('input').type('12').then(() => {
cy.get('#bar').its('callCount').then(res => {
expect(res).to.eq(initRes); // a basic check after mounted hook
});
});
});
});
You would probably want to do a test that this would fail, to make sure that Cypress is getting '#bar' again.

Why if i created a mock i am still getting error?

i am doing testing, i made a test in that test i create a mock for a fake function
jest.mock('#/services/myService', ()=>({getAvailables: jest.fn().mockReturnValue()}))
that function is running in my component
onMounted(async () => {
const answer = await getAvailables1()
const answer = await getAvailables2()
const answer = await getAvailables3()
but still i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables1) is not a function
(node:81921) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag
if i put like this first getAvailables2
onMounted(async () => {
const answer = await getAvailables2()
const answer = await getAvailables1()
i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables2) is not a function
if i put like this first getAvailables3
onMounted(async () => {
const answer = await getAvailables3()
const answer = await getAvailables2()
i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables3) is not a function
also i try with mockResolvedValue, does not worked
export const getAvailables = async () => {
let response
let error
try {
response = await getData()
} catch (err) {
error = err
throw err
}
return { response, error }
}
It looks like you want a mock partial:
jest.mock('#/services/myService', () => {
const originalModule = jest.requireActual('#/services/myService');
return {
__esModule: true,
...originalModule,
getAvailables1: () => Promise.resolve({ foo: 'bar' }),
getAvailables2: () => Promise.resolve({ foo: 'baz' }),
getAvailables3: () => Promise.resolve({ foo: 'bad' }),
/* any other method of your service that gets called */
};
});
This will mock the provided functions in the mock while the rest of the service will function as in the original.
getAvailables() is async function that always returns a promise.
So, in order to mock that function you need to return the mock promise with success or rejected value.
Following is the example of mocking that function which returns success promise.
jest.mock('#/services/myService', () => ({
getAvailables: jest.fn().mockResolvedValue(true)
}))

Why does my cypress e2e test never complete?

I have this cypress e2e tests.
/// <reference types="Cypress" />
describe('Toss Full Test', function () {
let polyfill;
const uuid = Cypress._.random(0, 1e6)
before(() => {
const polyfillUrl = 'https://unpkg.com/whatwg-fetch#3.0.0/dist/fetch.umd.js';
cy.request(polyfillUrl).then(response => {
polyfill = response.body;
});
});
Cypress.on('window:before:load', win => {
delete win.fetch;
win.eval(polyfill);
});
const SubscribeEmail = "tosstests" + uuid + "#yopmail.com";
const SubscribePassword = "tossTests123456!!";
const SubscribeLogin = "tosstests" + uuid;
it('Full process', function (win) {
cy.server();
cy.visit("/");
cy.route('POST', '/api/account/register').as('register');
//this could be lagging as ravendb is starting
cy.get("#LinkLogin", { timeout: 20000 }).click();
//register
cy.get("#LinkRegister").click();
cy.get("#NewEmail").type(SubscribeEmail);
cy.get("#NewName").type(SubscribeLogin);
cy.get("#NewPassword").type(SubscribePassword);
cy.get("#NewConfirmPassword").type(SubscribePassword);
cy.window()
.then(win => {
// disables runCaptcha
win.runCaptcha = new win.Function(['action'], 'return Promise.resolve(action)');
})
.then(
() => {
cy.get("#BtnRegister").click();
cy.wait('#register');
cy.get('#register').then(function (xhr) {
expect(xhr.status).to.eq(200);
});
}
);
})
})
The full code can be found here https://github.com/RemiBou/Toss.Blazor/tree/master/Toss.Tests.E2E.Cypress.
When I run my project with the following code
docker-compose up -V ravendb web
./node_modules/.bin/cypress open
The code runs well, the assertion "expect(xhr.status).to.eq(200);" returns true but the test execution never stops. Why is that ?
After a lot of trial and error I just needed to remove the "win" parameter from the method in the "if" call which was a test for getting a window reference. In fact this parameter is a callback you need to call at the end of the tests, I can't find any documentation about it.

Unit Test Rxjs 5

I am trying to write a test using mocha and chai for my observable methods that makes a call to a server and returns some json data. However, when I run the test I get the following error:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Even when I overwrite the default timeout time, I still get the above error. What am I doing wrong ?
describe("some test", () => {
let someClass: SomeClass;
before(() => {
someClass = new SomeClass();
});
;
it("should meet some condition", done => {
let getData = someClass.getData('query')
getData.subscribe(json => {
json.success.should.equal(true);
done();
},
done
);
});
});
I found a solution, I call done() in the before hook and the set timeout on each it() function.
describe("some test", () => {
let someClass: SomeClass;
before((done) => {
someClass = new SomeClass();
done();
});
;
it("should meet some condition", done => {
let getData = someClass.getData('query')
getData.subscribe(json => {
json.success.should.equal(true);
done();
},
done
);
}).timeout(10000);
});

Intermittent Selenium ECONNREFUSED errors on CircleCI

Our CircleCI tests use selenium, via the selenium-webdriver to run UI tests through PhantomJS. The tests work 100% of the time locally in our vagrant env, but fail about 1 out of 3 times on CircleCI with ECONNREFUSED errors like:
Error: ECONNREFUSED connect ECONNREFUSED 10.0.4.1:59525
at ClientRequest.<anonymous> (node_modules/selenium-webdriver/http/index.js:238:15)
at Socket.socketErrorListener (_http_client.js:310:9)
at emitErrorNT (net.js:1278:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
From: Task: WebDriver.navigate().to(http://127.0.0.1:8080/src/public/login.php?t=ur&ign=1&ut=ad)
at thenableWebDriverProxy.schedule (node_modules/selenium-webdriver/lib/webdriver.js:816:17)
at Navigation.to (node_modules/selenium-webdriver/lib/webdriver.js:1140:25)
at thenableWebDriverProxy.get (node_modules/selenium-webdriver/lib/webdriver.js:997:28)
at User.logIn (testJs/ui/utils/user.js:9:16)
at Host.logInAsHost (testJs/ui/utils/host.js:13:14)
at Preferences.disableRevenueGeneration (testJs/ui/utils/preferences.js:57:14)
at Context.<anonymous> (testJs/ui/tests/preferences.js:13:22)
These errors happen at random times throughout our tests and they are not being triggered by any particular place in our tests. As far as I can tell, this issue is occurring on the selenium/selenium-webdriver end as the web server remains up and working and isn't generating any errors.
I’ve tried all of the following and none of them have worked:
Upgraded to the latest selenium-webdriver (3.4.0)
Upgraded to a more recent version of nodejs (6.9.2)
Used a different web server
Upgraded to a recent version of PhantomJS (1.9.7-15)
Tried using export DBUS_SESSION_BUS_ADDRESS as per
https://github.com/SeleniumHQ/docker-selenium/issues/87
In node_modules/selenium-webdriver/http/index.js, I modified the code to retry for ECONNREFUSED errors by reusing the retry already there for ECONNRESET, i.e. if (e.code === 'ECONNRESET') { becomes if (e.code === 'ECONNRESET' || e.code === 'ECONNREFUSED') {. This doesn’t work as then selenium-webdriver just retries indefinitely and from this I realized that the issue appears to be that once an ECONNREFUSED error is encountered, selenium/selenium-webdriver are unrecoverable.
Has anyone found a solution?
WARNING: This is merely a hack and is by no means a proper solution, but it is the only one that appears to reliably work for us on CircleCI. Hopefully, someone else will find a better solution.
Our test framework, mocha, appears to have a retry mechanism developed specifically for selenium (go figure): http://mochajs.org/#retry-tests. The first gotcha is that code in after and before is not retried. Therefore, you need to move code to beforeEach and afterEach. The second gotcha is that you need some special logic in beforeEach and afterEach to handle driver errors.
So, in order to utilize this mechanism, we had to refactor our tests so that each test has a beforeEach that sets up a fresh webdriver instance and then an afterEach that quits that driver instance. This way, a crashed driver instance doesn’t stop all subsequent tests. We developed a helper function that we call at the beginning of all describe blocks so that we don’t have to add too much code to our tests.
Then, we added this.retries(10) to our topmost describe block.
Here is the helper class:
var webdriver = require('selenium-webdriver');
// We default to using phantomjs, but in the future, when we run tests in other browsers, e.g. via
// SauceLabs, we'll want to change the browser.
var customPhantom = webdriver.Capabilities.phantomjs();
customPhantom.set('ssl-protocol', 'any');
// For convenience in tests
global.By = webdriver.By;
global.until = webdriver.until;
var SeleniumStabilizer = function () {};
SeleniumStabilizer.prototype.MAX_RETRIES = 10;
SeleniumStabilizer.prototype.createDriver = function () {
global.driver = new webdriver.Builder()
// .forBrowser('phantomjs')
.withCapabilities(customPhantom)
.build();
// Resolves when driver is ready
return global.driver;
};
SeleniumStabilizer.prototype.init = function (opts) {
var self = this,
n = 0;
var beforeEachWithRetries = function () {
// Create a fresh selenium driver for the next test
return self.createDriver().then(function () {
if (opts.onBeforeEach) {
// Execute the test-specific defined onBeforeEach
return opts.onBeforeEach();
}
}).catch(function (err) {
// ECONNREFUSED error and we should retry?
if (err.message.indexOf('ECONNREFUSED') !== -1 && n++ < self.MAX_RETRIES) {
return beforeEachWithRetries();
} else {
throw err;
}
});
};
opts.beforeEach(function () {
n = 0;
return beforeEachWithRetries();
});
var afterEachWithRetries = function () {
return Promise.resolve().then(function () {
if (opts.onAfterEach) {
// Execute the test-specific defined onAfterEach
return opts.onAfterEach();
}
}).then(function () {
// Quit the selenium driver before starting the next test
return driver.quit();
}).catch(function (err) {
// ECONNREFUSED error and we should retry?
if (err.message.indexOf('ECONNREFUSED') !== -1 && n++ < self.MAX_RETRIES) {
// Create a new driver
return self.createDriver().then(function () {
return afterEachWithRetries();
});
} else {
throw err;
}
});
};
opts.afterEach(function () {
n = 0;
return afterEachWithRetries();
});
};
Then, your tests look like:
var seleniumStabilizer = new SeleniumStabilizer();
describe('my tests', function () {
this.retries(seleniumStabilizer.MAX_RETRIES);
describe('search engines', function () {
seleniumStabilizer.init({
beforeEach: beforeEach,
afterEach: afterEach,
onBeforeEach: function () {
// e.g. return doPromiseAfterDriverSetUp();
},
onAfterEach: function () {
// e.g. return doPromiseBeforeDriverQuits();
}
});
it('should get google', function () {
return driver.get('https://www.google.com');
});
it('should get amazon', function () {
return driver.get('https://www.amazon.com');
});
});
});