How to setup e2e protractor backend request mocking/stubbing - angularjs

I try to setup my independent protractor project to mock some of my backend requests. Therefore, I included angular-mocks.js and attached another module within the onPrepare() function of my protractor.conf.js:
browser.addMockModule('httpBackend', function() {
angular.module('httpBackend', ['myApp', 'ngMockE2E']).run(function($httpBackend) {
$httpBackend.whenPOST(/^requests\/*/).respond(function(method, url, data) {
var obj = {"msg": "Response!"};
return [200, JSON.stringify(obj), {}];
});
})
})
This lets me intercept any request but I am not getting what I want to return in respond(). It seems I am just getting a 200 OK.
What am I doing wrong?

Just to let you know how I solved it:
The docs say the following:
The respond method takes a set of static data to be returned or a function that can return an array containing response status (number), response data (string), response headers (Object), and the text for the status (string).
In my case, the headers Object somehow does not seem to be optional and I ended with setting it on my own before returning the array:
browser.addMockModule('httpBackend', function() {
angular.module('httpBackend', ['myApp', 'ngMockE2E']).run(function($httpBackend) {
$httpBackend.whenPOST(/^requests\/*/).respond(function(method, url, data) {
var obj = {"msg": "Response!"},
resHeader = {
"Cache-Control": "no-cache, no-store, max-age=0",
"Date": "Tue, 24 Nov 2015 17:08:57 GMT",
"Pragma": "no-cache",
"Transfer-Encoding": "chunked",
"Content-Type": "application/json; charset=UTF-8",
"Expires": "Thu, 01 Jan 1970 00:00:00 GMT",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "origin,x-requested-with,access-control-request-headers,content-type,access-control-request-method,accept",
"Access-Control-Allow-Methods": "POST, GET, OPTIONS, DELETE",
"Access-Control-Credentials": "true",
"Content-Language": "de-DE",
"Access-Control-Max-Age": "3600"
};
return [200, JSON.stringify(obj), resHeader];
});
})
})
Anybody has a clue why this is necessary or which of its attributes is obsolete?

Related

Not able to mock GET request in cypress

x.spec.js
before(() => {
cy.restoreLocalStorage();
cy.server()
cy.route({
method: 'GET',
url: '/dashboard/v1/public/api/allMachineStatus',
headers: {
"access-control-allow-credentials": true,
"authorization": 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXiOjE1OTI0MDU5NjMsImV4cCI6MTU5NDk5Nzk2MywiaWQiOiIxMDAwIiwiaXNfYWRtaW4iOnRydWV9.JaIUHy85pIZ_rulJCZXutqZXeC_4_wlVFa4z3I-8kO0'
},
response: 'fixture:allMachinesStatus'
})
cy.visit('/')
cy.get('[data-testid="side-bar')
.contains('Live Status')
.click()
});
beforeEach(() => {
cy.wait(100)
})
context("it should check headings",()=>{
it("should check some heading",()=>{
cy.get('[data-testid="refill-status-heading-live-status"]')
})
})
Above is the test code and
{
"error": false,
"data": [
{
"machine_id": "...",
"total_units": 550,
"total_price": "50"
}
]
}
this is in allMachinesStatus.json
When i load page i make **GET** request but i can not see that request in cypress logs
So the code here x.spec.js is also not mocking it. I am able to mock POST request but this get request is on page load and i dont know why its failing.
I have post request (timings in response headers are)
**..getPaymentMethods** - date: Sat, 20 Jun 2020 16:04:14 GMT // post request
**...allMachineStatus** - date: Sat, 20 Jun 2020 16:04:13 GMT // get request that is not showing up on cy browser

Fetch Angular $http response header param

I am working on an Progressive Web app module with AngularJS.
I have made a network call with POST request using '$http', I am able to get a response of it but am not getting 'Response Header' params.
Here is my Response header:
Connection:keep-alive
Content-Type:application/json
Date:Fri, 19 May 2017 10:41:49 GMT
Server:JBoss-EAP/7
Session-ID:XXXXX-YYYY-ZZZ
Transfer-Encoding:chunked
X-Powered-By:Undertow/1
And below is a request and API call.
$scope.data = {userid: $scope.username,
os: 'android',
device_id: 'b0316b93ae786ec0',
source: 'iv2',
password: $scope.password,
build_version_code: '2.3',
version: '5.1.1'};
$http({
method : "POST",
url: 'https://domain.name/v1/users/login',
data : $scope.data,
headers: {
'content-type': "application/json",
'sessionID': ''
}
})
.then(function successcallback(response){
console.log("Session-ID" , response.headers());
console.log("response" , response);
}, function errorcallback(response){
console.log('error' , response);
});
I have tried below possible solution based on response callback method.
function successcallback(response){
response.header('Session-ID');
}
and
success(function(response , status , headers , config){
console.log("response" ," headers - " + headers('Session-ID'));
}
The both approaches returns a null value instead of expected value.
Please let me know if I am missing something. I am happy to get all possible help.

S3 putObject fails using aws-sdk

It's driving me crazy, any help would be much appreciated!
To set up my bucket in S3 I followed http://www.cheynewallace.com/uploading-to-s3-with-angularjs/
Regarding this post I made following "improvements" by extended the policy with a wildcard and giving more rights
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectTorrent",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTorrent",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": [
"arn:aws:s3:::photos-eu/*"
]
}
]
}
and added < ExposeHeader>ETag< /ExposeHeader > to the Cors settings of the bucket
Then my angular service using the aws-sdk look like
/// <reference path="../../../typings/tsd.d.ts" />
module Services {
export interface IS3UploadService {
upload(imgName:string, imgData:string):ng.IPromise<{}>;
}
export class S3UploadService implements IS3UploadService {
static $inject = ['$q'];
private bucket:AWS.S3;
constructor(private $q:ng.IQService) {
var credentials = new AWS.Credentials("myAccessKeyId", "mySecretAccessKey");
AWS.config.update(credentials);
AWS.config.region = "eu-west-1";
this.bucket = new AWS.S3({params: {Bucket: 'peterparker-photos-eu', maxRetries: 10, region: "eu-west-1"}});
}
upload(imgName:string, imgData:string):ng.IPromise<{}> {
var deferred = this.$q.defer();
var params:AWS.s3.PutObjectRequest = {
Bucket: "peterparker-photos-eu",
Key: imgName,
Body: imgData,
ContentType: "image/jpeg",
ContentEncoding: "Base64"
};
this.bucket.putObject(params, (err:any, data:any) => {
if (err) {
console.error("->" + JSON.stringify(err));
deferred.reject(err);
} else {
console.info(data);
deferred.resolve(data);
}
});
return deferred.promise;
}
}
}
angular.module('App')
.service('S3UploadService', Services.S3UploadService);
For my test purpose, I push in the imgData an img encoded as Base64, something like "/9j/4AAQSkZJRgABAgAAZABkA...." (of course a valid image converted with http://base64-image.de)
And as result, each time I try, I've got following error
{"line":25,"column":24996,"sourceURL":"http://localhost:8100/lib/aws-sdk/dist/aws-sdk.min.js","message":"The request signature we calculated does not match the signature you provided. Check your key and signing method.","code":"SignatureDoesNotMatch","region":null,"time":"2016-06-08T15:12:09.945Z","requestId":null,"statusCode":403,"retryable":false,"retryDelay":60.59883770067245}
So much fun...
Update headers:
General
Request URL:https://peterparker-photos-eu.s3-eu-west-1.amazonaws.com/1465408512724.jpg
Request Method:PUT
Status Code:403 Forbidden
Remote Address:54.231.131.16:443
Response headers
Access-Control-Allow-Methods:HEAD, GET, PUT, POST, DELETE
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:ETag, x-amz-meta-custom-header
Connection:close
Content-Type:application/xml
Date:Wed, 08 Jun 2016 17:55:20 GMT
Server:AmazonS3
Transfer-Encoding:chunked
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request- Method
x-amz-id-...
x-amz-request-id:...
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2
Authorization:AWS ...
Connection:keep-alive
Content-Encoding:Base64
Content-Length:38780
Content-MD5:...
Content-Type:image/jpeg; charset=UTF-8
Host:peterparker-photos-eu.s3-eu-west-1.amazonaws.com
Origin:http://localhost:8100
Referer:http://localhost:8100/?ionicplatform=ios
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36
X-Amz-Date:Wed, 08 Jun 2016 17:55:20 GMT
X-Amz-User-Agent:aws-sdk-js/2.3.18
Request payload
Img base64 code
Update
Even by trying to upload a non Base64 content it finish with the same error
var paramsHtml:AWS.s3.PutObjectRequest = {
Bucket: "peterparker-photos-eu",
Key: "HelloWorld.html",
Body: "The Body",
ContentType: "text/html"
};
Update #2
I moved to a solution with a signed URL generated by my node js server as described in following solution, still got the same error as result...but I least I try ;)
upload file from angularjs directly to amazon s3 using signed url
Freak I finally find the solution or at least a solution.
After migrating my client aws-sdk based solution to a solution where the server generate a signedUrl I was still facing the same error. Short story long, it fixed the problem by setting in both side the Content-type for the header.
My code if someone face the same problem one day:
Server Node.js
var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: "myKey", secretAccessKey: "mySecret"});
AWS.config.region = 'eu-west-1';
app.post('/api/images', securityPolicy.authorise, function (req, res) {
var s3 = new AWS.S3();
var imgName = req.body.imgName;
var contentType = req.body.contentType;
// Expires in seconds
var params = {Bucket: 'photos-eu', Key: imgName, Expires: 600, ContentType: contentType};
s3.getSignedUrl('putObject', params, function (err, url) {
if (err) {
res.status(500).json({
error: "Presigned S3 url for putObject can't be created. " + JSON.stringify(err)
});
} else {
res.json({url: url});
}
});
});
Client angular:
First or course there is the part to call the node server, obvious POST to my server
And then the second part processing the signedURL
private uploadToS3(preSignedUrl:string, imgData:string):ng.IPromise<{}> {
var deferred = this.$q.defer();
// Post image to S3
this.$http({
method: 'PUT',
url: preSignedUrl,
headers: {'Content-Type': 'image/jpeg'},
data: imgData
})
.then((response:any) => {
console.log("Image uploaded to S3" + JSON.stringify(response));
deferred.resolve();
}, (response:any) => {
console.log("Error Presigned URL" + JSON.stringify(response));
deferred.reject(response);
});
return deferred.promise;
}

AngularJS $http date header

I'm trying to retrieve the $http date header from an AngularJS $http.get request so I can get the server time.
app.controller('MainCtrl', function($http,$scope) {
$scope.name = 'World';
$http({method: 'GET', url: 'http://graph.facebook.com/facebook'}).then(function(response){
console.log(response);
})
});
I can't seem to retrieve the Date header although when I inspected on chrome tools the date header was there.
try this:
$http({method: 'GET', url: 'http://graph.facebook.com/facebook'}).then(function(response){
var data = response.data,
status = response.status,
headers = response.headers(),
config = response.config;
})
headers will contain:
headers: {
"date": "Mon, 02 Mar 2015 23:02:51 GMT",
"content-encoding": "gzip",
"server": "Apache",
"vary": "Accept-Encoding",
"content-type": "text/html",
"connection": "Keep-Alive",
"keep-alive": "timeout=10, max=500",
"content-length": "39"
}
to access date:
headers.date
Since it's a CORS request to facebook api: The response header will contain only
Content-Type
Last-modified
Content-Language
Cache-Control
Expires
Pragma
The issue is because of missing Access-Control-Allow-Headers from request Header. To fix this we need to add Access-Control-Allow-Headers: * to request header in your run method

How to read response headers with $resource?

I'm using $resource to get data from my RESTful service and I need to read response headers to get 'X-Page' and 'X-Total-Pages' value for pagination.
Example:
Access-Control-Max-Age:1728000
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:2637
Content-Type:application/json
Date:Thu, 10 Apr 2014 16:53:01 GMT
Server:WEBrick/1.3.1 (Ruby/2.1.1/2014-02-24)
Vary:Origin
X-Page:1
X-Per-Page:10
X-Total:17
X-Total-Pages:2
But I couldn't get full headers from server.
This is returned headers:
This is the headers from server:
This is my code:
.factory('TestAPI', ['$resource',
function ($resource) {
return $resource("http://ip.jsontest.com/?callback=showIP", {}, {
query: {
method: 'GET'
}
});
}])
TestAPI.query({}, function (value, responseHeaders) {
console.log(responseHeaders());
}, function (response) {
console.log(response);
});
In your response headers you have to add the following header:
Access-Control-Expose-Headers: X-Total-Pages, X-Page
With this, the browser is capable to expose your customs headers an read it angular.

Resources