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

Deno std_assert lacks a method to validate if a native Error object has the same message attribute as another. #4221

Closed
elvitin opened this issue Jan 18, 2024 · 3 comments
Labels
assert feedback welcome We want community's feedback on this issue or PR

Comments

@elvitin
Copy link

elvitin commented Jan 18, 2024

I find myself in the following scenario: I want to validate if a native Error object returned from any function will have the expected message attribute. I noticed that Jest can validate this, but the native Deno testing library cannot. Here's an example with Jest:

  1. Prepare the project:

    $ mkdir jest-error-assert
    $ cd jest-error-assert
    $ npm init -y
    $ npm i -D jest
  2. Create the index.js file in the root:

    function getError() {
      return new Error("missing param: name");
    }
    
    test('[test1] Should return error object with "missing param: name" message', () => {
      const expectErrObj = new Error("missing param: name");
      expect(getError()).toEqual(expectErrObj);
    });
    
    test('[test2] Should return error object with "missing param: email" message', () => {
      const expectErrObj = new Error("missing param: email");
      expect(getError()).toEqual(expectErrObj);
    });
  3. Run Jest with npx jest:

Okay, notice that [test2] will fail because the Error object returned from the function does not have the expected message: missing param: email. Just modify getError to pass the test.


Now let's look at an example with Deno's standard assert:

  1. Prepare the project:

    $ mkdir deno-error-assert
    $ cd deno-error-assert
    $ deno init
  2. Remove everything from main.ts and main_test.ts, then add:

    // main.ts
    export function getError() {
      return new Error("missing param: name");
    }
    // main_test.ts
    import {
      assertEquals,
      equal,
    } from "https://deno.land/std@0.204.0/assert/mod.ts";
    import { getError } from "./main.ts";
    
    Deno.test(
      '[test1] Should return error object with "missing param: name" message',
      () => {
        const expectErrObj = new Error("missing param: name");
        assertEquals(getError(), expectErrObj);
      },
    );
    
    Deno.test(
      '[test2] Should return error object with "missing param: email" message',
      () => {
        const expectErrObj = new Error("missing param: email");
        equal(getError(), expectErrObj);
        assertEquals(getError(), expectErrObj);
    
        const anotherExpectErrObj = new Error("any message");
        equal(getError(), anotherExpectErrObj);
        assertEquals(getError(), anotherExpectErrObj);
      },
    );
  3. Run the test with deno test:

See that all tests pass, and there is no equivalent method in the std assert as in Jest to validate this case. Can someone explain why this happens?


My environment:

$ deno --version
deno 1.39.4 (release, x86_64-unknown-linux-gnu)
v8 12.0.267.8
typescript 5.3.3

my os:

$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
@elvitin elvitin added bug Something isn't working needs triage labels Jan 18, 2024
@kt3k
Copy link
Member

kt3k commented Jan 18, 2024

Looks like jest's internal eq utility has a special handling when the given values are both Errors. https://github.com/jestjs/jest/blob/8c78a08c6e75c1a0c4447aa8a0c61ad9e395e16f/packages/expect-utils/src/jasmineUtils.ts#L86-L88

On the other hand, assertEquals of deno_std/assert doesn't have it. Should we do the same as jest?

BTW std/assert has assertIsError utility which can be used for checking error message.

@kt3k kt3k added assert feedback welcome We want community's feedback on this issue or PR and removed bug Something isn't working needs triage labels Jan 18, 2024
@elvitin
Copy link
Author

elvitin commented Jan 18, 2024

Okay, so I can use assertIsError() as an alternative:

// main_test.ts
import {
  assertEquals,
  assertIsError,
  equal,
} from "https://deno.land/std@0.212.0/assert/mod.ts";
import { getError } from "./main.ts";

//...
Deno.test(
  '[test2] Should return error object with "missing param: email" message',
  () => {
    const expectErrObj = new Error("missing param: email");
    equal(getError(), expectErrObj);
    assertEquals(getError(), expectErrObj);

    // const anotherExpectErrObj = new Error('any message');
    // equal(getError(), anotherExpectErrObj); // doesn't throw an exception
    // assertEquals(getError(), anotherExpectErrObj); // doesn't throw an exception
    assertIsError(getError(), Error, "any message"); // throws an exception
  },
);

Now the exception is triggered by the assertIsError() call, nice!

But I wonder if assertEquals() shouldn't be agnostic to any type of object? Since assertEquals() compares whether objects are exactly identical. I believe assertEquals() shouldn't care whether the object in question is of type Error or not.

And if assertEquals() doesn't compare objects of type Error or, in other words, there are exceptions for some types of objects, this should be explicitly stated in the documentation.

@kt3k
Copy link
Member

kt3k commented Jan 19, 2024

I believe assertEquals() shouldn't care whether the object in question is of type Error or not.

assertEquals doesn't handle Errors in a special way. .message property of Error object is not enumerable (you can check that with Object.getOwnPropertyDescriptors(new Error)), and assertEquals doesn't compare properties of enumerable=false. That's why assertEquals doesn't throw for errors with different messages.

Jest does the similar about non enumerable properties, but they have special handling specific to Error objects

And if assertEquals() doesn't compare objects of type Error or, in other words, there are exceptions for some types of objects, this should be explicitly stated in the documentation.

Probably we need to document handling of non-enumerable properties..?

Another way to solve this confusion might be adding the same special handling for Errors like Jest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assert feedback welcome We want community's feedback on this issue or PR
Projects
None yet
Development

No branches or pull requests

2 participants