I've having a strange problem with this test:
import Deal from "../src/models/Deal"; import apiProducts from "../__mocks__/api/products"; describe("Deal", () => { describe("Deal.fromApi", () => { it("takes an api product and returns a Deal", () => { const apiDeal = apiProducts[0]; const newDeal = Deal.fromApi(apiDeal); const expected = expectedDeal(); expect(newDeal).toEqual(expected); }); }); });
export default class Deal { // no constructor since we only ever create a deal from Deal.fromApi static fromApi(obj: Object): Deal { const deal = new Deal(); deal.id = obj.id; deal.name = obj.name; deal.slug = obj.slug; deal.permalink = obj.permalink; deal.dateCreated = obj.date_created; deal.dateModified = obj.date_modified; deal.status = obj.status; deal.featured = obj.featured; deal.catalogVisibility = obj.catalog_visibility; deal.descriptionHTML = obj.description; deal.shortDescriptionHTML = obj.short_description; deal.price = Number(obj.price); deal.regularPrice = Number(obj.regular_price); deal.salePrice = Number(obj.sale_price); deal.dateOnSaleFrom = obj.date_on_sale_from; deal.dateOnSaleTo = obj.date_on_sale_to; deal.onSale = obj.on_sale; deal.purchasable = obj.purchasable; deal.relatedIds = obj.related_ids; deal.upsellIds = obj.upsell_ids; deal.crossSellIds = obj.cross_sell_ids; deal.categories = obj.categories; deal.tags = obj.tags; deal.images = obj.images; return deal; } descriptionWithTextSize(size: number): string { return this.descriptionWithStyle(`font-size:${size}`); } descriptionWithStyle(style: string): string { return `<div style="${style}">${this.description}</div>`; } distanceFromLocation = ( location: Location, unit: unitOfDistance = "mi" ): number => { return distanceBetween(this.location, location); }; distanceFrom = (otherDeal: Deal, unit: unitOfDistance = "mi"): number => { return distanceBetween(this.location, otherDeal.location); }; static toApi(deal: Deal): Object { return { ...deal }; } }
The test fails with this error:
● Deal › Deal.fromApi › takes an api product and returns a Deal expect(received).toEqual(expected) // deep equality Expected: {"catalogVisibility": "visible", "categories": [{"id": 15, "name": "New York", "slug": "new-york"}], "crossSellIds": [34, 31], "dateCreated": "2019-05-18T17:36:14", "dateModified": "2019-05-18T17:39:02", "dateOnSaleFrom": null, "dateOnSaleTo": null, "descriptionHTML": "<p>Pete's Tavern<br /> 129 E 18th St<br /> New York, NY 10003</p> <p>Weekdays from 4 p.m. to 7 p.m.<br /> $5 wines and beers</p> ", "distanceFromLocation": [Function anonymous], "featured": false, "id": 566, "images": [{"alt": "", "date_created": "2019-05-18T17:38:52", "date_created_gmt": "2019-05-18T17:38:52", "date_modified": "2019-05-18T17:38:52", "date_modified_gmt": "2019-05-18T17:38:52", "id": 567, "name": "wine and beers2", "src": "https://tragodeals.com/wp-content/uploads/2019/05/wine-and-beers2.jpg"}], "name": "Wines and beers", "onSale": true, "permalink": "https://tragodeals.com/product/wines-and-beers/", "price": 5, "purchasable": true, "regularPrice": 11, "relatedIds": [552, 564, 390, 37, 543], "salePrice": 5, "shortDescriptionHTML": "<p>$5 wines and beers</p> ", "slug": "wines-and-beers", "status": "publish", "tags": [{"id": 58, "name": "beers", "slug": "beers"}, {"id": 54, "name": "Cocktails", "slug": "cocktails"}, {"id": 45, "name": "drink", "slug": "drink"}, {"id": 57, "name": "wine", "slug": "wine"}], "upsellIds": [53]} Received: serializes to the same string > 15 | expect(newDeal).toEqual(expected); | ^ 16 | }); 17 | }); 18 | }); at Object.toEqual (__tests__/deal.test.js:15:23)
I inserted this loop to investigate:
for (let key in expected) { expect(expected[key]).toEqual(newDeal[key]); }
And I see that the problem is with functions. So I changed the whole test to this:
for (let key in expected) { if (typeof expected[key] === "function") continue; expect(expected[key]).toEqual(newDeal[key]); } // expect(newDeal).toEqual(expected);
And it passes, and also fails when it should. (if you read the old version of this question where I was getting passing tests that I didn't understand, it was because I was return
ing from the loop when I should have been continue
ing).
But I'd like to be able to do it with the standard assertion expect(newDeal).toEqual(expected)
. It looks like there's something I'm not understanding about checking for class object (Deal
) equality with functions.
PS. You might suggest using toMatchObject
. But, sadly:
● Deal › Deal.fromApi › takes an api product and returns a Deal expect(received).toMatchObject(expected) - Expected + Received @@ -1,6 +1,6 @@ - Deal { + Object { "address": "129 E 18th St New York, NY 10003", "catalogVisibility": "visible", "categories": Array [ Object { "id": 15, 13 | expect(expected[key]).toEqual(newDeal[key]); 14 | } > 15 | expect(newDeal).toMatchObject(expected); | ^ 16 | }); 17 | }); 18 | });
Similarly to other colleagues I had this issue with an Array comparison, I was basically testing a function that got the largest string in an array, additionally it should return an array if more than 1 of those strings matched the largest length possible.
When I started testing I got the following message:
So I replaced the toBe
method
expect(function(array1)).toBe('one result')
with toStrictEqual
to make a deep equality comparison
expect(function(array2)).toStrictEqual(['more than one', 'more than one']);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With