angular2 testing: add latency to mock http backend - unit-testing

I have a service that gets data from two different backends (database over http request and live data over socket.io) and then publishes this data as a single stream. When testing this service, I would like to be able to control the delay of the mock http service, so that I can play through different kinds of racing conditions. Currently I'm doing this:
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
DataService,
{
provide: IoService,
useClass: MockIoService
},
{
provide: Http,
useFactory: (mockBackend, options) => {
return new Http(mockBackend, options);
},
deps: [MockBackend, BaseRequestOptions]
},
MockBackend,
BaseRequestOptions
]
});
});
it('should get data from http backend', async(inject([DataService, MockBackend, IoService], (service: DataService, mockBackend, ioService) => {
const mockResponse = {
data: [
{ id: 0, text: 'httpData', start: 0, stop: 1 }
]
};
mockBackend.connections.subscribe((connection) => {
connection.mockRespond(new Response(new ResponseOptions({
body: JSON.stringify(mockResponse)
})));
});
service.subscribe('test').subscribe((data) => {
expect(data.text).toBe('httpData');
});
})));
This works but again, I would like to be able to define a delay for the MockBackend so that the response comes after a fixed number of seconds. Is that possible and if yes, how?

Related

Auth.federatedSignIn({provider: "Facebook"}) in react native returns [ERROR] OAuth - Error handling auth response. [Error: invalid_client]

I am trying to configure a Social Sign In for Facebook in my react native mobile app using Cognito's hosted UI. My intention is to have any user that signs in with Facebook to have an enabled user in my Cognito User Pool.
However, when I click my "Login with Facebook" button and redirected to Cognito/Facebook's auth flow, it closes the embedded browser immediately and shows the following error in the logs:
[ERROR] 19:02.561 OAuth - Error handling auth response. [Error: invalid_client]
I have a manually configured aws backend with the following configuration:
export default awsConfig = {
Auth: {
"aws_project_region": "us-west-2",
identityPoolId: 'us-east-1:xxxxxx',
region: 'us-east-1',
userPoolId: 'us-east-xxxxx',
userPoolWebClientId: 'xxxxxx',
mandatorySignIn: false,
oauth: {
domain: "myapp.auth.us-east-1.amazoncognito.com",
scope: [
"email",
"openid",
],
redirectSignIn: "myapp://",
redirectSignOut: "myapp://",
responseType: "code",
urlOpener
},
federationTarget: "COGNITO_USER_POOLS"
}
}
This is my Facebook Login configuration:
And here is my react native code:
import React, { Component } from 'react';
import Amplify, { Auth, Hub } from 'aws-amplify';
import awsConfig from './aws-custom-exports';
const configObj = Amplify.configure(awsConfig);
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
Button
} from 'react-native';
class App extends Component {
state = {
user: null,
customState: null
};
componentDidMount() {
Hub.listen("auth", ({ payload: { event, data } }) => {
switch (event) {
case "signIn":
this.setState({ user: data });
console.log("Sign in event recorded.")
break;
case "signOut":
this.setState({ user: null });
break;
case "customOAuthState":
this.setState({ customState: data });
console.log("Custom OAuth event recorded.")
default:
console.log("Other auth event: ", data)
}
})
Auth.currentAuthenticatedUser()
.then(user => this.setState({ user }))
.catch(() => console.log("Not signed in"));
}
render() {
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View style={styles.body}>
<Button onPress={() => {
Auth.federatedSignIn({provider: "Facebook"})
.then(data => {
console.log(data)
})
.catch(err => {
console.error(err)
})
}} title="Login with Facebook" />
</View>
</ScrollView>
</SafeAreaView>
</>
);
}
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
body: {
backgroundColor: Colors.white,
}
});
export default App;
My Info.plist file has the CFBundleURLSchemes set to myapp and have added the RTCLinking code snippets to my AppDelegate.m

Mocking imported modules for a service

Suppose i want to write a unit test for a service which depends on services of another module.
Now here is my question. Is there any way to write my test so that i mock the module that MyService depends on such that i can use it in my unit test like this:
const moduleRef = await Test.createTestingModule({
imports: [
MockedModule,
],
providers: [
MyService,
],
});
Or i have to write a mock for each dependency service and use them like this:
const moduleRef = await Test.createTestingModule({
providers: [
MyService,
{
provider: DependencyService,
useClass: DependencyServiceMock,
}
],
});
I suppose it would be possible to use a MockModule that provides and exports the same dependencies that the service would normally depend on. I haven't heard of someone trying that yet, but I don't see why it wouldn't work. So if you have
#Injectable()
export class MyService {
constructor(private readonly depService: DependencyService) {}
...
}
Then in your mock module you would need
#Module({
providers: [{
provide: DependencyService,
useClas: DependencyServiceMock,
}],
exports: [DependencyService],
})
export class MockedModule {}
And in your test you would need to do
beforeEach(async () => {
const app = await Test.createTestModule({
imports: [MockedModule],
providers: [MySerivce],
}).compile();
});
...

