I have converted my fetch calls to use breeze.EntityQuery but how can I write my unit tests to mock the breeze client? Here is my code for the unit test fetch call that I'm trying to write for breeze.
class HttpStub {
fetch(url) {
var response = this.itemStub;
this.url = url;
return new Promise((resolve) => {
resolve({ json: () => response });
});
}
configure(func) {}
}
describe('Order', () => {
var sut, http, itemStubs, itemFake;
beforeEach(() => {
http = new HttpStub();
sut = new Order(http);
itemStubs = [1];
itemFake = [2];
http.itemStub = itemStubs;
});
describe('getOrders', () => {
it('should return orders', (done) => {
var info = new Info("1", "C", null, null);
sut.getOrders(info).then(result => {
expect(result).toBe(itemStubs);
expect(result).not.toBe(itemFake);
done();
});
});
});
});
Try using the jasmine spyOn function with callFake. Jasmine's spies are an easier way to mock a function call.
beforeEach(function () {
spyOn(httpClient, "fetch").and.callFake(function () {
return new Promise(function (resolve, reject) {
var fetchResponse = "the fake response";
resolve(fetchResponse);
});
});
});
An example (with TypeScript)
import { HttpClient } from "aurelia-fetch-client";
import { autoinject, Container } from "aurelia-framework";
#autoinject
export class DemoClass {
constructor(private httpClient: HttpClient) { }
public UseTheHttpClient() {
return this.httpClient.fetch("some_url");
}
}
describe("the demo class", function () {
let container: Container = new Container();
let httpClient: HttpClient = new HttpClient(); // create an http client
container.registerInstance(HttpClient, httpClient);
let demoClass: DemoClass = container.get(DemoClass);
beforeEach(function () { // spy on that HTTP client
spyOn(httpClient, "fetch").and.callFake(function () {
return new Promise(function (resolve, reject) {
resolve("some_fake_response");
});
});
});
it("returns the fake response", function (done) {
demoClass.UseTheHttpClient().then((response) => {
expect(response).toBe("some_fake_response");
done();
});
});
});
Related
I am trying to create a framework for API tests using cypress and I am facing an issue accessing the data between tests using an alias. Is there something that I am missing?
custom.js
Cypress.Commands.add('getResource', function (uri) {
cy.request({
url: uri,
method: 'GET'
}).then(function (response) {
return cy.wrap(response);
});
});
test.js
exports.__esModule = true;
context('requests', function () {
it('validate get call response', function () {
let re = cy.getResource('https://reqres.in/api/users?page=2','resp')
re.then(function (response) {
cy.wrap(response.body).as('respbody');
cy.wrap(response.status).as('respstatus');
//cy.log(JSON.stringify(response.body));
});
});
it('Tests test', function () {
cy.wait('#respbody').then((body) => {
console.log(JSON.stringify(body));
});
});
});
cypress version - 8.2.0
By design cypress cleans up aliases after each test. So you can do something like this cypress recipe
Your getResource custom command is taking just one parameter, hence we are passing just one papameter.
exports.__esModule = true;
let responseBody;
let responseStatus;
context('requests', () => {
before(() => {
cy.getResource('https://reqres.in/api/users?page=2')
.then(function(response) {
responseBody = response.body
responseStatus = response.status
})
})
beforeEach(() => {
cy.wrap(responseBody).as('responseBody')
cy.wrap(responseStatus).as('responseStatus')
})
it('Get Response status', function() {
cy.wait('#responseStatus').then((responseStatus) => {
console.log(responseStatus)
})
})
it('Get Response Body', function() {
cy.wait('#responseBody').then((responseBody) => {
console.log(JSON.stringify(responseBody))
})
})
})
module.js
var Promise = require('bluebird');
var XMLHttpRequest = require('xhr2');
function fetchdata(id) {
var url = 'http://www.youtube.com/watch?v=' + id;
return new Promise(function (fulfill, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
var jsonStr;
try {
fulfill(xhr.response);
} catch (e) {
reject(jsonStr);
}
};
xhr.onerror = function(e) {
reject(e);
};
xhr.send('');
});
}
module.exports = {
getdata: function (videoID) {
return new Promise(function (fulfill, reject) {
if (!videoID) {
reject(new Error('Unable to get video id.'));
return;
}
fetchdata(videoID).then(
function (d) {
console.log( d);
}
);
});
}
};
index.js
var parser = require('./module.js');
parser.getdata("ZI4tRn4dOGg", function (data) {
console.log(data);
}
)
I tried to get youtube view page source code with xmlhttprequest.
BUT above code does not finish. I guess it is waiting for something.
Is problem from bluebird? or xhr2? and why does this code never finish?
Your xhr instance had a memory leak, might be a problem with the library, last publish was a year ago. Bluebird was ok. You can fix the hangup by using node-fetch and dropping in this replacement for fetchdata
const fetch = require('node-fetch')
function fetchdata(id) {
var url = 'http://www.youtube.com/watch?v=' + id;
return fetch(url).then(res => res.text())
}
I have the following code to return all the keys in the level DB in Node.js app, this is a method in a ES6 class:
class LevelDB {
constructor() {
this.db = level(chainDB);
}
getAllItems() {
let self = this;
return new Promise(function(resolve, reject){
self.db.createKeyStream()
.on('data', function (data) {
resolve(data);
})
.on('error', function (err) {
reject(err)
});
}
}
The database is created successfully.
What I'm notice is that the on data or on error is never fired? Im new using level so any help will be appreciate.
This solve the issue;
I just realize that I need to wait for the Stream close:
class LevelDB {
constructor() {
this.db = level(chainDB);
}
getAllItems() {
let self = this;
let dataArray = [];
return new Promise(function(resolve, reject){
self.db.createKeyStream()
.on('data', function (data) {
dataArray.push(data);
})
.on('error', function (err) {
reject(err)
})
.on('close', function () {
resolve(dataArray);
})
}
}
I need to fetch some real data in my tests from a remote url. I Superagent is not being mocked. I have done that by including node_modules/superagent/ in unmockedModulePathPatterns.
This is the file I am trying to test, the .end() function is never called.
This is my test, which fails with a timeout error.
jest.dontMock("../Stocks.js");
jest.dontMock("superagent");
describe("Stock Actions", () => {
var makeRequest = require('../Stocks')
pit("doesn't crash", function () {
var promise = makeRequest("Hello World")
promise.then(function (str) {
expect(str).toBe("yay");
});
return promise;
});
});
And this is the module it's trying to test:
import Reflux from 'reflux';
import request from 'superagent';
console.log("request-superagent", request)
const makeRequest = Reflux.createAction({ asyncResult: true });
const Store = Reflux.createStore({
init() {
this.listenTo(makeRequest, 'onMakeRequest');
},
onMakeRequest(url) {
request('GET', 'http://api.example.com/list/')
.end(function (err, res) {
console.log("res.text", res.text);
if (!res.ok) {
makeRequest.failed("aw");
}
makeRequest.completed("yay");
});
}
});
module.exports = makeRequest;
How do I use superagent in jest-cli?
As I want to implement a chat in AngularJS, I want to use the promise/deferred principle. My ChatService looks like the following:
factory('ChatService', ['$q', '$resource', function($q, $resource) {
var Service = {};
var connected = false;
var connection;
var chatResource = $resource('/guitars/chat/:action', {action: '#action'}, {
requestChatroomId: {
params: {
action: 'requestChatroomId'
},
method: 'GET'
},
sendMessage: {
params: {
action: 'sendMessage'
},
method: 'POST'
}
});
Service.connect = function(cb) {
var deferred = $q.defer();
chatResource.requestChatroomId(function(data) {
connection = new WebSocket('ws://127.0.0.1:8888/realtime/' + data.chatroomId);
connection.onerror = function (error) {
deferred.reject('Error: ' + error);
};
connection.onmessage = function (e) {
cb.call(this, e.data);
deferred.notify(e.data);
};
connected = true;
});
return deferred.promise;
};
Service.sendMessage = function(msg) {
if(!connected) {
return;
}
chatResource.sendMessage({message: msg});
}
return Service;
}])
My controller using the ChatService is:
app.controller('ChatCtrl', ['$scope', 'ChatService', function($scope, ChatService) {
$scope.chat = {};
$scope.chat.conversation = [];
var $messages = ChatService.connect(function(message) {
$scope.$apply(function() {
// #1 THIS FIRES EVERY TIME
$scope.chat.conversation.push(message);
});
});
$messages.then(function(message) {
console.log('Finishes - should never occur!')
}, function(error) {
console.log('An error occurred!')
}, function(message) {
// #2 THIS FIRES ONLY IF THERE IS AN INTERACTION WITH THE ANGULAR MODEL
console.log(message);
});
$scope.sendMessage = function(event) {
ChatService.sendMessage($scope.chat.message);
$scope.chat.message = '';
};
}]);
If something is pushed from the server, callback #1 is called, but callback #2 wont be called until there is some interaction with the angular-model, i.e. start writing something in the input-Box. What is the reason for that behaviour?
Okay the reason was, that AngularJS was not aware of a change. So I injected the $rootScope to my ChatService:
factory('ChatService', ['$q', '$resource', '$rootScope', function($q, $resource, $rootScope) {
and in connection.onmessage I called $apply() on $rootScope:
connection.onmessage = function (e) {
deferred.notify(e.data);
$rootScope.$apply();
};