Mocha 'before each hook' error message - javascript

I have the following message, just before a failing test
Below is my piece of code
before(function(done) {
function afterListening() {
customFormats(ZSchema);
done();
}
if (app.server.listening) return afterListening();
app.on('listening', afterListening);
});
describe('/a1/{exampleID}', function() {
describe('get', function() {
it('should respond with 200 Return an array of shelter...', function(done) {
/*eslint-disable*/
var schema = {
"type": [
"object",
"null"
],
"properties": {
"meta": {
"type": [
"object",
"null"
],
"properties": {
"resource": {
"type": [
"string",
"null"
],
"description": "fully qualified URL call"
},
"version": {
"type": [
"string",
"null"
],
"description": "version of API being called"
},
"response": {
"type": [
"integer",
"null"
],
"format": "int32",
"description": "status code"
},
"required": [
"version",
"resource"
]
}
}
};
/*eslint-enable*/
api.get('/a1/example/64442')
.set('Content-Type', 'application/json')
.expect(200)
.end(function(err, res) {
if (err) return done(err);
validator.validate(res.body, schema).should.be.true;
done();
});
});
});
});
Error
1) example "before each" hook:
Error: timeout of 200ms exceeded. Ensure the done() callback is being
called in this test.
at null. (lib/runnable.js:170:19)
This error came only when I run the test case on my machine.If I run the same test case in another machine the test case is passing. why it happens.It's weird to see like this.
Any help, please!!

You generally receive timeout error, when you are not returning a promise as expected.
Done is the older implementation of the same, but no longer required. If you are using a recent version of Mocha, you should be able to just return the promise instead of calling Done().
Here are details on mocha-as-promised - which was integrated with default Mocha, since version 1.18.0.
Example of how you should return a promise:
it("should be fulfilled with 5", function () {
return promise.should.become(5);
});
In case of beforeeach - implementation should look like this:
beforeEach(() => {
const {col1, comments} = mongoose.connection.collections;
return col1.drop(() => {
// Do something after collection is dropped
});
});
Notice return for the action taken within beforeeach.

Can you please share your beforeEach with us so we can help?
Without looking, it might be because your connection to whatever thing you're connecting to isn't responding on time or isn't responding at all.
Might wanna check your connection to places where your unit tests are connecting (chances are it's the database, because it's in beforeEach() and beforeEach() doesn't require a done() to be called inside it.
Increase your timeout to something like 10 seconds or such. If you don't get database errors then, your connection is slow. If you still get timeout errors even at 10 seconds, you might have no connection at all.

Related

How do you send HTTP POST Requests from a slack app in socket mode?

I am currently creating a bolt slack app with JavaScript that needs to send out an HTTP POST request to an external webhook when a button click occurs. Sending data to my slack app from external sources is simple enough using the slack webhook provided in the app settings, but I can't seem to figure out how to send a message from my app.js file. My app is currently in Socket Mode since I didn't want to set up a Request URL after my Ngrok url didn't seem to work with the verification in slack, and there doesn't seem to be a lot of documentation on this issue. Of the documentation I did find, https://api.slack.com/apis/connections/socket-implement#connect, I wasn't sure how to implement apps.connections.open into my JavaScript file. I am fairly new to JavaScript and HTTP Requests, so any help would be greatly appreciated. I am also using the Bolt app package for slack, below is my code.
const { App } = require('#slack/bolt');
// Initializes your app with your bot token and signing secret
const app = new App({
token: "xoxb-",
signingSecret: "",
appToken: "xapp-",
socketMode: true,
port: process.env.PORT || 3000
});
app.message('Hey bot', async ({ message, say }) => {
// say() sends a message to the channel where the event was triggered
await say({
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `You made a request <#${message.user}>?`
}},
{
"type": "divider"
},
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Error Message",
"emoji": true
}
},
{
"type": "input",
"element": {
"type": "plain_text_input",
"multiline": true,
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Description of Error",
"emoji": true
}
},
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Aditional notes?",
"emoji": true
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Submit",
"emoji": true
},
"value": "click_me_123",
"action_id": "button_click"
}
]
}
]
});
});
app.action('button_click', async ({ body, ack, say }) => {
// Acknowledge the action
await ack();
say("No Flagged Issues");
// My HTTP POST REQUEST would go here, IF I HAD ANY!
}
});
(async () => {
// Start your app
await app.start(process.env.PORT || 3000);
console.log('⚡️ Bolt app is running!');
})();
At the end of the day, Bolt apps are just plain old JS apps, so there's nothing particularly special you would need to do to make a HTTP POST from inside your app.action().
There's a bunch of libraries out there, but one of the more popular ones is Axios. After importing it, you'd just have code like this inside your app.action method
axios.get('https://www.nodesource.com/')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
// Using async/await
async function getUser() {
try {
const response = await axios.get('https://www.nodesource.com/');
console.log(response);
} catch (error) {
console.error(error);
}
}
This snippet is by no means idiomatic JS, but it's enough to get you going.

Handle Google API Response

I want to get the comments from a YouTube video and do some further work with them. I started with the implementation example from the docs for "CommentThreads: list" and continued from there on.
Using a main function I want to call the execute function and use the response it should return. It should look kinda like the following:
function execute() {
return gapi.client.youtube.commentThreads.list({
"part": [
"snippet"
],
"fields":[
"items/snippet/topLevelComment/snippet(authorDisplayName,authorProfileImageUrl,publishedAt,textDisplay)"
],
"videoId": "XXXXX"
}).then(function(response) {
console.log(response.result);
},
function(err) {
console.error("Execute error", err);
});
}
function main(){
let response = execute();
console.log(response);
}
And the output in the console looks like this:
{
"Ca": 2,
"yb": null,
"Yj": null,
"Sn": null,
"KB": false,
"xw": false
}
Another way I tried to solve this is to not return gapi.client.youtube.commentThreads.list but the response in the successful promise function like so:
function execute() {
gapi.client.youtube.commentThreads.list({
"part": [
"snippet"
],
"fields":[
"items/snippet/topLevelComment/snippet(authorDisplayName,authorProfileImageUrl,publishedAt,textDisplay)"
],
"videoId": "XXXXX"
}).then(function(response) {
console.log(response.result);
return reponse.result;
},
function(err) {
console.error("Execute error", err);
});
}
But here I only get an undefined.
I am just learning JavaScript and the use of the API.
EDIT:
I should also add that the console.log(response.result); in the execute function does print the information I want. But as soon as I return it and want to use it in the main() function it changes.
The problem seems to that when using the gapi that it returns a promise that I want to return. Promised are not evaluated immediately which means that it continues to execute the following functions, returning a value that has no response yet.
I solved the issue by using the async/await functionality to work with promises, which seemed to be more understandable and elegant in my eyes. I also changed some variables to constants as they did not need to be non-constants. My result looks like the following:
await function execute() {
let response = await gapi.client.youtube.commentThreads.list({
"part": [
"snippet"
],
"fields":[
"items/snippet/topLevelComment/snippet(authorDisplayName,authorProfileImageUrl,publishedAt,textDisplay)"
],
"videoId": "XXXXX"
});
return response.result;
}
async function main(){
let response = await execute();
console.log(response);
}
The reason why we also have to use async and await in the main() function is that by definition async functions always return promises.
To learn more about async/await I found this article whose explanation I liked: https://javascript.info/async-await
They also have an article about promises: https://javascript.info/promise-basics

AWS Lambda Log Output Issue

Hello I am testing out AWS Lambda and I keep getting the boilerplate output in my logs. I am new to AWS and this might be an easy fix but I have not been able to find a solution even in the docs.
Here is my index.js file
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Different OutPut'),
};
return response;
};
And here is the log output in the lambda console:
Response:
{
"statusCode": 200,
"body": "\"Hello from Lambda!\""
}
Request ID:
"dc746181-ec98-4c8a-8e09-c6157da669cb"
I am expecting to have 'Different OutPut' as the body.
Also here are the role permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Thank you for any advice.
If you keep getting Hello from Lambda! then it probably means that you haven't deployed the function before you test/execute it.
You have to explicitly deploy (orange Deploy button) function after each change in the code, so that changes take effect.
The other possibility is that you are executing wrong/old version of your function. In this case you have to explicitly select correct version if you have created any versions of your function.

