Getting the right stack trace out of jest - javascript

I am currently debugging some tests written with jest over typescript and I'm having a bit of a headache.
If a test, or tested class, runs Postgres SQL and there is an error in the query, I get the wrong stack trace, for example, this:
error: invalid input syntax for type integer: ""0""
at Parser.parseErrorMessage (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:369:69)
at Parser.handlePacket (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:188:21)
at Parser.parse (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:103:30)
at Socket.<anonymous> (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/index.ts:7:48)
at Socket.emit (node:events:365:28)
at addChunk (node:internal/streams/readable:314:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
The "error" line is very useful, however, the stack trace only tells me that the error was thrown by the pg-protocol driver. I would like to know which line within my code generated the error.
I am exactly 82.7% sure that this is due to PG's query being async.
It is incredibly time-consuming having to step debug or (gasp) console.log my way to each error when it would only be a matter of showing the correct call stack in order to make it better.
Has anyone found a way of making this developer-friendly?

Check if this is related to brianc/node-postgres issue 2484
is (there) a preferred package, extension, or method for providing more detail when you get a syntax error back from the parser?
(for instance, one that listed line number, column of the error)
for instance, right now:
error: syntax error at or near "as"
at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)
desired behavior:
error: syntax error at or near "as", line 5, column 7
at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)
Possible workaround from that issue:
There are a bunch of additional fields on Error objects populated by the driver.
If you log the error object you can see them. They correspond to the error fields returned by the server:
For example with the command:
SELECT foo
FROM bar
You can get an error like this:
{
length: 102,
severity: 'ERROR',
code: '42P01',
detail: undefined,
hint: undefined,
position: '17',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_relation.c',
line: '1180',
routine: 'parserOpenTable'
}
The one you want is position. It gives you the character offset in the SQL of the error.
In this example the position value of "17" refers to the start of the bar token in the SQL.
It's not always populated though as it depends on what caused the error (generally just parse errors).

I ran into a similar issue with aws-sdk for DynamoDb. This is a stacktrace I usually get from aws-sdk.
ResourceNotFoundException: Requested resource not found
at Request.extractError (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\protocol\json.js:52:27)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:688:14)
at Request.transition (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:22:10)
at AcceptorStateMachine.runTo (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:14:12)
at D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:26:10
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:38:9)
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:690:12)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:116:18)
My workaround is simply to catch async errors, and overwrite their stack traces. On the other hand, you may append Postgres stacktrace, or error message to your own errors.
async function getPersonFromDb (personId: string): Promise<DocumentClient.AttributeMap | undefined> {
const result = await documentClient.get({ // Similar to postgres.query()
TableName: 'wrong-name',
Key: { pk: personId, sk: personId }
}).promise().catch(error => {
Error.captureStackTrace(error)
throw error
})
return result.Item
}
test('Get a person from DynamoDB', async () => {
const person = await getPersonFromDb('hello')
expect(person).not.toBeUndefined()
})
// ========= new stacktrace ========
Error: Requested resource not found
at D:\workspaces\typescript-starters\console-app\test\abc.test.ts:12:13
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at getPersonFromDb (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:8:20)
at Object.<anonymous> (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:18:20) // my code, and where my error is thrown

Related

Truffle '"Migrations" -- cb is not a function'

