Skip to content

Conversation

pmarchini
Copy link
Member

@pmarchini pmarchini commented Aug 13, 2025

This is a draft implementation related to this issue: #59231.

I'm opening this PR mainly to collect some feedback regarding this feature and potential implementations, solutions, or ideas!

Note: The proposed solution is working, but it still needs refinement.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Aug 13, 2025
@pmarchini pmarchini force-pushed the issue/59231-toMatchInlineSnapshot branch from bd403c8 to 475eca6 Compare August 13, 2025 21:46
added: REPLACEME
-->

> Stability: 1.0 - Early development

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs rock!

});
```

When first run without the `--test-update-snapshots` flag, the test will fail

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, the ideal DX is to always assume a missing second parameter "wants to be updated" whether or not the --test-update-snapshots flag is passed. You can then get a really nice micro workflow on a given test without ever needing to pass the flag just by repeatedly deleting the param (in my IDE, I often delete the parameter just by hitting undo: ctrl-z, save, test / update, ctrl-z, save, test / update, ... until I get the shape I want).

const user = { name: 'Alice', age: 30 };

// Initially call without second argument
t.assert.inlineSnapshot(user);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great name! I think this aligns really well to the current TestContext.assert.snapshot() API. Also, I'm pleasantly surprised I don't need to await here.

test('inline snapshot test', (t) => {
const user = { name: 'Alice', age: 30 };

t.assert.inlineSnapshot(user, `
Copy link

@niedzielski niedzielski Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be really helpful if inlineSnapshot() supported wrapping. For example:

/**
 * Asserts bitmap is the expected hex value. The `expectedHex` arg is replaced
 * automatically when tests are run with `--test-update-snapshots`.
 */
function assertBitmapHex(ctx: TestContext, bmp: Uint8Array, expectedHex: string): string {
  const actualHex = [...bmp]
    .map(v => v.toString(16).padStart(2, '0'))
    .join('')
  ctx.assert.inlineSnapshot(actualHex, expectedHex) // <-- don't update me inline here!
}
test('', () => {
  // ...
  assertBitmapHex(bmp, '000000000000000000000000') // <-- I get updated inline here since I'm called at the top level test function.
})

It's possible to not use wrapping but then it gets pretty clumsy trying to fill out all the args in every test.

@JakobJingleheimer
Copy link
Member

What if we merely augment the current t.assert.snapshot to accept a second argument?

t.assert.snapshot({ name: 'Alice', age: 30 }, `{ name: 'Alice', age: 30 }`)

And then to generate updates --test-update-snapshots=inline (where the default value is external or something).

@niedzielski
Copy link

accept a second argument

I believe TestContext.assert.snapshot() already accepts a second argument. Also, since you wouldn't pass a second argument initially, there wouldn't be a way to distinguish from a file call? I realize you're proposing a flag to account for that but a project may have many inline and external snapshot tests both so the distinction must be encoded at each call site.

@pmarchini
Copy link
Member Author

What if we merely augment the current t.assert.snapshot to accept a second argument?

t.assert.snapshot({ name: 'Alice', age: 30 }, `{ name: 'Alice', age: 30 }`)

And then to generate updates --test-update-snapshots=inline (where the default value is external or something).

@JakobJingleheimer, IMHO I think we should decouple the two methods, as Jest does, for two reasons:

  1. we can de‑risk what’s already in place
  2. using a different method makes usage clearer and keeps it consistent with what’s already present in the ecosystem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants