supertest failing with ECONNRESET - javascript

I'm working on a Node.js project and trying to write test cases for the app.
The endpoints are working perfectly fine when I run them in Postman. But when I run the test cases, some of them, (Usually the first one in the order) fails with the error
- Error: read ECONNRESET
I have tried debugging it, searched for a potential solution, but I'm unable to fix it. I'm working with jasmine/supertest for the first time. Maybe I'm missing something I'm unable to anticipate but I haven't been able to find out the issue.
Can anybody help me out with this? Thanks a bunch in advance.
Here is my test code.
it('Gets Users List', async() => {
const response = await request.get('/users')
expect(response.status).toBe(200);
})
and my Controller function
export const index = async (req:Request, res: Response) => {
try {
const users : DataObject = await model.index()
res.status(users.status);
res.json(users.data);
} catch (error) {
res.status(NOT_FOUND);
res.json(error);
}
}
The peculiar behavior that I observed is when I add another method before this one, then this method works fine and the first one returns the same error.
I assume the first call is rejected due to the fact that connection was not established yet? I'm not sure though.
Anybody familiar with this issue?
Thanks in advance.

Related

How locate the row where the output statement resides in nodejs

As we all know, we can easy to see the line of an output statement in the browser, just like follow picture
enter image description here
but in the nodejs env, how do I know what line is 'output statement' in.
I have this need because I want to know better during development where the information is coming from when the program fails. Of course, I could have each output statement carry a unique character, like console.log('1', '...'), console.log('2', '...') but that feels silly and unhackable to me.
I'll show you a simple piece of code as an illustration
try {
throw new Error('something error')
} catch (error) {
console.log(error.stack)
}
Run the above code I can see the output:
Error: something error
at file:///c:/Users/Linhieng/Desktop/tmp/a.js:2:9
at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
the above output tell us what line is the error in, but I want to know the line of console.log.
You can monkeypatch console.log with code that parses the stack string, since this is Node.js and the format only varies across releases (unlike on browsers, where it can vary by browser as well):
const realLog = console.log;
console.log = (...msgs) => {
try {
throw new Error("something error");
} catch (error) {
const lines = error.stack.split(/(?:\r\n|\r|\n)+/);
msgs.push(`[${lines[2].trim()}]`);
}
realLog(...msgs);
};
Then for instance, this:
function example() {
console.log("Hi there");
}
example();
shows
Hi there [at example (file:///____/temp.js:13:13)]
At present, the "parsing" is really easy — just split on newlines and take the third element of the array. But you might want to extract more information, or the format could change in future versions to require more complicated "parsing."
I thing woth simple logging the only solution here is a manually passing the according line number. Something like that:
console.log(error, LINE_NUMBER);
Another possible solution probably could be when you use some kind of a external configurable NodeJS debugger software. There probably will be provided a functionality related you your needs.

Handling errors and recoverying with node pg (postgres) client

I am using node module pg in my application and I want to make sure it can properly handle connection and query errors.
The first problem I have is I want to make sure it can properly recover when postgres is unavailable.
I found there is an error event so I can detect if there is a connection error.
import pg from 'pg'
let pgClient = null
async function postgresConnect() {
pgClient = new pg.Client(process.env.CONNECTION_STRING)
pgClient.connect()
pgClient.on('error', async (e) => {
console.log('Reconnecting')
await sleep(5000)
await postgresConnect()
})
}
I don't like using a global here, and I want to set the sleep delay to do an small exponential backoff. I noticed "Reconnecting" fires twice immediately, then waits five seconds and I am not sure why it fired the first time without any waiting.
I also have to make sure the queries execute. I have something like this I was trying out.
async function getTimestamp() {
try {
const res = await pgClient.query(
'select current_timestamp from current_timestamp;'
)
return res.rows[0].current_timestamp
} catch (error) {
console.log('Retrying Query')
await sleep(1000)
return getTimestamp()
}
}
This seems to work, but I haven't tested it enough to make sure it will guarantee the query is executed or keep trying. I should look for specific errors and only loop forever on certain errors and fail on others. I need to do more research to find what errors are thrown. I also need to do a backoff on the delay here too.
It all "seems" to work, I don't want to fail victim to the Dunning-Kruger effect. I need to ensure this process can handle all sorts of situations and recover.

Typescript promises causes code to silently crash

I'm trying to use the async/await syntax to resolve a promise in typescript. I have experience in javascript, so I assume it is very similar, but I can't get around this bug. I am trying to use await on an asynchronous function, but the code will not continue running if I do it. For example, I have this code:
const strategies = await Strategy.getActiveStrategies();
In my Strategy model, I have this code segment (implemented using Mongoose):
public static async getActiveStrategies(filter = {}): Promise<Strategy[]> {
return StrategyModel.find(filter).then(result => {
// note, the the .then doesn't matter; I can't even console.log(result) except
// in my test cases.
return result.map(internalModel => {
let strategy = new Strategy();
strategy.setInternalModel(internalModel);
return strategy;
});
});
}
No matter how I change the syntax, it will not work. I can change the .then(...) to async/await, and it will stop running at the 'await' line. I can change the first code block to strategy.getActiveStrategies.then(activeStrategies => {...}), and it still does not run any code in the 'then' function. I've even tried doing:
const strategy = Strategy.getActiveStrategies();
console.log(strategy) // prints: Promise { <pending> }
await strategy // does not continue running after this line.
I've tried everything I can think of and nothing seems to work. What's even more weird is that the code passes all of my test cases (I did test-driven development). For example, one part of my test cases is:
const found = await Strategy.getAllStrategies();
expect(found.length).toEqual(2);
And everything works as you would expect. I have multiple test cases that work. But, when I try to call the function in the main app, it just does not work.
What am I doing wrong? I've worked with MongoDB, mongoose, and JavaScript on previous projects, and I feel like what I'm trying to do is pretty simple. I'm lost on how to continue; I've looked on StackOverflow and other online resources, and I can't find anybody who has a similar problem as me. Any help would be appreciated, and please let me know if you need any more details. Thank you.

How to run and read bluetoothctl commands outputs from NodeJS?

I want to periodically run commands to bluetoothctl via NodeJS, and be able to read the output of those commands.
For example I'd want to run the scan on, and get the output. As well as running devices and read the list. It's not matter that is a string, I can parse it, but I need to be able to interact with the bluetoothctl program.
The problem is that when you type in the terminal the command bluetoothctl it brings you in a "manager" like view, where I guess Node cannot read data from? Am I wrong?
I'm kinda lost, and I couldn't find anything useful. I've found some NodeJS bluetoothctl wrappers, but they're all old and requires deprecated versions of node..
Edit
Here's the code that I have so far. But the problem is that I don't get the expected output from the commands that I run, but instead I get the name of the command that I've called...
import * as cp from 'child_process';
async function sleep(ms) {
await new Promise(r => setTimeout(() => r(), ms));
return;
}
function log(m: string) {
console.log(`[${ShellyBluetoothScanner.name}] ${m}`);
}
export class ShellyBluetoothScanner {
bluetoothctl: cp.ChildProcessWithoutNullStreams;
constructor() {
this.setup();
}
async run() {
log('Running scan and devices list in 2s...');
await sleep(2000);
log('Enabling bluetooth');
this.bluetoothctl.stdin.write('power on');
await sleep(2000);
log('Claering devices');
this.bluetoothctl.stdin.write('remove *');
log('Scan devices for 3s');
this.bluetoothctl.stdin.write('scan on');
await sleep(3000);
log('Print devices');
this.bluetoothctl.stdin.write('devices');
}
private setup() {
log('INFO: Setting up bluetooth');
this.bluetoothctl = cp.spawn('bluetoothctl');
this.bluetoothctl.stdout.on('data', m => console.log('STDOUT Data - ', m.toString()));
this.bluetoothctl.stdout.on('error', error => console.log('STDOUT Error - ', error.message));
log('INFO: Bluetooth setup completed');
}
}
const SBTS = new ShellyBluetoothScanner();
SBTS.run();
I don't believe bluetoothctl was ever intended to be run in this way. It certainly has no documented API and I have seen the commands subtly change in the tool over time which will break your script.
A better way to achieve this is to use the D-Bus API that is documented and intended for this use.
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt
There are bindings available at: https://www.npmjs.com/package/dbus
I am sure there are also libraries that maybe helpful. Maybe https://www.npmjs.com/package/node-ble

Correct way to use async function inside a for-loop

Recently, I got some error when running the E2E tests and the only change I made is adding the checkColumns logic in the original test code as following:
it('check search and sort', async () => {
await checkLoadingAndResult();
await checkColumns(table, ...columns); //newly added
await checkTableSorting();
});
The logic of checkColumns is like:
export async function checkColumns(table: Table, ...columns: string[]) {
for (const col of columns) {
expect(await table.isColumnDisplayed(col)).toBeTruthy(`${col} is not displayed`)
}
}
The error message is like:
Error: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:59536
I think maybe there's something wrong in the checkColumns function and I don't know whether it's a correct way to call async methods inside a for-loop. And I guess this for-loop is the cause of the error.
This error message is not generated by your usage of async / await.
It is most likely displayed because the HTTP request sent failed due to a connection error, I had the issue on another framework and it was due to the webdriver that was not running.

Categories