I wrote a simple smart contract in Solidity 0.6.6 that I'm trying to deploy to the BSC Testnet.
This is what I have in my truffle-config.js file (privateKeys is an array with a single entry of ['0x + privatekey']:
networks: {
bscTestnet: {
provider: () => new HDWalletProvider(
privateKeys,
'https://data-seed-prebsc-1-s1.binance.org:8545/'
),
network_id: 97,
skipDryRun: true
}
}
When I run the command "truffle migrate --reset --network bscTestnet" I get the following error:
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: 'bscTestnet'
> Network id: 97
> Block gas limit: 30000000 (0x1c9c380)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
Error: *** Deployment Failed ***
"Migrations" -- cb is not a function.
at /Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:365:1
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Migration._deploy (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:70:1)
at Migration._load (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:56:1)
at Migration.run (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:217:1)
at Object.runMigrations (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:150:1)
at Object.runFrom (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:110:1)
at Object.runAll (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:114:1)
at Object.run (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:79:1)
at runMigrations (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate/run.js:80:1)
at Object.module.exports [as run] (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate/run.js:44:1)
at Command.run (/Users/admin/.nvm/versions/node/v17.4.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/command.js:189:1)
Truffle v5.4.31 (core: 5.4.31)
Node v17.4.0
Opened an Issue a about it: https://github.com/trufflesuite/truffle/issues/4676
I guess its a bug in HardwareWallet2.0.2.
Reverting to HardwareWallet2.0.0 solved the problem for me
npm i #truffle/hdwallet-provider#2.0.0
UPDATE:
Right, workaround: I rolled #HDWalletProvider back to v2.0.1 and was able to migrate.
I assume there must be an issue with the new version for ppl who updated today.
================
Same problem with Polygon Mumbai.
Function "cb" refers to the callback function. The strange part is the error message doesn't reference my own code at all; it references the migrations.js located in:
<.nvm/versions/node/v16.11.1/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:365:1
at processTicksAndRejections (node:internal/process/task_queues:96:5>
This leads me to believe there's a problem with out 1_initial_migration.js... however that's auto-generated so I can't see any problem... it's strange.
1_initial_migration.js:
const Migrations = artifacts.require("Migrations");
module.exports = function(deployer) {
deployer.deploy(Migrations);
};

Ben Awad vid tutorial problemwith npx mikro-orm migration:create

I'm following the tutorial step by step, when I get to the part of run npx mikro-orm migration:create, I get this error
TypeError [ERR_INVALID_ARG_TYPE]: The "key" argument must be of type string or an instance of Buffer, TypedArray, DataView, or KeyObject. Received null
at prepareSecretKey (internal/crypto/keys.js:322:11)
at new Hmac (internal/crypto/hash.js:113:9)
at Object.createHmac (crypto.js:147:10)
at createHMAC (C:\lireddit-server\node_modules\pg\lib\sasl.js:133:17)
at Hi (C:\lireddit-server\node_modules\pg\lib\sasl.js:137:13)
at Object.continueSession (C:\lireddit-server\node_modules\pg\lib\sasl.js:32:24)
at Client._handleAuthSASLContinue (C:\lireddit-server\node_modules\pg\lib\client.js:248:10)
at Connection.emit (events.js:314:20)
at Connection.EventEmitter.emit (domain.js:483:12)
at C:\lireddit-server\node_modules\pg\lib\connection.js:109:12
at Parser.parse (C:\lireddit-server\node_modules\pg-protocol\src\parser.ts:102:9)
at Socket.<anonymous> (C:\lireddit-server\node_modules\pg-protocol\src\index.ts:7:48)
at Socket.emit (events.js:314:20)
at Socket.EventEmitter.emit (domain.js:483:12)
at addChunk (_stream_readable.js:298:12)
at readableAddChunk (_stream_readable.js:273:9)```
I can't find any solution on google, and the tut doesn't point out how to login to postgresql on the app
You are missing some configuration, most probably user or password fields. Here is related issue:
https://github.com/mikro-orm/mikro-orm/issues/866
If you do not provide them, MikroORM will pick the defaults for given driver, which is postgres user and empty password - your postgres installation apparently do not have empty password for this user.
If you are using docker to create the postgres server, this is how you can make it accept empty pws:
postgre:
image: postgres:12.4
ports:
- 5432:5432
environment:
POSTGRES_HOST_AUTH_METHOD: trust <-- here
It seems like you have not specified the password or user property of an object which you are passing inside of MikroORM.init.
This should work
export default {
entities: [Entity],
dbName: "yourDatabaseName",
type: "postgresql",
user: "yourUserName",
password: "yourPassword"
} as Parameters<typeof MikroORM.init>[0];

Uncaught NetworkingError: Cannot read property 'replace' of undefined Error

I'm getting the following error when trying to run the following code. My goal is to delete all items in both the User and Item tables. User and Item correspond to Dynamoose models.
The for loop is running correctly. But the scan().exec callback function isn't being run at all and it's throwing the following error.
What is really strange is on CircleCI this problem doesn't happen. It only happens on my local computer. I have tried removing node_modules and running npm install with no luck. Also it works fine if I remove the code below.
Any ideas? Or even where to start debugging this?
Code:
var dbarray = [User, Item];
for (var i = 0; i < dbarray.length; i++) {
dbarray[i].scan().exec(function(err, items) {
if (err) {
throw err;
}
items.forEach(function(item, key) {
item.delete();
});
});
}
Error:
General
1) "before each" hook
0 passing (10s)
1 failing
1) "before each" hook:
Uncaught NetworkingError: Cannot read property 'replace' of undefined
at findTargetPort (node_modules/zombie/lib/reroute.js:50:28)
at Socket.Net.Socket.connect (node_modules/zombie/lib/reroute.js:69:18)
at Agent.connect [as createConnection] (net.js:106:35)
at Agent.createSocket (_http_agent.js:217:26)
at Agent.addRequest (_http_agent.js:187:10)
at new ClientRequest (_http_client.js:272:16)
at Object.request (http.js:39:10)
at features.constructor.handleRequest (node_modules/aws-sdk/lib/http/node.js:42:23)
at executeSend (node_modules/aws-sdk/lib/event_listeners.js:304:29)
at Request.SEND (node_modules/aws-sdk/lib/event_listeners.js:318:9)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:101:18)
at Request.emit (node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (node_modules/aws-sdk/lib/state_machine.js:14:12)
at node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:115:18)
at callNextListener (node_modules/aws-sdk/lib/sequential_executor.js:95:12)
at node_modules/aws-sdk/lib/event_listeners.js:220:9
at finish (node_modules/aws-sdk/lib/config.js:315:7)
at node_modules/aws-sdk/lib/config.js:333:9
at Credentials.get (node_modules/aws-sdk/lib/credentials.js:126:7)
at getAsyncCredentials (node_modules/aws-sdk/lib/config.js:327:24)
at Config.getCredentials (node_modules/aws-sdk/lib/config.js:347:9)
at Request.SIGN (node_modules/aws-sdk/lib/event_listeners.js:192:22)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:101:18)
at Request.emit (node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (node_modules/aws-sdk/lib/state_machine.js:14:12)
at node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:115:18)
at Timeout.callNextListener [as _onTimeout] (node_modules/aws-sdk/lib/sequential_executor.js:95:12)
The issue turned out to be with Zombie.js. Specially Browser.localhost('localhost', port);. Removing that line and passing in http://localhost:3000 before each visit command solved the problem.
Not sure why the error was mentioning AWS and things like that.

JavaScript ES6 - console.log with template literal

I'm writing node's script that connect to the mongo database.
I noticed that printing error response is different by small change in console.log syntax. Below example should be more meaningful.
#!/usr/bin/env node
const mongoose = require("mongoose");
const config = require("./config");
mongoose.connect(config.dbURI, (err) => {
if (err) {
console.log(`${err}`); // First console.log
console.log(err); // Second console.log
} else {
console.log(`Database connection successful`)
}
});
Example output of the first console.log
MongoError: Authentication failed.
Example output of the second console.log
{ MongoError: Authentication failed.
at Function.MongoError.create (/Users/sigo/Sources/crypto-change/node_modules/mongodb-core/lib/error.js:31:11)
at /Users/sigo/Sources/crypto-change/node_modules/mongodb-core/lib/connection/pool.js:489:72
at authenticateStragglers (/Users/sigo/Sources/crypto-change/node_modules/mongodb-core/lib/connection/pool.js:435:16)
at Connection.messageHandler (/Users/sigo/Sources/crypto-change/node_modules/mongodb-core/lib/connection/pool.js:469:5)
at Socket.<anonymous> (/Users/sigo/Sources/crypto-change/node_modules/mongodb-core/lib/connection/connection.js:321:22)
at emitOne (events.js:96:13)
at Socket.emit (events.js:191:7)
at readableAddChunk (_stream_readable.js:178:18)
at Socket.Readable.push (_stream_readable.js:136:10)
at TCP.onread (net.js:563:20)
name: 'MongoError',
message: 'Authentication failed.',
ok: 0,
code: 18,
errmsg: 'Authentication failed.' }
Where comes from this difference?
${err} (or '' + err for that matter) will interpolate the err object with a string which will also change your Error object into a string - which is equivalent to calling err.toString(). However directly logging err will pass it to the console as an object and display it in that manner.
This is called "implicit coercion" - if you would like to know more about this subject I can highly recommend reading You Don't Know JS: Types & Grammar (Chapter 4: Coercion) for a deep dive.
By interpolating in a template string, the err object is cast to a string, using its own .toString method that is inherited from Error.prototype.toString. The code is equivalent to
console.log(String(err));
console.log(err.toString());
When passing the err object directly to the console.log method, it uses node's inspect function instead, the code is equivalent to
console.log(util.inspect(err));

Using passport-steam with sails-generate-auth

I'm creating a SailsJS application, and I want users to log in only with Steam authentication. I used sails-generate-auth to create some boilerplate code with sails routes, but I'm having trouble plugging passport-steam into it.
https://github.com/kasperisager/sails-generate-auth
https://github.com/liamcurry/passport-steam
The reported error is:
C:\Users\Joe\testProject\node_modules\passport-steam\lib\passport-steam\strategy.js:67
id: result.response.players[0].steamid,
^
TypeError: Cannot read property 'steamid' of undefined
at steamapi.getPlayerSummaries.callback (C:\Users\Joe\testProject\node_modules\passport-steam\lib\passport-steam\strategy.js:67:43)
at IncomingMessage.<anonymous> (C:\Users\Joe\testProject\node_modules\passport-steam\node_modules\steam-web\lib\steam.js:218:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:944:16
at process._tickDomainCallback (node.js:486:13)
I have a feeling that this is caused by SteamWebAPI returning an empty response: {"response":{"players":[]}}, which is caused by a bogus SteamID in the request. The offending line is here in passport-steam: https://github.com/liamcurry/passport-steam/blob/master/lib/passport-steam/strategy.js#L53
Looking at identifier parameter to getUserProfile, it appears to be the entire Sails request scope. If I hardcode a good steam id into that array, I get this error:
C:\Users\Joe\testProject\api\services\passport.js:98
return next(new Error('Neither a username nor email was available'));
^
TypeError: undefined is not a function
at Authenticator.passport.connect (C:\Users\Joe\testProject\api\services\passport.js:98:12)
at module.exports (C:\Users\Joe\testProject\api\services\protocols\openid.js:24:12)
at steamapi.getPlayerSummaries.callback (C:\Users\Joe\testProject\node_modules\passport-steam\lib\passport-steam\strategy.js:72:11)
at IncomingMessage.<anonymous> (C:\Users\Joe\testProject\node_modules\passport-steam\node_modules\steam-web\lib\steam.js:218:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:944:16
at process._tickDomainCallback (node.js:486:13)
I think that makes sense since the steam response doesn't have a username nor email, but this is the profile: {"emails":[{}],"name":{}}
This is my passport configuration:
steam: {
name: 'Steam',
protocol: 'openid',
strategy: require('passport-steam').Strategy,
options: {
returnURL: 'http://localhost:1337/auth/steam/callback',
realm: 'http://localhost:1337/',
apiKey:'STEAM-API-KEY-REMOVED'
}
}
}
Not sure if there is something simple I'm missing, or I need to write a ton of custom handling. Is my configuration correct?
This is caused by out-of-date source code in npm. Even with the latest 0.1.4 version, the code is not correct. Replacing strategy.js in passport-steam with the latest version will fix this error.
Also, in api\services\passport.js, a little custom handling in passport.connect() needs to be added. The profile does not have a username, but has an id (user steamid) and displayName. These can be used to set the user model properties, e.g.
//steam auth
if (profile.hasOwnProperty('displayName')) {
user.username = profile.displayName;
}
Here is the ticket where the problem was solved: https://github.com/liamcurry/passport-steam/issues/10

Categories