effect icon indicating copy to clipboard operation
effect copied to clipboard

Expecting Error value wrapped in an Exit would not be equal using @effect/vitest

Open steffanek opened this issue 1 year ago • 5 comments

What version of Effect is running?

3.2.3

What steps can reproduce the bug?

import * as it from "@effect/vitest";
it.addEqualityTesters();

import { Schema } from "@effect/schema";
import { Exit } from "effect";

class SchemaTaggedError extends Schema.TaggedError<SchemaTaggedError>()(
  "SchemaTaggedError",
  {
    msg: Schema.String,
    other: Schema.String,
  }
) {}

it.it("test error", () => {
  it.expect(new SchemaTaggedError({ msg: "a", other: "other" })).toEqual(
    new SchemaTaggedError({ msg: "a", other: "other" })
  );
});

it.it("test exit with string value", () => {
  it.expect(Exit.fail("d")).toEqual(Exit.fail("d"));
});

//This pass, however error values are not the same
it.it("test exit with error value", () => {
  it.expect(
    Exit.fail(new SchemaTaggedError({ msg: "a", other: "other" }))
  ).toEqual(Exit.fail(new SchemaTaggedError({ msg: "b", other: "other" })));
});

What is the expected behavior?

The 3rd test should fail.

What do you see instead?

The 3rd test pass.

Additional information

I'm using latest version as follow:

  • vitest 1.6.0
  • @effect/vitest 0.5.3
  • effect 3.2.3

steffanek avatar May 23 '24 06:05 steffanek

Looks like a vitest bug, the following passes (wrongly):

import * as it from "@effect/vitest"

import { Schema } from "@effect/schema"
import { Exit } from "effect"

class SchemaTaggedError extends Schema.TaggedError<SchemaTaggedError>()(
  "SchemaTaggedError",
  {
    msg: Schema.String
  }
) {}

it.it("test exit with error value", () => {
  it.expect(Exit.fail(new SchemaTaggedError({ msg: "a" })))
    .toEqual(Exit.fail(new SchemaTaggedError({ msg: "b" })))
})

And the following fails:

import * as it from "@effect/vitest"

import { Schema } from "@effect/schema"
import { Exit } from "effect"

class SchemaTaggedError extends Schema.TaggedError<SchemaTaggedError>()(
  "SchemaTaggedError",
  {
    message: Schema.String
  }
) {}

it.it("test exit with error value", () => {
  it.expect(Exit.fail(new SchemaTaggedError({ message: "a" })))
    .toEqual(Exit.fail(new SchemaTaggedError({ message: "b" })))
})

The reason seems to be how vitest decides to compare instances of Error, it seems that only the message gets considered

mikearnaldi avatar May 23 '24 16:05 mikearnaldi

Even though something is deeply odd because the following correctly fails:

import * as it from "@effect/vitest"

import { Schema } from "@effect/schema"
import { Exit } from "effect"

class SchemaTaggedError extends Schema.TaggedError<SchemaTaggedError>()(
  "SchemaTaggedError",
  {
    msg: Schema.String
  }
) {
}

it.it("test exit with error value", () => {
  it.expect(new SchemaTaggedError({ msg: "a" }))
    .toEqual(new SchemaTaggedError({ msg: "b" }))
})

cc @sukovanej @tim-smart

mikearnaldi avatar May 23 '24 17:05 mikearnaldi

Thanks @mikearnaldi to check it out this issue. Few month ago, I already reported an issue on vitest repo, and I was using a custom matcher that properly compare Error instances (by not only considering the msg property). Likewise, I asked this morning to the same thread https://github.com/vitest-dev/vitest/issues/5244

steffanek avatar May 23 '24 18:05 steffanek

even adding a custom matcher for errors doesn't work, it looks like it is ignored...

mikearnaldi avatar May 23 '24 18:05 mikearnaldi

even adding a custom matcher for errors doesn't work, it looks like it is ignored...

Yes. Also, there is a recent issue related to the cause prop on Error instances reported on https://github.com/vitest-dev/vitest/issues/5697 not sure it's related.

steffanek avatar May 23 '24 19:05 steffanek

Looks like this was fixed in vitest 3 https://github.com/vitest-dev/vitest/pull/5876

dudeofawesome avatar Mar 20 '25 18:03 dudeofawesome