I'm doing some multi user testing for my AngularJS controllers, as my users have different roles and settings. The first one always works great, but subsequent attempts never issue attempts for HTTP mock requests, as the controllers are singletons. Is there any way for me to clear out all existing controllers, or even the whole Angular module setup and start it back up again so I can perform these types of tests?
Have you tried creating your controller in a beforeEach function? This way your controller will be recreated for each test.
beforeEach(inject(function ($rootScope, $controller, $location) {
root = $rootScope;
scope = $rootScope.$new();
location = $location;
controller = $controller('AccountInfoController', { $scope: scope, $location:$location, customer: customer });
}));
try this code if you want clear module
angular.module('app',[]);
Related
I'm implementing a web-scraping script for a website which will collect some useful information.
Script is implemented using Puppeteer library and is basically a set of instructions like:
Start a headless chrome
Open new tab/page
Get some pagination links from the HTML
Open every pagination link found and scrape some information from HTML
I'm looking for some way of testing this functionality. Ideally, what I want to do is to "pre-save" the real HTML responses in test folder and then mock the external website responses (making sure they always are the same). And then assert that collected information is correct.
I'm familiar with several tools which are able to mock endpoints for fetch function in the browser. I'm looking for something similar but for Puppeteer.
So far, the only solution I'm thinking about is to use browser instance as a dependency for my script. And then mock the newPage method of the browser to return a page with custom interceptor. This looks like a lot of work though.
Any other solution for this?
A simple solution is to store the HTML page you want to test (or parts of it) locally and open it in Puppeteer. It is possible to open local HTML websites in Puppeteer. Then the result can be tested in a Javascript test framework like Mocha or Jest.
If you need a real web server for the tests, another option is to use a library like Express to serve local HTML pages as a mock for a web server response. You can find an example in this search engine scraper which contains tests for scraping various search engines.
It is also possible to mock and stub Puppeteer functions like launch, goto and $eval. This approach requires a lot of stubbed methods.
This is something I am playing around with at the moment.
I got this working by setting setRequestInterception:
it('responds', () => {
return (async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', request => {
// TODO: match request.url()
request.respond({
content: 'application/json',
headers: {"Access-Control-Allow-Origin": "*"},
body: JSON.stringify({foo: 'bar'})
})
});
res = await page.goto('https://example.com');
json = await res.json()
await browser.close();
expect(json).toStrictEqual({"foo": "bar"})
})();
})
This also looks to be a useful tool: https://github.com/jefflau/jest-fetch-mock. Maybe it could be handy to match requests etc
Also see: Best way to intercept XHR request on page with Puppeteer and return mock response
I want to test my models, and their integration with my REST API, using the Ember testing framework which ships with Ember CLI, but requests, using my RESTAdapter settings are not being made in my tests, within my model tests. As it stands, any call to save() on a model will cause all tests following it to not execute:
Here is a test I made to check interaction with the server (REST API):
test "store can be used to send data to server", ->
store = #store()
Ember.run ->
cpanel = store.createRecord "item"
cpanel.save().then((response) =>
equal(response.status, 200)
)
This completely blocks all tests following this one; furthermore, no requests are made to the server, when monitoring the Network tab in Chrome dev tools:
A friend advised me to use the QUnit Async Helper, but when using that, I find that this.store() is undefined (perhaps the Ember QUnit Adapter decided to leave out support for async testing helpers?):
asyncTest "Async creates account on server", ->
expect(2)
store = #store()
Ember.run =>
account = store.createRecord("account", {
siteName: "sample account"
url: "http://url.com"
})
account.save().then((response) =>
equal(response.status, 200)
ok account
start()
)
How can I write an async test for my individual models, and test their integration with my REST API using the Ember QUnit framework in Ember CLI without having to write integration tests?
I'm not sure where status is coming from, the promise of save returns the record, not the response from server.
In order to use start, you must use stop first.
stop();
someAsyncCall(function(){
start();
});
And the store is only injected into routes and controllers, and isn't in scope of your tests. You'll need to use the container to get the store.
store = App.__container__.lookup('store:main');
It'd look something like this:
test("save a record", function(){
var record,
store = App.__container__.lookup('store:main');
stop();
Em.run(function(){
record = store.createRecord('color', {color:'green'});
record.save().then(function(){
start();
equal(record.get('id'), 1);
});
});
});
Example: http://emberjs.jsbin.com/wipo/49/edit
Trying to understand better about ember's register and inject.
Basically my code looks like this:
//creating a service
Nerdeez.Wormhole = Ember.Object.extend({
...
})
//registering this service as a singleton
App.register('wormhole:current', Nerdeez.Wormhole, {singleton: true});
//wanting to inject this service to be available everywhere in my application
//especially in the adapter where i use it in the ajax hook
App.inject('App', 'wormhole', 'wormhole:current');
//when trying to access this service in the ajax hook in the adapter i get undefined WTF!
App.get('wormhole') === undefined //true
i just want this service available globally in the entire application as a singleton, what is the best way to achieve this?
it's important to say that i manage to inject my service to models, views, and controllers and the problem is injecting it to my adapter.
Thanks in advance
I couldn't figure out a way to inject the object into App either, but you can inject it into the adapter (or store) just like you can with for route & controller objects:
// register
App.register('wormhole:current', Nerdeez.Wormhole);
// inject into adapter
App.inject('adapter', 'wormhole', 'wormhole:current');
// inject into store
App.inject('store', 'wormhole', 'wormhole:current');
// inject into routes & controllers
App.inject('route', 'wormhole', 'wormhole:current');
App.inject('controller', 'wormhole', 'wormhole:current');
We are using version pre4 of ember.
We have a framework (SignalR) working parallel with ember that handles real-time notifications to our application. In the older versions of ember we were able to access the global reference of the router / controller. But with the new version of Ember this is no longer possible. (This is fine)
We have tried different approaches like setting up a global controller in the top route:
setupController: function(){
app.appController = this.controllerFor('app');
}
and sending an event to this controller, which bubbles up to the route like this:
notificator.update = function (context) {
app.appController.send('notificationOccured', context);
});
But this feels like working against the Ember team which just removed the global references.
So now to the big question: is there a better way to access the router or a controller from outside Ember? Preferably send an event to either with a context.
All help is appreciated!
So now to the big question: is there a better way to access the router or a controller from outside Ember? Preferably send an event to either with a context.
Yes. This sounds like a good fit for the ember instrumentation module. Have an appropriate controller subscribe to SignalR events, then trigger them whenever your app handles real-time notification.
First, add a method to ApplicationController for processing updates. If not defined here the event would bubble to the router.
App.ApplicationController = Ember.Controller.extend({
count: 0,
name: 'default',
signalrNotificationOccured: function(context) {
this.incrementProperty('count');
this.set('name', context.name);
}
});
Next, setup your ApplicationController by subscribing to the signalr.notificationOccured event. Use the before callback to log the event and send it's payload to the controller.
App.ApplicationRoute = Ember.Route.extend({
setupController: function (controller, model) {
Ember.Instrumentation.subscribe("signalr.notificationOccured", {
before: function(name, timestamp, payload) {
console.log('Recieved ', name, ' at ' + timestamp + ' with payload: ', payload);
controller.send('signalrNotificationOccured', payload);
},
after: function() {}
});
}
});
Then from your SignalR Application, use Ember.Instrumentation.instrument to send payload to your ApplicationController as follows:
notificator.update = function (context) {
Ember.Instrumentation.instrument("signalr.notificationOccured", context);
});
I posted a working copy with simulated SignalR notifications here: http://jsbin.com/iyexuf/1/edit
Docs on the instrumentation module can be found here, also check out the specs for more examples.
You probably shouldn't be doing this but here's a way to get access to the application's controllers, views, models and router instances. When your application is initialized, controllers, views, models and router are all registered in the application container __container__
APP.__container__.lookup('controller:foo').get('content');
APP.__container__.lookup('view:foo').get('templateName');
APP.__container__.lookup('router:main');
What i think you should do is encapsulate calls to the 3rd party library inside Ember and let Ember manage the whole application. See this attempt to make JQuery UI ember-aware
I'd like to unit test some controller actions and ultimately test that validation attributes and action response filters are functioning properly. To do this sort of thing in ASP .NET MVC was easy with mvccontrib; however, with Web API, mocking the HttpContext seems to be quite a bit different.
How do I go about mocking HttpContext for a Web API controller so that I can test model binding and the like?
You shouldn't need HttpContext in a Web API. Everything you need should be in the HttpRequestMessage and its Properties collection.
Do not use HttpContext.
Just Mock the service and the controller and go with somthing like this:
_serviceMock.Setup(s => s.YourFunction(params if needed)).Returns(return value).
var response = _controllerMock.YourFunction(parameter);
_serviceMock.VerifyAll();
var result = response.Result;
var value = result.Value;