Skip to content

assert: add includes api #44029

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

Closed
wants to merge 3 commits into from
Closed

assert: add includes api #44029

wants to merge 3 commits into from

Conversation

zackschuster
Copy link

very simple proxy to StringPrototypeIncludes

inspired by #43784 (comment)

@nodejs-github-bot nodejs-github-bot added assert Issues and PRs related to the assert subsystem. needs-ci PRs that need a full CI run. labels Jul 28, 2022
@zackschuster
Copy link
Author

@aduh95

@cjihrig
Copy link
Contributor

cjihrig commented Jul 28, 2022

very simple proxy to StringPrototypeIncludes

My concern with adding APIs like this is that it is a slippery slope to a more confusing API. Right now this is a wrapper around StringPrototypeIncludes but people are likely to ask for this to support objects, Sets, arrays, etc. See the include() API in chai, @hapi/code, and probably other assertion libraries.

@mscdex
Copy link
Contributor

mscdex commented Jul 28, 2022

I agree it isn't very worthwhile to add a (very specific wrapper) function like this.

@zackschuster
Copy link
Author

zackschuster commented Jul 28, 2022

My concern with adding APIs like this is that it is a slippery slope to a more confusing API. Right now this is a wrapper around StringPrototypeIncludes but people are likely to ask for this to support objects, Sets, arrays, etc. See the include() API in chai, @hapi/code, and probably other assertion libraries.

i think your concern about confusion is valid, but as the desire is for an api that delivers a useful AssertionError, i think we can resolve it with our wordings for the error messages (e.g. by saying things like the <target> (of type <array|string|etc>) does not include <value> – or however it's decided to be worded 😄).

@tniessen
Copy link
Member

I think most users would expect the negation assert.doesNotInclude() to exist as well (based on the existing API). However, ...

My concern with adding APIs like this is that it is a slippery slope to a more confusing API. Right now this is a wrapper around StringPrototypeIncludes but people are likely to ask for this to support objects, Sets, arrays, etc.

It's also a slippery slope to bloating the assert module with many other small functions (e.g., , assert.startsWith(), assert.doesNotStartWith(), assert.endsWith(), assert.doesNotEndWith(), etc.).

i think your concern about confusion is valid, but as the desire is for an api that delivers a useful AssertionError, i think we can resolve it with our wordings for the error messages (e.g. by saying things like the <target> (of type <array|string|etc>) does not include <value> – or however it's decided to be worded 😄).

Unfortunately, adding types to such an API later can be considered a breaking change (see #41007 (comment), for example). In short: if this API is defined to reject non-string inputs, then later allowing non-string inputs weakens the assertion.


assert.match('foo bar baz', /bar/) might not produce pretty error messages and the RegExp might require escaping, but it's versatile.

@zackschuster
Copy link
Author

zackschuster commented Jul 28, 2022

I think most users would expect the negation assert.doesNotInclude() to exist as well (based on the existing API). However, It's also a slippery slope to bloating the assert module with many other small functions (e.g., , assert.startsWith(), assert.doesNotStartWith(), assert.endsWith(), assert.doesNotEndWith(), etc.).

if we end up making includes variadic then i think we actually have a strong argument against such requests, as those new methods don't have the same semantic overlap as includes.

i don't mind adding a negation.

Unfortunately, adding types to such an API later can be considered a breaking change (see #41007 (comment), for example). In short: if this API is defined to reject non-string inputs, then later allowing non-string inputs weakens the assertion.

agreed, it would need to be done now, as part of this pr.

Comment on lines +1455 to +1464
assert.includes('I will fail', 'pass');
// AssertionError [ERR_ASSERTION]: The substring was not located inside the target string.

assert.includes(123, 'pass');
// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string.

assert.includes('I will fail', /pass/);
// AssertionError [ERR_ASSERTION]: The "substring" argument must be of type string.

assert.includes('I will pass', 'pass');
Copy link

Choose a reason for hiding this comment

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

I think, it would be nice to add a valid case with for regexp, like:

assert.includes(/\bpass\b/, 'It will pass');

@zackschuster WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

that's just the assert.match api, but in reverse. i think that would be far more confusing than helpful.

Copy link

@Mifrill Mifrill Jul 29, 2022

Choose a reason for hiding this comment

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

okay, but for me, the word "includes" suitable to regexp matches. Well, with that point of view, it probably better to rename includes into strictIncludes, similar to toEqual and toStrictEqual

Copy link
Contributor

Choose a reason for hiding this comment

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

"strict equality" refers to a real JS thing (https://tc39.es/ecma262/#sec-isstrictlyequal), "strict includes" does not. I don't think we should go with strictIncludes.

the word "includes" suitable to regexp matches

Arguably match is even more suitable.

@aduh95
Copy link
Contributor

aduh95 commented Jul 30, 2022

the RegExp might require escaping

That's the big issue, there is no built-in way to escape regexes. If there was, there would be no need for this specific API (nor doesNotInclude, startsWith, doesNotStartsWith, etc.).

@tniessen
Copy link
Member

the RegExp might require escaping

That's the big issue, there is no built-in way to escape regexes. If there was, there would be no need for this specific API (nor doesNotInclude, startsWith, doesNotStartsWith, etc.).

That is not a Node.js issue (e.g., here is a discussion from 12 years ago), and a TC39 proposal exists to address it.

@aduh95
Copy link
Contributor

aduh95 commented Sep 20, 2023

I think it would be a nice to have, especially since the TC39 proposal seems stalled, but I can see the argument why we wouldn't add it to Node.js to keep our API simpler. Maybe @nodejs/test_runner has some thoughts?
We should probably either close this PR, or fix the linter issue and add the doesNotInclude util.

@aduh95 aduh95 added the stalled Issues and PRs that are stalled. label Sep 20, 2023
@github-actions
Copy link
Contributor

This issue/PR was marked as stalled, it will be automatically closed in 30 days. If it should remain open, please leave a comment explaining why it should remain open.

@ljharb
Copy link
Member

ljharb commented Sep 20, 2023

@aduh95 i have the proposal on the agenda for next week’s plenary; it’s not stalled.

@zackschuster zackschuster closed this by deleting the head repository Nov 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assert Issues and PRs related to the assert subsystem. needs-ci PRs that need a full CI run. stalled Issues and PRs that are stalled.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants