Comments (20)
It'd help to get a better idea of what you're hoping to test. Protractor is intended for end to end tests, so the primary use case is when you have an actual backend hooked up. It sounds like you're looking to test just your UI via your static files, without any real $http requests hitting backends?
Protractor provides a way to override modules, so it would certainly be possible to have a helper file that would make setting up your $http mocks easier. You still need some way to serve your static files, though.
from protractor.
My exact case is that I have a rails app serving an API and the static files which make up my Angular app. I'd like to test the Angular app but stop at the AJAX requests and keep the rails app out of it.
I have a lightweight connect server which serves the Angular app for integration testing and currently it just returns canned responses to the AJAX API requests. I'd like to be able to make assertions against those requests and set them to return different responses in different tests.
I didn't realise that I could override modules from protractor - that sounds like exactly what I need! I take it I can just use the mock $httpBackend
like I do in Karma unit tests? Is there an example somewhere of how to go about this with Protractor?
from protractor.
Hey @mrappleton, we do something similar with a Rails app that acts as only API in dev and also serves static assets in production. We use Lineman to manage our static assets in dev mode and run a small apiProxy configuration that talks to the Rails API transparently. Lineman has a built in fake-server that sounds similar to what you are using connect for. Once we are ready to move to prod we execute lineman build
which bundles up all our static assets that we just dump into the Rails public directory.
If you need the flexibility of defining the API responses in each test you may want to check out a small gem that we made @testdouble called servme. It gives you a small DSL that allows you to stub responses for particular requests, here's an example:
before(:each) do
on({
:url => "/api/login",
:method => :post,
:params => {
:login => "todd",
:password => "scotch"
}
}).respond_with(:token => "1234567890")
end
In general I agree with @juliemr that Protractor is the ideal tool for writing tests that hit your actual backend or an actual fake backend as opposed to $httpBackend; I feel the latter is most appropriate for unit tests.
from protractor.
Hey @davemo serveme looks very cool, however what I'm really after though is to avoid Rails entirely with these tests and just isolate the Angular app as a system. I think having access to the mock $httpBackend would do the job for me, @juliemr do you have any pointers on getting this set up? Will I be able to access the mocked object from within my specs?
from protractor.
@mrappleton - unfortunately, the javascript running in your application is separated from the javascript running in your specs, so you won't be able to access the mocked object from your specs. The only way that code is sent to the browser under test is via webdriver.executeScript
, which can only return a primitive or an element. That means you won't be able to use the unit testing $httpBackend. Here's an example of a very simple way to override a module:
// This function will be executed in the context of the application under test, so it may not refer to any local variables.
var mockModuleA = function() {
var newModule = angular.module('moduleA', []);
newModule.factory('$http', function() {
mockHttp = function() { return 'foo!' };
return mockHttp;
});
};
it('should override services via mock modules', function() {
ptor.addMockModule('moduleA', mockModuleA);\
ptor.get('app/index.html');
// your test here
});
from protractor.
Thanks for the explanation @juliemr, makes perfect sense. What I've decided to do is change my API mocking to be a little smarter so it can more closely simulate POSTing and saving data - that way I can just do a POST then reload a page and assert that the data is shown.
from protractor.
i use ngMockE2E as mock, works perfect.
var mock_code = function () {
angular.module('httpBackendMock', ['ngMockE2E'])
.run(function ($httpBackend) {
$httpBackend.whenGET('/api/login').respond({status:'loggedin'});
$httpBackend.whenGET(/.*/).passThrough();
});
};
it('should override services via mock modules', function() {
ptor.addMockModule('httpBackendMock', mock_code);
ptor.get('app/index.html');
// your test here
});
from protractor.
@ozanturksever How are you getting the ngMockE2E module? Do you have it referenced in your test or on the browser already? The code that you have won't work unless the angular-mock.js file is referenced somewhere.
from protractor.
i have grunt tasks that generates reference for it, so for tests it is referenced after angular.js. I also made a little change in angular-mocks.js. It is not queuing responses anymore, responds immediately.
$ diff angular-mocks-protractor.js angular-mocks.js
911c911
< setTimeout(resp,0);
---
> responses.push(resp);
from protractor.
Very clever, @ozanturksever, thanks for the insight.
from protractor.
@juliemr: with reference to your suggested solution... thank you. My setup is slightly different, and I'm having trouble adapting your solution to my requirements.
The code for the service (ie, the service that I want to mock) looks something like this:
angular.module('XServiceModule', ['ngResource']).factory(
'XService',
function ($resource) {
return $resource(
'path/to/service'
);
}
);
That service is called as a POST from the controller like this:
XService.save(
{},
JSON.stringify(YModel),
function (value, getResponseHeaders) {
// everybody is happy; do something
},
function (httpResponse) {
// error handling here
}
);
From an e2e testing pov (I'm using Protractor), what I want to do is to specify exactly the JSON object that is returned when that service is called – but I'm stuck!
Can you help out? Am sure I am close... :-)
many thanks
Matt
from protractor.
I think I might have found a solution:
// this mock service will return success
var mockXServiceModuleSuccess = function () {
angular.module('XServiceModule', []).factory(
'XService',
function () {
return {
save: function (params, postData, onSuccess, onError) {
var value = {}, // set as necessary
getResponseHeaders = function () {
return {}; // set as necessary
};
onSuccess(value, getResponseHeaders);
}
};
}
);
};
// and this one will fail
var mockXServiceModuleError = function () {
angular.module('XServiceModule', []).factory(
'XService',
function () {
return {
save: function (params, postData, onSuccess, onError) {
var httpResponse = {}; // set as necessary
onError(httpResponse);
}
};
}
);
};
And then, at the relevant parts in the testing code, add the mocked module:
browser.addMockModule('XServiceModule', mockXServiceModuleSuccess);
or:
browser.addMockModule('XServiceModule', mockXServiceModuleError);
I have given that a go, and it seems to be working.
Does it look right to you? Is there something I have missed?
cheers
Matt
from protractor.
The only thing I think I might have missed is to return a promise
from the mocked save()
method, which I guess would look like this:
return $q.defer().deferred.promise;
Does that look right?
And how would I inject $q
?
from protractor.
Bump.
I have found that using mockXServiceModuleSuccess()
(in my sample code, above) works, but using mockXServiceModuleError()
does not work: the onError()
parameter is never called.
So I'm guessing that I am not correctly mocking the behaviour of the Promise that would normally be returned by $http
.
Could someone point me in the right direction?
Spent quite a bit of time on this already.
cheers
Matt
from protractor.
ngMockE2E
does the job for simple specs but what about with complex multi-stage scenarios?
For example:
- go to the list of products (mock
GET /api/products.json
), assets that we have 3 rows - click delete product (mock 'DELETE /api/products/1.json)
- products list will be reloaded (mock
GET /api/products.json
again, this time return a list with 2 rows) - assert that the list contains 2 rows
Can we somehow redefine $httpBackend
stubs several times in the flow (for examples for GET /api/products.json
request)?
from protractor.
@lucassus i've been dealing with a complicated mock situation for the last week or so - have just made a breakthrough - you can use clearMockModules() in tandem with addMockModule to hand in a different set of mocks for any test.
For now, i've added a before and after to all my tests
beforeEach ->
ptor.addMockModule 'MockedBackend', MockedBackend
afterEach ->
ptor.clearMockModules()
it 'should blah blah blah', -> etc
You should be able to remove that beforeEach and add a custom mockedBackend per describe
or per test.
from protractor.
@ozanturksever .Yes I followed similar to your thinking and I am new to protractor. can you please instruct for the correct solution. I have created mock module thats replace the main module during bootstrap process, and the httpBacked intercepts the desired calls and returns the dummy data. Since my app not interact with real backend.
But In my case I want to test the case with server exception, The same url we need to test for both positive case and negative case.
from protractor.
Hey guys,
I created a little mock module to help me handle success and error scenarios, maybe it will help you better organize mocking.
https://github.com/unDemian/protractor-mock
from protractor.
i was following exact same example with addMockmodule for ssome reason it was not mocking my backend resource calls
var mock_code = function () {
angular.module('httpBackendMock', ['ngMockE2E'])
.run(function ($httpBackend) {
console.log($httpBackend);
$httpBackend.whenGET('someurl').respond('json');
$httpBackend.whenGET('someurl').respond('json1');
$httpBackend.whenGET(/.*/).passThrough();
});
};
console.log(mock_code);
ptor.addMockModule('myapp', mock_code);
ptor.addMockModule('myapp', mock_code);
ptor.addMockModule('httpBackendMock', mock_code);
browser.addMockModule('myapp', mock_code);
browser.addMockModule('myapp', mock_code);
browser.addMockModule('httpBackendMock', mock_code);
ptor.driver.get('appurl');
and this is inside my protractor specs and it just not complaining any issue and not mocking my resource calls
from protractor.
This is be the good solution. Which i am using right now.
http://stackoverflow.com/a/34610987/3840665
from protractor.
Related Issues (20)
- Support on Protractor after 2022 and any plans for licensed version HOT 7
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. HOT 4
- Callback function is taking long after completing the run in the protractor testcase
- [BUG] Upgrade transitive dependency "[email protected]" to fix CVE-2021-3918 HOT 1
- [BUG] input with dropdown use clear the selected tag won't remove, and click will click on the text not the element.
- Is protractor no longer working when using Angular 13? HOT 8
- protractor.Key.chord() broken in the latest chromedriver HOT 3
- Prototype Pollution in minimist
- qs version CVE-2021-44907 (High) detected in my repo dependencies
- need support for finding element under shadow root HOT 3
- Feature request - html to pdf
- Git.io deprecation notice
- Getting the ERROR "This driver instance does not have a valid session ID (did you call WebDriver.quit()?) and may no longer be used." When I try to use restart() or close() method HOT 2
- Deprecated warning with Protractor HOT 2
- Interview partners for research about communication in GitHub projects wanted
- Can existing Protractor automation scripts developed in year 2020 supported on windows 2019 OS server
- webdriver Manager , chrome version higher then 114 HOT 3
- Migrate Protractor to Playwright
- Meera HOT 1
- Performance Dashboard
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from protractor.