JavaScript: Azure function blob binding handling exceptions

Hi I have created a azure function httptrigger to read a blob from blob storage with blob input bindings.
below is the function.json:
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"name" : "blobContent",
"type": "blob",
"direction": "in",
"path": "containerName/{id}.{extn}",
"connection": "AzureWebJobsStorage"
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
]
}
and the index.js file is :
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.id || (req.body && req.body.id)) {
context.res = {
body : {'data' : context.bindings.blobContent},
headers : {'Content-type': 'application/xml"'}
}
}
else {
context.res = {
status: 400,
body: "Please pass a object/chuck id on the query string or in the request body"
};
}
context.done(null,context.res);
};
I am using both get and post method to call the httptrigger. Since i am using blob input binding, the content is retrieved before processing index.js. With this, i couldn't validate whether the API called with id and extn. Is there a way to handle the exception and give a message back to the API caller to pass the necessary parameters. Thanks in advance.
So Functions does have some way of doing this, called Function Filters. This feature allows you to write methods that are called before or after the job function is ran (Invocation Filters), or that are invoked whenever the code encounters an exception in the functions runtime (Exception Filters). You could write an exception filter that catches an exception when the input binding fails and that would accomplish what you want.
Unfortunately, at the time of writing this answer, Function Filters are only compatible with pre-compiled C# functions. There is currently this issue tracking this feature's addition into other scenarios.

Error serving HTML files from an Azure function

I am trying to open, read and return an HTML files using Azure functions. I am developing locally and the logs says that the function executed successfully however on the browser I am getting 500 internal server error. Am I doing something wrong in here?
const fs = require('fs');
const path = require('path');
const mime = require('../node_modules/mime-types');
module.exports = function (context, req) {
const staticFilesFolder = 'www/build/';
const defaultPage = 'index.html';
getFile(context, req.query.file);
function getFile(context, file) {
const homeLocation = process.env["HOME"];
if(!file || file == null || file === undefined){
context.done(null,{status:200,body:"<h1>Define a file</h1>",headers:{
"Content-Type":" text/html; charset=utf-8"
}});
}
fs.readFile(path.resolve(path.join(homeLocation, staticFilesFolder, file)),
(err, htmlContent) => {
if (err) {
getFile(context, "404.html");
}
else {
const res = {
status: 200,
body: htmlContent,
headers:{
"Content-Type": mime.lookup(path.join(homeLocation, staticFilesFolder, file))
}
}
context.done(null,res);
}
})
}
};
Note
I am sure that 404.html exists and index.html exists. When I log the contents of htmlContent it is giving the correct output.
functions.json
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"methods":["get"],
"route":"home",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Response on Chrome
If I removed "Content-Length" header the status code changes to 406.
Update 1 The code seems to be running normally on Azure Portal but it is not working when running it locally.
It looks like you are combining two methods of returning data from an http triggered function(context.res and context.done()): https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node#accessing-the-request-and-response
Since you are using context.res, try removing context.done();
You are making an incorrect use of context.res, you shouldn't be overwriting it but instead leveraging the methods provided by the Response class provided in the Azure NodeJS worker. If you are using using VSCode you'll get intellisense for these methods. Otherwise see: https://github.com/Azure/azure-functions-nodejs-worker/blob/dev/src/http/Response.ts
Your code should look something like this instead.
context.res.setHeader('content-type', 'text/html; charset=utf-8')
context.res.raw(htmlContent)
Using context.res.raw or context.res.send will already perform the context.done call for you.
Make sure you use content-type=text/html; charset-utf8 instead of content-type=text/html or you'll trigger an issue with the returned content-type. Instead of returning content-type=text/html you end up getting content-type=text/plain which will fail to render your html.
Addressed on: https://github.com/Azure/azure-webjobs-sdk-script/issues/2053

Categories