How to a pass a complex object as a mock data service stub - testing

I'm working on a test for a module, which works except for the fact that I can not access, the inner object attributes properties.
tokenStorageServiceStub = { // Mock service data
getUser: () => of({
username: 'organization-a-a-normal',
roles: ['PROCESSOR'],
attributes: {
organizationId: 111,
organizationName: 'Org.name Aa',
userFullName: 'User for organization A-A',
userId: 22,
},
access_token: 'AT01',
refresh_token: 'RT01',
token_type: 'Bearer',
expires_in: 3600,
}),
};
The component code complains about the last statement:
this.activeTokens = this.token.getUser(); // OK
this.username = this.activeTokens.username; // OK
this.organization.id = this.activeTokens.attributes.organizationId; // `attributes` is undefined?
Chrome Headless 88.0.4298.0 (Linux x86_64) SettingsComponent should create FAILED
TypeError: Cannot read property 'organizationId' of undefined
at SettingsComponent.call [as ngOnInit] (src/app/organization/settings/settings.component.ts:22:61)
I think it's because of the innerworking of the RxJs.of() function. In the manual, I see things like ObservableInput. But there is no mention of Objects as such.
I also read about of() getting deprecated? What will be a good approach to pass my object data in a test service stub?

Related

Callback response in Jest is different than normal response

I have a method that calls an endpoint in React Native and I want to test it with jest. Everything is asynchronous and it works but the callback response when the function is called in testing side is totally different than the response when the function is called normally in application.
Normally, my response will be a JSON like this:
"_bodyBlob":{
"_data":{
"__collector":[
"Object"
],
"blobId":"43564E12-D797-4971-80C7-A6E06D690F8A",
"name":"login",
"offset":0,
"size":784,
"type":"application/json"
}
},
"_bodyInit":{
"_data":{
"__collector":[
"Object"
],
"blobId":"43564E12-D797-4971-80C7-A6E06D690F8A",
"name":"login",
"offset":0,
"size":784,
"type":"application/json"
}
},
"bodyUsed":false,
"headers":{
"map":{
//a lot of private data here and others
}
},
"ok":true,
"status":200,
"statusText":"",
"type":"default",
"url":"private url"
}
But the response that is returned when called the method by Jest is like this:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: { body: <Buffer >, disturbed: false, error: null },
[Symbol(Response internals)]: {
url: undefined,
status: 200,
statusText: 'OK',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: undefined
}
}
Which is not even a JSON.
Is this a normal response for a callback when the method is called by Jest or could be something wrong while I call the function because it's all asynchronous?
Thank you for your time.
It seems in your Jest test the response is the javascript Response object: https://developer.mozilla.org/en-US/docs/Web/API/Response
In order to get the JSON out of it, you need to apply its json() method like in this example: https://developer.mozilla.org/en-US/docs/Web/API/Response#an_ajax_call
So once you get the response object, do this:
const jsonValue = await response.json();
The reason why the value is different in jest and in your actual application could be that in your actual application, the library handling the response probably calls the json object before passing you the response.

My firebase user object doesn't seem to be right

I'm newbie to firebase.
I'm trying to make a signup component using firebase authentication, but the user object I've got returned from firebase.auth().createUserWithEmailAndPassword doesn't seem to be right.
The official document says that I can get the uid by calling user.uid, but in my case it returns null. Instead, I can get uid by calling user.user.uid.
I'm so confused.
Is the document I'v seen was outdated? or have I done something wrong?
Detailed codes are below. Please take a look and give me a piece of advice.
const promise=firebase.auth.createUserWithEmailAndPassword(email, password);
promise
.then((user) => {
console.log(user);
console.log(user.id); //returns null
console.log(user.user.uid); //returns O6hLcfJL5NT4fV2S7JprQ3MhjCK2, which I assumes to be uid.
})
.catch((e) => {
console.log(e.message);
})
Following are the result of console.log(user).
{user: P, credential: null, additionalUserInfo: Wf, operationType: "signIn"}
additionalUserInfo: Wf {providerId: "password", isNewUser: true}
credential: null
operationType: "signIn"
user: P {G: Array(0), l: "AIzaSyDIj8N9kONUkpOdMGuApNcKkaeFYYEzfyk", o: "[DEFAULT]", u: "bluegenie-2ba45.firebaseapp.com", c: bi, …}
__proto__: Object
As you can see, there is another user object inside the user object which I've got returned from createUserWithEmailAndPassword() method.
Thanks in advance.
createUserWithEmailAndPassword returns a promise that resolves with a UserCredential instead of a User.
This change was made in v5.0.0

Files larger than ~7mb throws "Response not received." on IBM Watson Speech-To-Text async createJob call

I'm working on server-side speech to text transcription, and I was able to get a post endpoint working for smaller files, but anything larger than ~7Mb throws an error that doesn't make much sense to me.
I know this code works for small files, and that the callback URL is registered correctly. I've tried throwing the "readableTranscriptStream" creation in a setTimeout() function, just to make sure it wasn't an issue of the full file not being passed to the createJob call. I've also tried just passing req.file.buffer as an argument for the audio param. I also know it isn't an issue of the encoding of the files being incorrect, as I've used the same audio file, slowly increasing the length and size of the file until it threw this error, and it worked until I hit about 7.2Mb, or ~3 min of audio in a .wav 16-bit encoded file.
I've also tried this with the fs.createFileStream('./local_test.wav') as an argument and gotten the same error back, though when I tried that, the _requestBodyLength field in the error was 10485760, and the _requestBodyBuffers was an array of objects. I realize this 10485760 is the same as the maxBodyLength, but the docs for the API say that "You can pass a maximum of 1 GB and a minimum of 100 bytes of audio with a request", and the test audio was, again ~7.2 Mb.
username: process.env.wastonUsername,
password: process.env.watsonPassword,
url: 'https://stream.watsonplatform.net/speech-to-text/api/'
});
const storage = multer.memoryStorage();
const upload = multer({ storage: storage , limit: {fields: 1, fileSize: 209715200, files:1, parts:2}});
upload.single('track')(req,res, (err) => {
req.setTimeout(0);
if (err) {
console.log(err);
return res.status(400).json({ message: err })
}
const registerCallbackParams = {
callback_url: <my_callback_url>,
user_secret: "Test"
};
const readableTranscriptStream = new Readable();
readableTranscriptStream.push(req.file.buffer);
readableTranscriptStream.push(null);
const createJobParams = {
audio: readableTranscriptStream,
callback_url: <my_callback_url>,
content_type: req.file.mimetype,
events:"recognitions.completed_with_results",
inactivity_timeout: -1
};
speechToText.createJob(createJobParams)
.then(recognitionJob => {
console.log(recognitionJob);
})
.catch(err => {
console.log('error:', err);
});
})
The error I'm getting back is :
error:{
Error: Response not received. Body of error is HTTP ClientRequest object
at formatError (/app/node_modules/ibm-cloud-sdk-core/lib/requestwrapper.js:111:17 )
at /app/node_modules/ibm-cloud-sdk-core/lib/requestwrapper.js:259:19 at process._tickCallback (internal/process/next_tick.js:68:7 )
message:'Response not received. Body of error is HTTP ClientRequest object',
body:Writable {
_writableState:WritableState {
objectMode:false,
highWaterMark:16384,
finalCalled:false,
needDrain:false,
ending:false,
ended:false,
finished:false,
destroyed:false,
decodeStrings:true,
defaultEncoding:'utf8',
length:0,
writing:false,
corked:0,
sync:true,
bufferProcessing:false,
onwrite:[
Function:bound onwrite
],
writecb:null,
writelen:0,
bufferedRequest:null,
lastBufferedRequest:null,
pendingcb:0,
prefinished:false,
errorEmitted:false,
emitClose:true,
bufferedRequestCount:0,
corkedRequestsFree:[
Object
]
},
writable:true,
_events:[
Object:null prototype
] {
response:[
Function:handleResponse
],
error:[
Function:handleRequestError
]
},
_eventsCount:2,
_maxListeners:undefined,
_options:{
maxRedirects:21,
maxBodyLength:10485760,
protocol:'https:',
path:'/speech-to-text/api/v1/recognitions?callback_url=<my_callback_url>&events=recognitions.completed_with_results&inactivity_timeout=-1',
method:'post',
headers:[
Object
],
agent:[
Agent
],
auth:undefined,
hostname:'stream.watsonplatform.net',
port:null,
nativeProtocols:[
Object
],
pathname:'/speech-to-text/api/v1/recognitions',
search:'?callback_url=<my_callback_url>&events=recognitions.completed_with_results&inactivity_timeout=-1'
},
_ended:false,
_ending:true,
_redirectCount:0,
_redirects:[
],
_requestBodyLength:0,
_requestBodyBuffers:[
],
_onNativeResponse:[
Function
],
_currentRequest:ClientRequest {
_events:[
Object
],
_eventsCount:6,
_maxListeners:undefined,
output:[
],
outputEncodings:[
],
outputCallbacks:[
],
outputSize:0,
writable:true,
_last:true,
chunkedEncoding:false,
shouldKeepAlive:false,
useChunkedEncodingByDefault:true,
sendDate:false,
_removedConnection:false,
_removedContLen:false,
_removedTE:false,
_contentLength:null,
_hasBody:true,
_trailer:'',
finished:false,
_headerSent:false,
socket:null,
connection:null,
_header:null,
_onPendingData:[
Function:noopPendingOutput
],
agent:[
Agent
],
socketPath:undefined,
timeout:undefined,
method:'POST',
path:'/speech-to-text/api/v1/recognitions?callback_url=<my_callback_url>&events=recognitions.completed_with_results&inactivity_timeout=-1',
_ended:false,
res:null,
aborted:1558070725953,
timeoutCb:null,
upgradeOrConnect:false,
parser:null,
maxHeadersCount:null,
_redirectable:[
Circular
],
[
Symbol(isCorked)
]:false,
[
Symbol(outHeadersKey)
]:[
Object
]
},
_currentUrl:'https://stream.watsonplatform.net/speech-to-text/api/v1/recognitions?callback_url=<my_callback_url>&events=recognitions.completed_with_results&inactivity_timeout=-1'
}
}
Try adding maxContentLength: Infinity as an option when instantiating SpeechToText
const speechToText = new SpeechToTextV1({
username: 'user',
password: 'pass',
version: '2019-01-01',
maxContentLength: Infinity,
});
the limit is 1GB, please make sure you are using Chunked transfer encoding in the submission, that a typical cause of errors when feeding large files. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding

How to store the data in local device using JSONStore in worklight?

I'm doing Login Page in worklight using JavaScript and jquery, the username and password should validate the data getting from JSONstore?
How to store the data locally using JSONStore in worklight and how does i get the data from JSONStore while validating the username and password?
In below code where my data will store and get, if the username and password has typed where it validate:
var collections = {
people : {
searchFields : {name: 'string'}
},
orders : {
searchFields: {name: 'string'}
}
};
WL.JSONStore.init(collections)
.then(function () {
return WL.JSONStore.init(collections);
})
.then(function () {
return WL.JSONStore.init(collections);
})
.then(function () {
alert('Multiple inits worked');
})
.fail(function (err) {
lert('Multiple inits failed' + err.toString());
});
How to solve the issue?
You really should never ever store username and password locally in the device. That does not sound very secure...
Additionally, where is the username and password coming from? How should the logic be able to validate the credentials? It needs to compare whatever is inputted with something, to know that it is correct. An implementation cannot be done without otherwise, so you need to provide the answer to this...
In the meanwhile, you can take a look at the following tutorial: Offline Authentication.
The included sample application assumes you have first authenticated with a backend system, and later allows for authenticating locally, "offline", in case an Internet connection is not available. For this it uses JSONStore to securely authenticate.
The tutorial include a thorough implementation example, be sure to follow it, and to provide the missing information in your question.
This tutorial explains how to use the JSONStore API, including the Add method: https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-1/foundation/data/jsonstore/jsonstore-javascript-api/
var collectionName = 'people';
var options = {};
var data = {name: 'yoel', age: 23};
WL.JSONStore.get(collectionName).add(data, options).then(function () {
// handle success
}).fail(function (error) {
// handle failure
});

Sencha touch 2 - show response (JSON string) on proxy loading

Is there a way to output the json-string read by my store in sencha touch 2?
My store is not reading the records so I'm trying to see where went wrong.
My store is defined as follows:
Ext.define("NotesApp.store.Online", {
extend: "Ext.data.Store",
config: {
model: 'NotesApp.model.Note',
storeId: 'Online',
proxy: {
type: 'jsonp',
url: 'http://xxxxxx.com/qa.php',
reader: {
type: 'json',
rootProperty: 'results'
}
},
autoLoad: false,
listeners: {
load: function() {
console.log("updating");
// Clear proxy from offline store
Ext.getStore('Notes').getProxy().clear();
console.log("updating1");
// Loop through records and fill the offline store
this.each(function(record) {
console.log("updating2");
Ext.getStore('Notes').add(record.data);
});
// Sync the offline store
Ext.getStore('Notes').sync();
console.log("updating3");
// Remove data from online store
this.removeAll();
console.log("updated");
}
},
fields: [
{
name: 'id'
},
{
name: 'dateCreated'
},
{
name: 'question'
},
{
name: 'answer'
},
{
name: 'type'
},
{
name: 'author'
}
]
}
});
you may get all the data returned by the server through the proxy, like this:
store.getProxy().getReader().rawData
You can get all the data (javascript objects) returned by the server through the proxy as lasaro suggests:
store.getProxy().getReader().rawData
To get the JSON string of the raw data (the reader should be a JSON reader) you can do:
Ext.encode(store.getProxy().getReader().rawData)
//or if you don't like 'shorthands':
Ext.JSON.encode(store.getProxy().getReader().rawData)
You can also get it by handling the store load event:
// add this in the store config
listeners: {
load: function(store, records, successful, operation, eOpts) {
operation.getResponse().responseText
}
}
As far as I know, there's no way to explicitly observe your response results if you are using a configured proxy (It's obviously easy if you manually send a Ext.Ajax.request or Ext.JsonP.request).
However, you can still watch your results from your browser's developer tools.
For Google Chrome:
When you start your application and assume that your request is completed. Switch to Network tab. The hightlighted link on the left-side panel is the API url from which I fetched data. And on the right panel, choose Response. The response result will appear there. If you have nothing, it's likely that you've triggered a bad request.
Hope this helps.
Your response json should be in following format in Ajax request
{results:[{"id":"1", "name":"note 1"},{"id":"2", "name":"note 2"},{"id":"3", "name":"note 3"}]}
id and name are properties of your model NOte.
For jsonp,
in your server side, get value from 'callback'. that value contains a name of callback method. Then concat that method name to your result string and write the response.
Then the json string should be in following format
callbackmethod({results:[{"id":"1", "name":"note 1"},{"id":"2", "name":"note 2"},{"id":"3", "name":"note 3"}]});