-
Notifications
You must be signed in to change notification settings - Fork 19
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
Proxy revoked error when performing chai deep equality #37
Comments
hi @Rubilmax, the deep attributes contain some special objects that are not finalized draft in Unless you are certain that all sources are generally finalizable draft instances, it is not recommended to directly use For example, class Foobar {
bar = 1;
}
const foobar = new Foobar();
const state = create(
foobar,
(draft) => {
draft.bar = 2;
},
{ mark: () => 'immutable' }
);
const foobar2 = new Foobar();
foobar2.bar = 2;
expect(state).toEqual(foobar2); Could you provide a minimal reproducible example? |
How can I make sure of that? i am working on a minimal reproducible example |
Alright so here's the minimal reproducible case I could find: https://github.com/Rubilmax/mutative-jest It is actually using I defined some classes: export class Entity {
constructor(public readonly name: string) {}
}
export class Group {
constructor(
public readonly id: string,
public readonly children: Entity[],
) {}
public clone() {
return new Group(this.id, this.children);
}
}
export class Data {
constructor(public readonly groupData: Record<string, Group>) {}
} And a failing test: import { makeCreator } from "mutative";
import { Data, Entity, Group } from "../src/Data";
const create = makeCreator({
mark: () => "immutable",
});
const entity1 = new Entity("entity1");
const entity2 = new Entity("entity2");
const data = new Data({
id1: new Group("id1", []),
id2: new Group("id2", [entity1]),
id3: new Group("id3", [entity1, entity2]),
});
describe("Data", () => {
it("should not fail", () => {
expect(
create(data, (draft) => {
draft.groupData["id1"] = draft.groupData["id1"]!.clone();
}),
).toEqual({});
});
}); which throws the following error: The test does not throw this error as soon as we remove the |
@Rubilmax , Although you used the public clone() {
return new Group(this.id, this.children);
}
create(data, (draft) => {
draft.groupData['id1'] = unsafe(() => draft.groupData['id1']!.clone());
}) |
I noticed that the data structure in the example is a non-unidirectional tree, but you used Unless you explicitly ensure that the entire object tree is in a strictly immutable mode, it may produce unintended behaviors. We should use the mark function to distinguish between immutable and mutable nodes. const nextData = create(data, (draft) => {
expect(current(draft.groupData['id2'].children[0])).toBe(
current(draft.groupData['id3'].children[0])
);
expect(draft.groupData['id2'].children[0].name).toBe('entity1');
expect(draft.groupData['id3'].children[0].name).toBe('entity1');
draft.groupData['id2'].children[0].name = 'new-entity';
expect(draft.groupData['id2'].children[0].name).toBe('new-entity');
// !!! it's unexpected
expect(draft.groupData['id3'].children[0].name).toBe('entity1');
}); |
Indeed, and I didn't know how to handle these. Unfortunately, using
That is correct and it purely was for the example but clearly not necessary. In my real-life example it is not the case; and I fully understand the possible unexpected outcomes due to this, thanks! |
I tried this and it doesn't throw anymore but the test doesn't pass: import { makeCreator, unsafe } from "mutative";
import { Data, Entity, Group } from "../src/Data";
const create = makeCreator({
mark: (value) => {
if (value instanceof Group) return "mutable";
return "immutable";
},
});
const entity1 = new Entity("entity1");
const entity2 = new Entity("entity2");
const data = new Data({
id1: new Group("id1", []),
id2: new Group("id2", [entity1]),
id3: new Group("id3", [entity2]),
});
describe("Data", () => {
it("should not fail", () => {
expect(
create(
data,
(draft) => {
draft.groupData["id1"] = unsafe(() => draft.groupData["id1"]!.clone());
},
{ strict: true },
),
).toEqual(
new Data({
id1: new Group("id1", []),
id2: new Group("id2", [new Entity("entity1_cloned")]),
id3: new Group("id3", [new Entity("entity2_cloned")]),
}),
);
});
}); I'm sorry this may sound easy for you but I don't fully understand the expected usage of |
Sorry, the docs for the These test cases should work fine. import { makeCreator, unsafe } from 'mutative';
export class Entity {
constructor(public readonly name: string) {}
}
export class Group {
constructor(public readonly id: string, public readonly children: Entity[]) {}
public clone() {
return new Group(this.id, this.children);
}
}
export class Data {
constructor(public readonly groupData: Record<string, Group>) {}
}
const create = makeCreator({
mark: (value) => {
if (value instanceof Group) return 'mutable';
return 'immutable';
},
});
const entity1 = new Entity('entity1');
const entity2 = new Entity('entity2');
const data = new Data({
id1: new Group('id1', []),
id2: new Group('id2', [entity1]),
id3: new Group('id3', [entity2]),
});
describe('Data', () => {
it('should not fail', () => {
expect(
create(
data,
(draft) => {
draft.groupData['id1'] = unsafe(() =>
draft.groupData['id1']!.clone()
);
},
{ strict: true }
)
).toEqual(
new Data({
id1: new Group('id1', []),
id2: new Group('id2', [new Entity('entity1')]),
id3: new Group('id3', [new Entity('entity2')]),
})
);
});
}); |
Although the custom Thank you very much for reporting this issue. |
@Rubilmax Mutative v1.0.5 has been released. Feel free to use it. |
Amazing!! Saw you implemented this issue's example as a test. Will check this out asap. Thanks for your reactivity |
This comment was marked as spam.
This comment was marked as spam.
You need to execute their clones. draft.groupData['id2'] = draft.groupData['id2']!.clone();
draft.groupData['id3'] = draft.groupData['id3']!.clone(); |
This is ridiculous lmao I'm so sorry, thanks again for your reactivity. It's all sorted out |
Using
create
to apply a reducer on some Class instance marked asimmutable
and then comparing the result data to some expected class instance with chai's deep equality util throws a Proxy revoked error:Do you know why?
The text was updated successfully, but these errors were encountered: