duplex stream getting changed in callback:node js - node.js

I have a code where I am getting a duplex stream and in that function I call a callback which return me the values from redis.
function (index, arr, null, callback) {
const streamObject = stream;
const Id = arr[index].split(':')[0];
const Version = arr[index].split(':')[1];
console.log("STREAM RECEIVED IN SECOND 1");
console.log(streamObject);//printing for the first time
var response = this.ts.service(Id, Version, streamObject, (fn, type) => {
console.log("STREAM RECEIVED IN SECOND 2");
console.log(streamObject);
}
here when I print the stream object for the first time I get the stream object as follows
STREAM RECEIVED IN SECOND 1
Stream {
domain:
Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
_events:
{ end: [Function],
data: [Function],
drain: [Function: ondrain],
error: [Function: onerror],
close: [Function: cleanup] },
_eventsCount: 5,
_maxListeners: undefined,
writable: true,
readable: true,
paused: false,
autoDestroy: true,
write: [Function],
push: [Function],
queue: [Function],
end: [Function],
destroy: [Function],
pause: [Function],
resume: [Function] }
and in the second time I get
STREAM RECEIVED IN SECOND 2
Stream {
domain:
Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
_events: { end: [Function], data: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
writable: false,
readable: false,
paused: false,
autoDestroy: true,
write: [Function],
push: [Function],
queue: [Function],
end: [Function],
destroy: [Function],
pause: [Function],
resume: [Function],
root: null }
so stream is getting modified I am not sure why is it happening, I am not doing anything with the stream in the function called.
this is how my service method look which I am calling
service(id, vn, requestObject, callback) {
log.info("entering transformer service");
var transformerCombinedKey = id + vn;
if (!_.isString(transformerId)) {
throw new TypeError("Expected a string for transformerId");
}
if (!(transformerCombinedKey in this.functionRepositoryStore)) {
//FIXME: after using cache as a implementation should ret
var persistenceClientPromise = this.persistenceClient.getTransformerByIdAndVersion(transformerId, versionNumber)
persistenceClientPromise.then(
(aJSONStringifiedTransformer) => {
if (!aJSONStringifiedTransformer) {
callback(new Error("The given transformerId, " + transformerId + ", was not found."));
return;
}
this.functionRepositoryStore[transformerCombinedKey] = JSON.parse(aJSONStringifiedTransformer).transformerFunction;
this.transformerTypeRepository[transformerCombinedKey] = JSON.parse(aJSONStringifiedTransformer).transformerType;
const code = "var _ = require('lodash'); console.log('runnig VM1'); module.exports = " + this.functionRepositoryStore[transformerCombinedKey] + ';';
var transformerFunction = vm.runInNewContext(code, sandbox);
console.log("Calling callback inside the transformer service===1 ");
console.log(JSON.stringify(transformerFunction));
callback(transformerFunction, this.transformerTypeRepository[transformerCombinedKey]);
return
},
(error) => {
log.error("Error while getting transformer for Id " + transformerId + " and versionNumber " + versionNumber);
callback(error, null);
});
} else {
const code = "var _ = require('lodash'); console.log('runnig VM2'); module.exports = " + this.functionRepositoryStore[transformerCombinedKey] + '; ';
var transformerFunction = vm.runInNewContext(code, sandbox);
console.log("Calling callback inside the transformer service=== ");
console.log(JSON.stringify(transformerFunction));
callback(transformerFunction, this.transformerTypeRepository[transformerCombinedKey]);
}
}
}
this issue I see when I hit my app for the first time, when I hit it again without restarting the app, It works fine stream remain duplex also.
and also if I remove my call to redis this method , then stream doesn't change it works fine.
I am using waterfall and this is the second function of my waterfall model like
async.waterfall([func1,func2], function (err, result) {
if (err) {
console.log(err);
reject(err);
} else {
fulfill(result);
}
});
this first function also do the same thing but it works fine, the output of first is passed to the second.
this is how I create my stream
let streamParser = JSONStream.parse('*');
streamParser.on('data', fn);
let toPassStreamObject = streamObject.pipe(JSONStream.stringify())
.pipe(streamParser)
streamObject is the stream which I get from my DB.
fn (data) {
data['Date'] = data["month"];
delete data['month'];
}
I stuck on this for some time.how to prevent stream from changing.
this is reference to my previous post

Related

Firebase image upload, resize via cloud functions (https), and save to firestore

I am trying to achieve the following, however as a bit of a newbie, I can't see what I'm doing wrong:
File upload triggers a cloud function (https.onRequest())
Resize the image 3 times (100x100 thumb, 500x500 thumb, resize original to limit it's size)
Save all 3 images to the firebase storage bucket (Google Storage)
Get the respective signed URLs of the 3 images
Save signed URLs to Firestore
The following code works, but not consistently:
In my index.js file I create the HTTP trigger by:
export const image = functions.https.onRequest(uploadImage);
That calls:
import * as admin from "firebase-admin";
import * as Busboy from "busboy";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
const cors = require("cors")({ origin: true });
const spawn = require("child-process-promise").spawn;
const gcconfig = {
projectId: "PROJECT_ID",
keyFilename: "key.json"
};
const gcs = require("#google-cloud/storage")(gcconfig);
export const uploadImage = (req, res) => {
cors(req, res, () => {
if (req.method === "POST") {
const busboy = new Busboy({ headers: req.headers });
const docRef = req.query.docRef;
const fieldRef = req.query.fieldRef;
const storageRef = req.query.storageRef;
let fileData = null;
// Max height and width of the thumbnail in pixels.
const THUMB_MAX_HEIGHT = 100;
const THUMB_MAX_WIDTH = 100;
const THUMB_PREFIX = "thumb_";
const RESIZED_MAX_HEIGHT = 500;
const RESIZED_MAX_WIDTH = 500;
const RESIZED_PREFIX = "resized_";
const ORIGINAL_MAX_HEIGHT = 1000;
const ORIGINAL_MAX_WIDTH = 1400;
// Listen for event when Busboy finds a file to stream.
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
const tempLocalFile = path.join(os.tmpdir(), filename);
fileData = { file: filename, type: mimetype };
// Download file local tmp.
file.pipe(fs.createWriteStream(tempLocalFile));
});
busboy.on("finish", () => {
// File and directory paths.
const tempLocalFile = path.join(os.tmpdir(), fileData.file);
const tempLocalThumbFile = path.join(os.tmpdir(),`${THUMB_PREFIX}${fileData.file}`);
const tempLocalResizedFile = path.join(os.tmpdir(),`${RESIZED_PREFIX}${fileData.file}`);
const origFilePath = path.normalize(path.join(storageRef, fileData.file));
const thumbFilePath = path.normalize(path.join(storageRef, `${THUMB_PREFIX}${fileData.file}`));
const resizedFilePath = path.normalize(path.join(storageRef, `${RESIZED_PREFIX}${fileData.file}`));
// Cloud Storage files.
const bucket = gcs.bucket("PROJECT_ID.appspot.com");
const metadata = {
contentType: fileData.type,
"Cache-Control": "public,max-age=3600"
};
// Generate a thumbnail called tempLocalThumbFile
const promise = spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`,
tempLocalThumbFile
],
{ capture: ["stdout", "stderr"] }
);
return promise
.then(() => {
// Generate a resized_ called tempLocalResizedFile
return spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${RESIZED_MAX_WIDTH}x${RESIZED_MAX_HEIGHT}>`,
tempLocalResizedFile
],
{ capture: ["stdout", "stderr"] }
);
})
.then(() => {
// Resize original to ensure it's not massive
return spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${ORIGINAL_MAX_WIDTH}x${ORIGINAL_MAX_HEIGHT}>`,
tempLocalFile
],
{ capture: ["stdout", "stderr"] }
);
})
.then(() => {
// upload images to storage
const thumbUp = bucket.upload(tempLocalThumbFile, {
destination: thumbFilePath,
metadata: metadata
});
const resizeUp = bucket.upload(tempLocalResizedFile, {
destination: resizedFilePath,
metadata: metadata
});
const origUp = bucket.upload(tempLocalFile, {
destination: origFilePath,
metadata: metadata
});
return Promise.all([thumbUp, resizeUp, origUp]);
})
.then(() => {
// Once the image has been uploaded delete the local files to free up disk space.
fs.unlinkSync(tempLocalFile);
fs.unlinkSync(tempLocalThumbFile);
fs.unlinkSync(tempLocalResizedFile);
const config = {
action: "read",
expires: "03-01-2500"
};
// Get the Signed URLs for the thumbnail and original image.
return Promise.all([
bucket.file(thumbFilePath).getSignedUrl(config),
bucket.file(resizedFilePath).getSignedUrl(config),
bucket.file(origFilePath).getSignedUrl(config)
]);
})
.then(results => {
console.log("Got Signed URLs.", results);
const thumbFileUrl = results[0][0];
const resizeFileUrl = results[1][0];
const origFileUrl = results[2][0];
// Add the URLs to the Database
return admin
.firestore()
.doc(docRef)
.update({
[fieldRef + ".original"]: origFileUrl,
[fieldRef + ".resized"]: resizeFileUrl,
[fieldRef + ".thumb"]: thumbFileUrl
});
})
.then(() => {
console.log("Image URLs saved to Firestore.");
res.status(200).send({
message: "File Saved."
});
})
.catch(err => {
console.log("Error:", err);
res.status(500).send({
error: err
});
});
});
busboy.end(req.rawBody);
} else {
return res.status(500).json({
message: "Not Allowed"
});
}
});
};
The error message I receive when it fails is:
Error: { ChildProcessError: convert /tmp/ff658860-cc0f-11e8-bd7d-178b6a853dfe.png -thumbnail 100x100> /tmp/thumb_ff658860-cc0f-11e8-bd7d-178b6a853dfe.png failed with code 1 at ChildProcess. (/user_code/node_modules/child-process-promise/lib/index.js:132:23) at emitTwo (events.js:106:13) at ChildProcess.emit (events.js:191:7) at maybeClose (internal/child_process.js:920:16) at Socket. (internal/child_process.js:351:11) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7) at Pipe._handle.close [as _onclose] (net.js:509:12) name: 'ChildProcessError', code: 1, childProcess: ChildProcess { domain: Domain { domain: null, _events: [Object], _eventsCount: 1, _maxListeners: undefined, members: [] }, _events: { error: [Function: t], close: [Function] }, _eventsCount: 2, _maxListeners: undefined, _closesNeeded: 3, _closesGot: 3, connected: false, signalCode: null, exitCode: 1, killed: false, spawnfile: 'convert', _handle: null, spawnargs: [ 'convert', '/tmp/ff658860-cc0f-11e8-bd7d-178b6a853dfe.png', '-thumbnail', '100x100>', '/tmp/thumb_ff658860-cc0f-11e8-bd7d-178b6a853dfe.png' ], pid: 12, stdin: Socket { connecting: false, _hadError: false, _handle: null, _parent: null, _host: null, _readableState: [Object], readable: false, domain: [Object], _events: [Object], _eventsCount: 2, _maxListeners: undefined, _writableState: [Object], writable: false, allowHalfOpen: false, destroyed: true, _bytesDispatched: 0, _sockname: null, _pendingData: null, _pendingEncoding: '', server: null, _server: null, write: [Function: writeAfterFIN], _idleNext: null, _idlePrev: null, _idleTimeout: -1 }, stdout: Socket { connecting: false, _hadError: false, _handle: null, _parent: null, _host: null, _readableState: [Object], readable: false, domain: [Object], _events: [Object], _eventsCount: 4, _maxListeners: undefined, _writableState: [Object], writable: false, allowHalfOpen: false, destroyed: true, _bytesDispatched: 0, _sockname: null, _pendingData: null, _pendingEncoding: '', server: null, _server: null, read: [Function], _consuming: true, _idleNext: null, _idlePrev: null, _idleTimeout: -1, write: [Function: writeAfterFIN] }, stderr: Socket { connecting: false, _hadError: false, _handle: null, _parent: null, _host: null, _readableState: [Object], readable: false, domain: [Object], _events: [Object], _eventsCount: 4, _maxListeners: undefined, _writableState: [Object], writable: false, allowHalfOpen: false, destroyed: true, _bytesDispatched: 0, _sockname: null, _pendingData: null, _pendingEncoding: '', server: null, _server: null, read: [Function], _consuming: true, _idleNext: null, _idlePrev: null, _idleTimeout: -1, write: [Function: writeAfterFIN] }, stdio: [ [Object], [Object], [Object] ] }, stdout: '', stderr: 'convert: improper image header /tmp/ff658860-cc0f-11e8-bd7d-178b6a853dfe.png\' # error/png.c/ReadPNGImage/3927.\nconvert: no images defined/tmp/thumb_ff658860-cc0f-11e8-bd7d-178b6a853dfe.png\' # error/convert.c/ConvertImageCommand/3210.\n' }
I'm not familiar with busboy but believe I'm ending the process correctly, but as this typically only works for the first upload after saving the cloud function, I suspect the code may not be ending cleanly?
Any help is greatly appreciated. Thank you.

How to connect to MongoDB using Node.js written in TypeScript?

I'm working on a Node.js server, connecting to MongoDB and written with TypeScript. When I try to use MongoDB it doesn't create a connection, however when I check the mongo output it does appear to create a connection.
What am I missing in my code to define the connection in Node.js?
My connection string is 'mongodb://localhost:27017'
My connection method:
connect() {
console.log('connecting to mongo') //this is called
MongoClient.connect(this.connectionString, {useNewUrlParser: true})
.then(client => {
console.log('setting client'); //this doesn't get called
this.client = client;
console.log(this.client);
})
.catch(error => {
console.log('error during connecting to mongo: '); //this also doesn't get called
console.error(error);
});
}
Mongo output:
2018-11-08T23:06:24.106+0100 I NETWORK [listener] connection accepted from 127.0.0.1:51345 #11 (2 connections now open)
2018-11-08T23:06:24.107+0100 I NETWORK [conn11] received client metadata from 127.0.0.1:51345 conn11: { driver: { name: "nodejs", version: "3.1.9" }, os: { type: "Darwin", name: "darwin", architecture: "x64", version: "17.7.0" }, platform: "Node.js v8.9.3, LE, mongodb-core: 3.1.8" }
My repository is at https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/db/mongo.db.ts for the full code.
console.log(db) as asked by shkaper
MongoClient {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
s:
{ url: 'mongodb://localhost:27017',
options:
{ servers: [Array],
caseTranslate: true,
useNewUrlParser: true,
socketTimeoutMS: 360000,
connectTimeoutMS: 30000,
promiseLibrary: [Function: Promise] },
promiseLibrary: [Function: Promise],
dbCache: {},
sessions: [] },
topology:
Server {
domain: null,
_events:
{ serverOpening: [Function],
serverDescriptionChanged: [Function],
serverHeartbeatStarted: [Function],
serverHeartbeatSucceeded: [Function],
serverHeartbeatFailed: [Function],
serverClosed: [Function],
topologyOpening: [Function],
topologyClosed: [Function],
topologyDescriptionChanged: [Function],
commandStarted: [Function],
commandSucceeded: [Function],
commandFailed: [Function],
joined: [Function],
left: [Function],
ping: [Function],
ha: [Function],
authenticated: [Function],
error: [Function],
timeout: [Function],
close: [Function],
parseError: [Function],
open: [Object],
fullsetup: [Object],
all: [Object],
reconnect: [Function] },
_eventsCount: 25,
_maxListeners: Infinity,
clientInfo:
{ driver: [Object],
os: [Object],
platform: 'Node.js v8.9.3, LE' },
s:
{ coreTopology: [Object],
sCapabilities: null,
clonedOptions: [Object],
reconnect: true,
emitError: true,
poolSize: 5,
storeOptions: [Object],
store: [Object],
host: 'localhost',
port: 27017,
options: [Object],
sessionPool: [Object],
sessions: [],
promiseLibrary: [Function: Promise] } } }
The issue is because mongo.connect is async code and controller call it wrongly. so the subsequent line mongo.getDb() will be executed without having this.client initiated properly.
Since you use Typescript, we can use async/await for cleaner code.
async connect() { // add async
console.log('connecting to mongo');
try {
if (!this.client) { // I added this extra check
console.log('setting client');
this.client = await MongoClient.connect(this.connectionString, { useNewUrlParser: true })
console.log(this.client);
}
} catch(error) {
console.log('error during connecting to mongo: ');
console.error(error);
}
}
And in controller code
async get(req: Request, res: Response) { // add async
const mongo = new MongoDb();
await mongo.connect(); // add await
const db = mongo.db();
// ....
}
I tried your repo with the changes and got this response
Hope it helps
Based on what you said about neither error nor success callbacks being called, I think the problem is not only in code here: https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/db/mongo.db.ts
But also e.g. here: https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/controllers/to-do.controller.ts
When you run mongo.connect there should be an option to wait for the promise returned from MongoClient.connect. So I would change code in mongo.db.ts to for example sth like this (it depends how you want to handle this promise):
connect() {
console.log('connecting to mongo')
return MongoClient.connect(this.connectionString, {useNewUrlParser: true})
.then(client => {
console.log('setting client');
this.client = client;
console.log(this.client);
})
.catch(error => {
console.log('error during connecting to mongo: ');
console.error(error);
});
}
Then in to-do.controller.ts you can await this or use then:
get(req: Request, res: Response) {
const mongo = new MongoDb();
mongo.connect().then(() => {
const db = mongo.getDb();
const collection = db.collection('todo', (error, collection) => {
if (error) {
res.json(error);
res.statusCode = HttpStatus.BAD_REQUEST
return;
}
collection.find().toArray((error, result) => {
if (error) {
res.json(error);
res.statusCode = HttpStatus.BAD_REQUEST
}
res.json(result);
res.statusCode = HttpStatus.OK;
})
});
mongo.close();
});
}
I suppose that your code just does not "wait" for connection to be established and then fails.
The above solutions do work but there is another method that I like a bit better. It more resembles a standard HTTP call (I've gotten it to work with and without the async-await, but it's a good idea to leave it in):
private async connect(){
this.mongo = new mongodb.MongoClient(this.url, {useNewParser: true});
await this.mongo.connect((err, client) => {
if(client.isConnected()){
console.log('setting client');
this.client = client;
console.log(this.client);
}
else{
console.log('error during connecting to mongo: ');
console.error(error);
}
});
}
This is based off the Node.js driver api v3.2 that you can look over here:
https://mongodb.github.io/node-mongodb-native/3.2/api/index.html
It might just be a different way of shaving a cat but I figure it's worth sharing for anyone else who ends up here later.

MongoDB error while retrieving collection

I'm having a problem getting collection from the database in my Node.js application. I'm using Mongodb 3.6.
That's how I set it up:
var moment = require('moment');
var MongoClient = require('mongodb').MongoClient;
/*
===========================================================================
DB setup
===========================================================================
*/
var state = {
db: null,
}
function get() {
return state.db;
}
exports.connect_database = function(done) {
if (state.db) return done()
MongoClient.connect(process.env.DATABASE_URL, function(err, db) {
if (err) return done(err)
state.db = db
done()
})
}
/* some other functions ... */
exports.return_collection = function(collection_name, callback) {
var result_array = [];
var collection = get().getCollection(collection_name);
var result = collection.find()
result.forEach(function(res) {
result_array.push(res);
}, function(error) {
console.log("error: ")
console.log(error);
if (!error)
callback(result_array);
});
}
In the main file I do:
'use strict';
// LIB IMPORTS
var env = require('node-env-file');
env(__dirname + '/.env');
// LOCAL IMPORTS
var aux = require('./modules/aux.js');
var scheduler = require('./modules/scheduler.js');
var Bot = require('./modules/bot.js');
/*
===========================================================================
DB setup
===========================================================================
*/
aux.connect_database((err) => {
if (err) {
console.log('Unable to connect to Mongo.')
process.exit(1)
} else {
console.log('Connected to db.');
}
})
I can see in the log the Connected to db. prompt, so the connection works fine. After that I try to call some function to add/retrieve data from the db and i get the error:
TypeError: get(...).getCollection is not a function
at Object.exports.return_collection
If I try to print the state.db variable I get the following result:
MongoClient {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
s:
{ url: 'mongodb://localhost:27017/BotDb',
options:
{ socketOptions: {},
read_preference_tags: null,
readPreference: [Object],
dbName: 'slackBotDb',
servers: [Object],
server_options: [Object],
db_options: [Object],
rs_options: [Object],
mongos_options: [Object],
socketTimeoutMS: 360000,
connectTimeoutMS: 30000,
promiseLibrary: [Function: Promise] },
promiseLibrary: [Function: Promise],
dbCache: {},
sessions: [] },
topology:
Server {
domain: null,
_events:
{ serverOpening: [Function],
serverDescriptionChanged: [Function],
serverHeartbeatStarted: [Function],
serverHeartbeatSucceeded: [Function],
serverHeartbeatFailed: [Function],
serverClosed: [Function],
topologyOpening: [Function],
topologyClosed: [Function],
topologyDescriptionChanged: [Function],
joined: [Function],
left: [Function],
ping: [Function],
ha: [Function],
authenticated: [Function],
error: [Function],
timeout: [Function],
close: [Function],
parseError: [Function],
open: [Object],
fullsetup: [Object],
all: [Object],
reconnect: [Function] },
_eventsCount: 22,
_maxListeners: undefined,
clientInfo:
{ driver: [Object],
os: [Object],
platform: 'Node.js v7.10.0, LE' },
s:
{ coreTopology: [Object],
sCapabilities: null,
clonedOptions: [Object],
reconnect: true,
emitError: true,
poolSize: 5,
storeOptions: [Object],
store: [Object],
host: 'localhost',
port: 27017,
options: [Object],
sessionPool: [Object],
promiseLibrary: [Function: Promise] } } }
What am I missing? In the mongo console everything looks fine:
> db.getCollection("users");
BotDb.users
I can't find any function named getCollection in the API documentation for the Node.js MongoDB native driver. Collections are usually fetched with collection('mycoll'). So you can rewrite this line:
var collection = get().getCollection(collection_name);
to
var collection = get().collection(collection_name);
Note that if you use v3.0 or later of the driver you have to modify the connect function as well. There were some changes done to the connection functions (see here). The callback now returns a client object rather than the db object. So you'll have to change your function to:
exports.connect_database = function(done) {
if (state.db) return done()
MongoClient.connect(process.env.DATABASE_URL, function(err, client) {
if (err) return done(err);
state.db = client.db('database_name');
done();
})
}
Note the 'database_name' string. It should be the name of your database.

Sinon spy assert fails even though call count is 1

Using Node, Sinon, Chai, proxyquire for fetch, and Mocha
How come this sinon spy assertion fooCallback1.should.have.been.called; is failing to be called once? I see with console.log(fooCallback1) in the source code that the callCount is 1.
This is the first and only test...so I don't see a reason to reset the spy.
function setLight(...args) {
var request;
var lightNumber;
var alertName;
var callback1;
var callback2;
var callback3;
[request, lightNumber, alertName,
callback1, callback2, callback3] = args;
return fetch(request)
.then(status)
.then(toJSON)
.then(() => {
if(Boolean(callback1)) {
console.log('one')
callback1(lightNumber);
console.log(callback1);
}
before(()=> {
fetch = sinon.stub().returnsPromise();
var response = {
status: 200,
json: () => { 'foo' }
};
fetch.resolves(response);
fetchHelper = proxy('../lib/fetch-helper', {'node-fetch': fetch});
});
it('should run fetch for light effect and shutoff', (done)=> {
var fooCallback1 = sinon.spy();
fetchHelper.setLight('foo', 123, 'foo-alert', fooCallback1);
fetch.should.have.been.called;
fooCallback1.should.have.been.called;
done();
});
1) when executing setLight should run fetch for light effect and shutoff:
AssertionError: expected spy to have been called at least once, but it was never called
at Context.it (test/fetch-helper.js:24:34)
when executing setLight
1) should run fetch for light effect and shutoff
one
{ [Function: proxy]
isSinonProxy: true,
formatters:
{ c: [Function: c],
n: [Function: n],
D: [Function: D],
C: [Function: C],
t: [Function: t],
'*': [Function: *] },
reset: [Function: reset],
invoke: [Function: invoke],
named: [Function: named],
getCall: [Function: getCall],
getCalls: [Function: getCalls],
calledBefore: [Function: calledBefore],
calledAfter: [Function: calledAfter],
calledImmediatelyBefore: [Function: calledImmediatelyBefore],
calledImmediatelyAfter: [Function: calledImmediatelyAfter],
withArgs: [Function: withArgs],
matches: [Function: matches],
printf: [Function: printf],
calledOn: [Function],
alwaysCalledOn: [Function],
calledWith: [Function],
calledWithMatch: [Function],
alwaysCalledWith: [Function],
alwaysCalledWithMatch: [Function],
calledWithExactly: [Function],
alwaysCalledWithExactly: [Function],
neverCalledWith: [Function],
neverCalledWithMatch: [Function],
threw: [Function],
alwaysThrew: [Function],
returned: [Function],
alwaysReturned: [Function],
calledWithNew: [Function],
alwaysCalledWithNew: [Function],
callArg: [Function],
callArgWith: [Function],
callArgOn: [Function],
callArgOnWith: [Function],
yield: [Function],
invokeCallback: [Function],
yieldOn: [Function],
yieldTo: [Function],
yieldToOn: [Function],
spyCall: { [Function: createSpyCall] toString: [Function: toString] },
called: true,
notCalled: false,
calledOnce: true,
calledTwice: false,
calledThrice: false,
callCount: 1,
firstCall:
{ proxy: [Circular],
thisValue: undefined,
args: [ 123 ],
returnValue: undefined,
exception: undefined,
callId: 11,
errorWithCallStack:
Error
at Function.invoke (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:205:19)
at proxy (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:97:22)
at fetch.then.then.then (/home/one/github/lifx-weather/lib/fetch-helper.js:52:9)
at process._tickCallback (internal/process/next_tick.js:103:7) },
secondCall: null,
thirdCall: null,
lastCall:
{ proxy: [Circular],
thisValue: undefined,
args: [ 123 ],
returnValue: undefined,
exception: undefined,
callId: 11,
errorWithCallStack:
Error
at Function.invoke (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:205:19)
at proxy (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:97:22)
at fetch.then.then.then (/home/one/github/lifx-weather/lib/fetch-helper.js:52:9)
at process._tickCallback (internal/process/next_tick.js:103:7) },
args: [ [ 123 ] ],
returnValues: [ undefined ],
thisValues: [ undefined ],
exceptions: [ undefined ],
callIds: [ 11 ],
errorsWithCallStack:
[ Error
at Function.invoke (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:205:19)
at proxy (/home/one/github/lifx-weather/node_modules/sinon/lib/sinon/spy.js:97:22)
at fetch.then.then.then (/home/one/github/lifx-weather/lib/fetch-helper.js:52:9)
at process._tickCallback (internal/process/next_tick.js:103:7) ],
displayName: 'spy',
toString: [Function: toString],
instantiateFake: [Function: create],
id: 'spy#11' }
- should set normal alert lock on
- should set normal alert lock off after time
0 passing (15ms)
2 pending
1 failing
1) when executing setLight should run fetch for light effect and shutoff:
AssertionError: expected spy to have been called at least once, but it was never called
at Context.it (test/fetch-helper.js:27:34)
Here is another way I wrote the test and still same result:
before((done)=> {
fetch = sinon.stub().returnsPromise();
fetchHelper = proxy('../lib/fetch-helper', {'node-fetch': fetch});
done()
});
after(()=> {
});
it('should run fetch for light effect and shutoff', (done)=> {
function fooCallback1() { console.log('aaaaaaaaaaaaaaaaaaaa') }
var foo = sinon.spy(fooCallback1)
fetchHelper.setLight('foo', 123, 'foo-alert', fooCallback1);
var response = {
status: 200,
json: () => { 'foo' }
};
fetch.resolves(response);
fetch.should.have.been.called;
foo.should.have.been.called;
done();
});
when executing setLight
one
aaaaaaaaaaaaaaaaaaaa
1) should run fetch for light effect and shutoff
- should set normal alert lock on
- should set normal alert lock off after time
0 passing (10ms)
2 pending
1 failing
1) when executing setLight should run fetch for light effect and shutoff:
AssertionError: expected fooCallback1 to have been called at least once, but it was never called
at Context.it (test/fetch-helper.js:28:25
fetchHelper.setLight() is asynchronous, but your test isn't waiting for it to complete, so the order in which the code is run is something like this:
fetchHelper.setLight()
fetch(request)
fetch.should.have.been.called
fooCallback1.should.have.been.called
done()
console.log('one')
callback1(lightNumber)
console.log(callback1)
You need to rewrite the test so it will wait for the callback to get called. You don't use a spy for that, but a regular callback function in which you test the assertion(s):
it('should run fetch for light effect and shutoff', done => {
fetchHelper.setLight('foo', 123, 'foo-alert', () => {
fetch.should.have.been.called;
done();
});
});
In addition to robertklep's excellent answer, here is a alternate way I got it to work. I call the fetch resolve after calling the fetch wrapper setLight:
it('should run fetch for light effect and shutoff', (done)=> {
var foo = sinon.spy()
fetchHelper.setLight('foo', 123, 'foo-alert', foo);
fetch.resolves(response);
fetch.should.have.been.called;
foo.should.have.been.called;
done();
});

azure blob storage node.js backend

I'm following this article on how to upload a blob into a container. This is what I've have
var azure = require('azure-storage');
var blobSvc = azure.createBlobServiceAnonymous('https://<storage-name>.blob.core.windows.net/');
exports.post = function(request, response) {
console.log(request.files); // [1]
blobSvc.createBlockBlobFromLocalFile('dubfiles', 'myblob', request.files.file.name, function(error, result, response){
if(!error){
// file uploaded
console.log(response); //[2]
console.log(result); // [3]
}
});
};
[1] Logs this
{ file:
{ domain: null,
_events: null,
_maxListeners: 10,
size: 859552,
path: 'D:\\local\\Temp\\155976e3a6b8e0aa871c5deee05af9f2',
name: 'heuristic-serch.pdf',
type: 'application/pdf',
hash: false,
lastModifiedDate: Tue Jun 23 2015 08:43:55 GMT+0000 (Coordinated Universal Time),
_writeStream: {
domain: null,
_events: null,
_maxListeners: 10,
path: 'D:\\local\\Temp\\155976e3a6b8e0aa871c5deee05af9f2',
fd: 3,
writable: false,
flags: 'w',
encoding: 'binary',
mode: 438,
bytesWritten: 859552,
busy: false,
_queue: [],
_open: [Function],
drainable: true,
flush: [Function],
write: [Function],
end: [Function],
destroy: [Function],
destroySoon: [Function],
pipe: [Function],
setMaxListeners: [Function],
emit: [Function],
addListener: [Function],
on: [Function],
once: [Function],
removeListener: [Function],
removeAllListeners: [Function],
listeners: [Function] },
open: [Function],
toJSON: [Function],
write: [Function],
end: [Function],
setMaxListeners: [Function],
emit: [Function],
addListener: [Function],
on: [Function], once: [Function],
removeListener: [Function],
removeAllListeners: [Function],
listeners: [Function]
}
}
[2] Logs no response to logs
[3] Logs no result to logs
The container is empty when I check on the azure management portal.
How can this be done correctly?
I'm now able to upload a blob to a container. This is what I have
var azure = require('azure-storage');
exports.post = function(request, response) {
var accountName = request.service.config.appSettings.STORAGE_ACCOUNT_NAME; // storage account name at appSettings
var accountKey = request.service.config.appSettings.STORAGE_ACCOUNT_ACCESS_KEY; //storage account key at appSettings
var host = accountName + '.blob.core.windows.net';
var container = 'container_name';
var blobSvc = azure.createBlobService(accountName, accountKey, host);
blobSvc.createContainerIfNotExists(container, {publicAccessLevel : 'blob'}, function(error, result, response){
if(!error){
console.log('no error occurred!'); // logs if no error occurred
console.log(result); // logs false if container already exists
console.log(response); // logs response including the etag
//Container exists and allows
//anonymous read access to blob
//content and metadata within this container
blobSvc.createBlockBlobFromLocalFile(container, request.files.file.name, request.files.file.path, function(error, result, response){
if(!error){
// file uploaded
// console.log(error);
console.log(response); // logs response
console.log(result); // logs result
}
});
}
});
};

Resources