Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_runner: fix escaping in snapshot tests #53833

Merged

Conversation

JulianKniephoff
Copy link
Contributor

Snapshotted values are escaped after serialization. This happens when serializing a value for comparison when snapshots already exist, and also when updating them. That is, snapshots are escaped in the internal storage, but when written to disk, one "level" of escaping is removed. That escaping is never added back when reading the snapshots back. This makes even the simplest test trying to serialize a string with an escape code in it fail, like the one I added here.

Honestly I'm not quite sure about the approach here: An alternative would be to not escape snapshots internally, and only do so when writing them to disk/interpolating them into the appropriate JS-code. I haven't fully thought this through, though, and there is also a test explicitly ensuring that serialize escapes values, so there might be a good reason for it.

Another thing I'm not sure about is whether the test I added is sufficient, because it feels kind of indirect. Let me know if you want to see that changed.

@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 Jul 13, 2024
@@ -147,6 +147,9 @@ class SnapshotManager {
}

this.snapshots = context.exports;
for (const [key, value] of Object.entries(this.snapshots)) {
Copy link
Member

@RedYetiDev RedYetiDev Jul 13, 2024

Choose a reason for hiding this comment

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

I believe this should be replaced with a primordial implementation, see https://github.com/nodejs/node/blob/main/doc/contributing/primordials.md ?

Copy link
Contributor

Choose a reason for hiding this comment

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

This will look something like this:

// Add to the imports at the top of the file.
const {
  ObjectEntries,
} = primordials;

const entries = ObjectEntries(context.exports);

for (let i = 0; i < entries.length; i++) {
  const { 0: key, 1: value } = entries[i];
  this.snapshots[key] = templateEscape(value);
}

(Let's also update to operator on context.exports before assigning to this.snapshots.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Out of curiosity: Can you explain why this shouldn't use array destructuring and for-of?

Also, what about something like this, which looks a bit more natural to me, and also avoids these, and even the need for the primordial:

for (const key in context.exports) {
  this.snapshots[key] = templateEscape(context.exports[key]);
}

🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe for-in loops are allowed, so that should be fine.

Can you explain why this shouldn't use array destructuring and for-of?

The idea is that user code can change the way those things work and potentially break the test runner. There is an explanation of both of those in https://github.com/nodejs/node/blob/main/doc/contributing/primordials.md#implicit-use-of-user-mutable-methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh sorry, I overlooked that section. 😅 Alright, thanks, I will make the change, then! 😀

Copy link
Contributor

@cjihrig cjihrig left a comment

Choose a reason for hiding this comment

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

Thanks for this. I think it looks good. Just a couple minor comments.

@@ -147,6 +147,9 @@ class SnapshotManager {
}

this.snapshots = context.exports;
for (const [key, value] of Object.entries(this.snapshots)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will look something like this:

// Add to the imports at the top of the file.
const {
  ObjectEntries,
} = primordials;

const entries = ObjectEntries(context.exports);

for (let i = 0; i < entries.length; i++) {
  const { 0: key, 1: value } = entries[i];
  this.snapshots[key] = templateEscape(value);
}

(Let's also update to operator on context.exports before assigning to this.snapshots.

@@ -22,3 +22,7 @@ test('`${foo}`', async (t) => {
const options = { serializers: [() => { return '***'; }]};
t.assert.snapshot('snapshotted string', options);
});

test('escapes', async (t) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add some more escape characters that are also used by templateEscape().

@@ -22,3 +22,7 @@ test('`${foo}`', async (t) => {
const options = { serializers: [() => { return '***'; }]};
t.assert.snapshot('snapshotted string', options);
});

test('escapes', async (t) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be good to add a test where the test name includes the problematic escape characters since that is serialized as the snapshot ID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The test before mine does that, doesn't it? I could combine these, of course, but that one sets a custom serializer, so I didn't want to tamper with it. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, please don't change the existing tests. It would be good to have coverage without custom serializers, and they are pretty cheap to add.

Snapshotted values are escaped after serialization.
This happens when serializing a value for comparison
when snapshots already exist, and also when updating them.
That is, snapshots are escaped in the internal storage,
but when written to disk, one "level" of escaping is removed.
That escaping is never added back when reading the snapshots back.
This makes even the simplest test trying to serialize a string
with an escape code in it fail, like the one I added here.
@JulianKniephoff
Copy link
Contributor Author

I fixed the missing semicolon (sorry about that 🙈), but I have no idea what to do about the failing test-linux job. 🤔

@cjihrig cjihrig added the request-ci Add this label to start a Jenkins CI on a PR. label Jul 14, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jul 14, 2024
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Jul 14, 2024

@cjihrig cjihrig added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. and removed needs-ci PRs that need a full CI run. labels Jul 14, 2024
@MoLow MoLow added the commit-queue Add this label to land a pull request using GitHub Actions. label Jul 15, 2024
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Jul 15, 2024
@nodejs-github-bot nodejs-github-bot merged commit 4b4a931 into nodejs:main Jul 15, 2024
58 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 4b4a931

aduh95 pushed a commit that referenced this pull request Jul 16, 2024
Snapshotted values are escaped after serialization.
This happens when serializing a value for comparison
when snapshots already exist, and also when updating them.
That is, snapshots are escaped in the internal storage,
but when written to disk, one "level" of escaping is removed.
That escaping is never added back when reading the snapshots back.
This makes even the simplest test trying to serialize a string
with an escape code in it fail, like the one I added here.

PR-URL: #53833
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: James M Snell <jasnell@gmail.com>
aduh95 pushed a commit that referenced this pull request Jul 16, 2024
Snapshotted values are escaped after serialization.
This happens when serializing a value for comparison
when snapshots already exist, and also when updating them.
That is, snapshots are escaped in the internal storage,
but when written to disk, one "level" of escaping is removed.
That escaping is never added back when reading the snapshots back.
This makes even the simplest test trying to serialize a string
with an escape code in it fail, like the one I added here.

PR-URL: #53833
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: James M Snell <jasnell@gmail.com>
@aduh95 aduh95 mentioned this pull request Jul 16, 2024
ehsankhfr pushed a commit to ehsankhfr/node that referenced this pull request Jul 18, 2024
Snapshotted values are escaped after serialization.
This happens when serializing a value for comparison
when snapshots already exist, and also when updating them.
That is, snapshots are escaped in the internal storage,
but when written to disk, one "level" of escaping is removed.
That escaping is never added back when reading the snapshots back.
This makes even the simplest test trying to serialize a string
with an escape code in it fail, like the one I added here.

PR-URL: nodejs#53833
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: James M Snell <jasnell@gmail.com>
@targos targos added the dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. label Sep 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants