I have this function and I want to test it. I want to test stream.on('error', err => reject(err)); line, but don't know how to reach it. What could I input in this function to trigger the error throw? Thank you!
function streamToString(stream) {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('data', chunk => chunks.push(Buffer.from(chunk)));
stream.on('error', err => reject(err));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
}
If you are in nodejs and using jest you could Emit the error by your self like:
function streamToString(stream) {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
stream.on("error", (err) => reject(err));
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
});
}
test("broken stream", () => {
let fs = require("fs");
let stream = fs.createReadStream("file.txt");
let res = streamToString(stream);
stream.emit("error", "OH NO!");
return expect(res).rejects.toMatch("OH NO!");
});
//or
test("broken stream", () => {
let fs = require("fs");
let stream = fs.createReadStream("file.txt");
let res = streamToString(stream);
stream.destroy("OH NO!");
return expect(res).rejects.toMatch("OH NO!");
});
Related
Please excuse my ignorance on node.
I need to read an image through a url and resize it through sharp.
Currently I have it like this to read local.
For example.
I want to read this image
url= "https://miami.pfsrealty.com/wp-content/uploads/2020/02/Miami-y-su-bahia-con-nubes-al-atardecer-Compressed.jpg"
And my current code is this.
return new Promise(async (resolve, reject) => {
const fileSystem = require('fs');
const image = fileSystem.readFileSync(directoryPath, 'base64');
const sharp = require('sharp');
const height: number = parseInt(heightString);//parameter
const width: number = parseInt(widthString);//parameter
let img = new Buffer(image, 'base64');
await sharp(img)
.resize(height, width)
.toBuffer()
.then(resizedImageBuffer => {
const resizedImageData = resizedImageBuffer.toString('base64');
resolve(resizedImageData);
})
.catch(error => {
// error handeling
reject(error);
});
});
How should the call be?
Thanks !
try this
const sharp = require('sharp');
const fs = require('fs');
function readAndSave(url, width = 300, height = 300) {
const filename = url.replace(/^.*[\\\/]/, '');
require('axios').get(url, { responseType: 'arraybuffer' })
.then((response) => {
return Buffer.from(response.data, "utf-8")
}).then((buffer) => {
return new Promise((resolve, reject) => {
sharp(buffer)
.resize(height, width)
.toBuffer()
.then(resizedImageBuffer => {
const resizedImageData = resizedImageBuffer.toString('base64');
const buf = Buffer.from(resizedImageData, 'base64');
fs.writeFile(`./${filename}`, buf, function (err) {
if (err) throw err;
});
resolve()
})
.catch(error => {
// error handeling
reject(error);
});
})
}).catch(error => {
console.log('error', error)
});
}
readAndSave('https://miami.pfsrealty.com/wp-content/uploads/2020/02/Miami-y-su-bahia-con-nubes-al-atardecer-Compressed.jpg');
I have a little problem, I need the makeZip function to wait for the takeScreenshot function to take all the screenshots it needs, how do I do this while taking care of best practices?
(I know at this point "then" doesn't make sense with the post method, I just tried it my way before but it didn't work the way I wanted)
Function:
const takeScreenshot = (url) => {
const resolutionsArray = Object.values(resolutions);
resolutionsArray.map(async (mediaSize) => {
webshot(url, setFileName(url, mediaSize), setOptions(mediaSize), (err) => {
if (!err) {
console.log("screenshot taken!");
}
});
});
};
calling functions:
app.post("/", async (req, res) => {
const { url } = req.body;
takeScreenshot(url)
.then((url) => makeZip(url))
.then((url) => sendEmail(url))
.then((message) => res.send(message))
.catch((err) => console.log(err));
});
My suggestion is:
to use Promise.all or Promise.allSettled when you need to handle several promises
extract callback of map fn
const makeWebshot = (argsHere) => new Promise((reselove, reject) => {
webshot(url, setFileName(url, mediaSize), setOptions(mediaSize), (err) => {
if (err) return reject(err);
return resolve();
});
});
Update takeScreenshot to
const takeScreenshot = (url) => {
const resolutionsArray = Object.values(resolutions);
return Promise.all(resolutionsArray.map((mediaSize) => makeWebshot(argsHere)));
};
When dealing with a list of Promises you will want to use Promise.all to wait for them all to resolve. Here is a simple example:
const list = [1,2,3];
const all = list.map(i => new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i);
resolve(i*2);
}, 100);
}));
Promise.all(all).then(console.log)
In your case it would be something like this:
const takeScreenshot = (url) =>
Object.values(resolutions).map(async (mediaSize) => {
webshot(url, setFileName(url, mediaSize), setOptions(mediaSize), (err) => {
if (!err) {
console.log("screenshot taken!");
}
});
});
app.post("/", async (req, res) => {
const { url } = req.body;
Promise.all(takeScreenshot(url))
.then((listOfUrls) => ...
});
But since I don't know what webshot returns, I can't tell you what the processing of the listOfUrls should look like.
so I am new to async/await on node.js and I could use some help figuring out this code.
I'm trying to get a file from a ftp server via the 'ftp' package, to write the data into a local 'data.txt' and to open it later in the code. My problem is that I don't understand how to make sure the file is completely written in the 'data.txt' before trying to open it with fs.readFileSync().
const ConfigFTP = require('./credentials.json')
const FtpClient = new ftpclient();
FtpClient.on('ready', async function() {
await new Promise(resolve =>
FtpClient.get('the ftp file directory', (err, stream) => {
if (err) throw err;
stream.once('close', () => {FtpClient.end();});
// Stream written in data.txt
const Streampipe = stream.pipe(fs.createWriteStream('data.txt')).on('finish', resolve)
})
)
})
FtpClient.connect(ConfigFTP);
var Data = fs.readFileSync('data.txt', 'utf8');
I'm not sure what you want to accomplish, but you can do something like these:
1)
const ConfigFTP = require('./credentials.json')
const FtpClient = new ftpclient()
let writeStream = fs.createWriteStream('data.txt')
FtpClient.on('ready', async function () {
FtpClient.get('the ftp file directory', (err, stream) => {
if (err) throw err
stream.once('close', () => { FtpClient.end() })
// Stream written in data.txt
const Streampipe = stream.pipe(writeStream)
})
})
FtpClient.connect(ConfigFTP)
writeStream.on('finish', () => {
var Data = fs.readFileSync('data.txt', 'utf8')
})
2)
const ConfigFTP = require('./credentials.json')
const FtpClient = new ftpclient()
FtpClient.on('ready', async function() {
await new Promise(resolve =>
FtpClient.get('the ftp file directory', (err, stream) => {
if (err) throw err
stream.once('close', () => {FtpClient.end()})
// Stream written in data.txt
const Streampipe = stream.pipe(fs.createWriteStream('data.txt')).on('finish', resolve)
})
)
var Data = fs.readFileSync('data.txt', 'utf8')
})
FtpClient.connect(ConfigFTP)
I have a function that downloads a file using got and uses fs.createWritableStream to write file on disk. The code is working smooth but the unit test are being a pain:
download(twilioPath, destFile) {
return new Promise(function(resolve, reject) {
const uri = `${TWILIO_BASE_URL}${twilioPath}`.replace('json', 'mp3')
let file = fs.createWriteStream(`/tmp/${destFile}`)
console.log(got)
let str = got.stream(uri)
console.log(uri)
str.on('error', function(err) {
console.log('Error dl', err)
reject(err)
})
str.pipe(file)
file.on('finish', function() {
console.log('banana')
let cb = function() {
console.log('Download completed')
resolve(file)
}
file.close(cb)
})
})
My resolve or reject is not being called and I don't know how to fix that:
const Recording = require('./Recording')
const Readable = require('stream')
var mockedStream = new Readable();
var mockedWrite = new Readable.Writable()
jest.mock('fs', () => ({
createWriteStream: jest.fn((file_name) => {
return mockedWrite;
})
}));
jest.mock('got', () => {
return {
stream: () => {
return mockedStream
}
}
})
describe('Recording', () => {
test('should download a file from twilio', async () => {
...
mockedStream.emit('error')
mockedWrite.emit('finish')
console.log(result)
....
})
})
I've tried to force emit events but no lucky.
how can i use multi promise await in my codes ? when i wanna use second await for second promise it throw an error
function ReadJSONFile() {
return new Promise((resolve, reject) => {
fs.readFile('import.json', 'utf-8', (err, data) => {
if (err) reject(err);
resolve(JSON.parse(data));
});
});
}
const Get_Image = async (Path) => {
Child_Process = exec('node get_image.js "'+Path+'",(err,stdout,stderr) =>
return new Promise((resolve,reject) => {
resolve(stdout);
});
}
const Catch = async () => {
let get_json_file = await ReadJSONFile(); // this works perefectly
for(var i=0;i< Object.keys(get_json_file);i++) {
console.log(await Get_Image(get_json_file[i].image_path); //but this throw error
}
}
you didn`t return a promise that is why you got an error
const Get_Image = async (Path) => {
return new Promise((resolve,reject) => {
Child_Process = exec('node get_image.js "'+Path+'",(err,stdout,stderr) =>
resolve(stdout);
});
});
}