AWS Lambda NodeJS launch EMR Spark Problem

I am trying to launch an EMR cluster with the following script in Lambda (NodeJS-12).
var AWS = require('aws-sdk');
var emr = new AWS.EMR({apiVersion: '2009-03-31', region: 'ap-northeast-1'});
exports.handler = (event, context, callback) => {
var params = {
"Name": "LaunchEMR",
"Instances": {
"KeepJobFlowAliveWhenNoSteps": true,
"TerminationProtected": false,
"Ec2SubnetId": "subnet-XXXXXXXX",
"EmrManagedMasterSecurityGroup": "ElasticMapReduce-master",
"EmrManagedSlaveSecurityGroup": "ElasticMapReduce-slave",
"HadoopVersion": "2.8.5",
"InstanceGroups": [{
"Name": "Master",
"InstanceRole": "MASTER",
"InstanceCount": 1,
"InstanceType": "m3.xlarge",
"Market": "ON_DEMAND"
}, {
"Name": "Core",
"InstanceRole": "CORE",
"InstanceCount": 1,
"InstanceType": "m3.xlarge",
"Market": "ON_DEMAND"
}]
},
"Applications": [{
"Name": "Hadoop"
}, {
"Name": "Spark"
}],
"ServiceRole": "EMR_DefaultRole",
"JobFlowRole": "EMR_EC2_DefaultRole",
"ReleaseLabel": "emr-5.28.0"
};
emr.runJobFlow(params)
.on('success', function(response){ console.log("success => " + response); console.log(response); })
.on('error', function(response){ console.log("error => " + response); console.log(response); })
.on('complete', function(response){ console.log("complete => " + response); console.log(response); })
.send( function(err, data){
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
callback(null, {
statusCode: 200,
body: JSON.stringify(err),
});
});
};
I had tuned the IAM policies can I seem to be able to submit the request successfully to EMR, as there is no error in the Lambda cloud-watch log, and we can see the request in EMR events.
However, we will get a cluster termination event right after the request event.
Error Log
Amazon EMR Cluster j-31OE0F3OXGO4K (LaunchEMR) has terminated with errors at 2019-12-02 06:32 UTC with a reason of VALIDATION_ERROR.
The SubnetID and Security-Group are the same as my manually started clusters.
I added the "iam:PassRole" in "EMR_DefaultRole".
I also tried some other instance types.
Is there anything that I am missing?
I am able to successfully run it by taking these 3 lines off.
"Ec2SubnetId": "subnet-XXXXXXXX",
"EmrManagedMasterSecurityGroup": "ElasticMapReduce-master",
"EmrManagedSlaveSecurityGroup": "ElasticMapReduce-slave",
But I still have no idea why it works. (and why it doesn't)

How to set the MockBackend status code?

For an HTTP test I've got these providers ..
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (pBackend: MockBackend, pOptions: BaseRequestOptions) => {
return new Http(pBackend, pOptions);
},
deps: [MockBackend, BaseRequestOptions]
}
]
I can mock a success response ..
let backend = injector.get(MockBackend);
backend.connections.subscribe(
(connection: MockConnection) => {
connection.mockRespond(new Response(
new ResponseOptions({
body: {mydata:'somedata'}
}
)));
});
and an error response ..
let backend = injector.get(MockBackend);
backend.connections.subscribe(
(connection: MockConnection) => {
connection.mockError(new Error('error'));
});
but please, how do i mock a non 200 response. E.G. how do I respond with HTTP status code 418 for example?
Thanks
Just add a status property to the ResponseOptions
new ResponseOptions({
body: {mydata:'somedata'},
status: 418
})
See the docs for other properties

Torii Not injecting 'session' EmberJS 2.0

I keep receiving the error that the session var is not defined. I've looked at other answers on here about restarting ember serve to remove any caching issues but I've tried that multiple times and I've followed the emberfire guide to the letter. Does anyone have any idea what could be going wrong? The authentication succeeds but the session doesn't get bound to. Here are my files:
/app/routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.query('post', {
orderBy: 'timestamp',
limitToLast: 3
});
},
actions: {
authenticate: function(username, pass) {
this.get('session').open('firebase', {
provider: "password",
email: username,
password: pass
}).then(function (data) {
console.log(data.currentUser);
console.log(session);
});
}
}
});
/app/torii-adapters
import Ember from 'ember';
import ToriiFirebaseAdapter from 'emberfire/torii-adapters/firebase';
export default ToriiFirebaseAdapter.extend({
firebase: Ember.inject.service()
});
/config/environment.js
var ENV = {
modulePrefix: 'website',
environment: environment,
contentSecurityPolicy: { 'connect-src': "'self' https://auth.firebase.com wss://*.firebaseio.com" },
firebase: 'https://REMOVED.firebaseio.com/',
torii: {
sessionServiceName: 'session'
},
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
I was having the same issue following the tutorial for emberfire. I solved the issue by explicitly install torii via npm:
npm install torii
Restarted the server and all is well.