Unraveling the Perfect Jest Stack Trace

Currently, I am in the process of debugging some tests that were written with jest using typescript and it's causing quite a headache.

Whenever a test or tested class runs Postgres SQL and encounters an error in the query, the stack trace provided is not helpful. For example, you might see something like 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 line mentioning the "error" is useful, but the stack trace only indicates that the error originated from the pg-protocol driver. It would be more beneficial to pinpoint exactly which part of my code caused the error.

I have a strong feeling, around 82.7%, that this issue stems from PG's query being asynchronous.

Debugging by stepping through or resorting to console.log every error is incredibly time-consuming when simply showing the correct call stack could provide a much clearer picture.

Has anyone discovered a developer-friendly solution to this problem?

Answer №1

Verify if this pertains to the issue 2484 in the brianc/node-postgres repository.

Is there a recommended package, extension, or method for providing detailed information when encountering a syntax error from the parser?
For example, one that includes the line number and column of the error.

Currently:

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 outcome:

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)

Potential solution provided in that issue:

There are multiple additional fields on Error objects populated by the driver.
By logging the error object, you can view them. They correspond to the error fields returned by the server:

For instance, with the query:

SELECT foo
FROM bar

You may encounter 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 critical field is position. It provides the character offset in the SQL of the error.
In this case, the position value of "17" corresponds to the beginning of the bar token in the SQL.
However, it may not always be filled depending on the cause of the error (typically limited to parse errors).

Answer №2

Encountered a similar issue while working with the aws-sdk for DynamoDb. Here is the typical stacktrace generated by 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)

To handle this issue, I implemented a workaround to catch async errors and modify their stack traces. Additionally, you can integrate Postgres stacktraces or error messages into 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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing custom form fields with JavaScript in Symfony2

Here is my form field template: {% block test_question_widget %} {% spaceless %} <div {{ block('widget_container_attributes') }}> {% set type = type|default('hidden') %} <input type="{{ typ ...

how to use jquery to indicate that a checkbox is selected

click here to see the image $(document).ready(function() { $('.editbtn').on('click', function(){ $('#editmodal').modal('show'); $tr=$(this).closest('tr'); var da ...

Bringing in a variable from a component that is dynamically imported

I have a dynamically imported (Map) component on my page. const Map = dynamic(() => import('../components/Mapcomp'), { ssr: false, }) In addition to the component, I also need to import a variable from it. const [taskImg, setTaskImg] = useS ...

What could be causing the getTotals() method to malfunction?

I have been working on a finance app that is designed to update the "income", "expenses", and "balance" tables at the top each time a new item is added by the user. However, the current code seems to be failing in updating these values correctly based on u ...

Unique Text: "Personalized marker/pin for interactive map feature"

Looking to create a custom image map marker/pin with a unique bottom design resembling a union shape using CSS and Vue.js. I've attempted it myself but haven't been able to achieve the exact look as shown in the reference image. Any advice or ass ...

Expand the HTTP Response interface with Typescript

Recently, I've been working on a piece of code that involves the axios library. Here's what I have so far: const BTrustURLResponse: Response = await axios.get(`${process.env.BTRUST_URL}/flow/${process.env.BTRUST_FLOWID}/link?callback_url=${callba ...

Error encountered while attempting to load SWC binary for win32/ia32 in a Next JS application

Upon installing a Next.js app using the command npx create-next-app@latest, I encountered an error while running the app. Can anyone explain why this error occurred and provide a solution? PS D:\New folder\my-app> npm run dev [email pr ...

What causes Vue to only update once when there are two closely timed mutations to reactive data?

Can you take a look at this simple example? export default { data() { return { name: "Amy", age: 18, }; }, computed: { combinedDataForWatching() { return { name: this.name, age: this.age, ...

Why is my jQuery $.ajax success function not providing any results?

When checking the Network tab in Chrome, I noticed that the correct data (action, username, password) is being sent, but the message is not returning to $('#return_login'). Can anyone spot what might be wrong with my code? Below is the jQuery co ...

Arrange two arrays by organizing them based on the contents of one in JavaScript

Consider the following two arrays: priceArray= [1, 5, 3, 7] userIdArray=[11, 52, 41, 5] The goal is to sort the priceArray in such a way that the userIdArray also gets sorted accordingly. The desired output should look like this: priceArray= [1, 3, 5, ...

Tips on optimizing a setTimeout script for seamless integration with an HTML form

Here is the script: <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> function addToCart() { document.getElementById("msgs-box").innerHTML = "Item added to cart s ...

Preserving Scroll Location Through Back Button Usage and Ajax Manipulation of the Document Object Model

Currently, I am incorporating a feature where results are loaded in using ajax with an infinite scroll. However, there is an issue when a user clicks on an item in the list and navigates away from the page - upon returning by clicking the back button, they ...

Determining the character encoding of a JavaScript source code file

For my German users, I want to display a status message with umlauts (ä/ü/ö) directly in the source file instead of requiring an extra download for messages. However, I'm having trouble defining the encoding for a JS source file. Is there a way si ...

Discover the ins and outs of the "DOM" within a string, treating it as HTML in AngularJS

Looking to extract data from a legal HTML string based on tags and attributes, but want to avoid using jQuery in favor of Angular. Are there built-in functions in Angular for this task? ...

Why am I receiving an undefined value when I try to log the createdAnimal?

My main goal with this code is to successfully console.log(createdAnimal) and have the objectAnimal with specific parameters printed out. The following code snippet demonstrates the desired parameters: animalMaker('cat','flying',true); ...

What is the reasoning behind having two separate permission dialog boxes for accessing the webcam and microphone in flash?

I am currently using a JavaScript plugin known as cameratag () in order to record videos through the web browser. This plugin utilizes a flash-based solution. When the flash application requests permission to access the webcam, it presents a security dialo ...

What is the best way to incorporate audio playback while browsing files on an HTML5 webpage with TypeScript?

<input type="file" id="soundUrl" (change)="onAudioPlay()" /> <audio id="sound" controls></audio> This is the HTML code I'm working with, and I'm looking to trigger audio playback after a user selects an MP3 file using TypeScrip ...

Error encountered: JSHint is flagging issues with setting a background gradient using

I have been experimenting with animating a background gradient using jQuery, and here is the code snippet I am working with: this.$next.css('line-indent', 0).animate({ 'line-indent': 100 }, { "duration": 750, "step": functi ...

The module 'react' is not found in the directory '/react/node_modules/react-redux/lib/components'

Issue: Module react not found at path /home/react/node_modules/react-redux/lib/components While utilizing cypress for unit testing components, the tests are encountering the error mentioned above despite 'react' being present in the dependencies ...

Using JQuery to reveal a hidden child element within a parent element

I'm facing a challenge with displaying nested ul lists on my website. The parent ul is hidden with CSS, causing the child ul to also remain hidden even when I try to display it using jQuery. One approach I've attempted is adding a class to the f ...