yozibak
yozibak

Reputation: 149

How to assert arg is included in specific array? (jest toHaveBeenCalledWith)

I've been struggling to find a way to do something like this:

// module

const m = {
  doSomething: (id: string) => {}
}

type Item = { id: string }

const randomInt = (min: number, max: number) => {
  return Math.floor(Math.random() * (max - min + 1) + min)
}
const fn = (items:Item[]) => {
  const toBeUsed = items[randomInt(0, items.length - 1)]
  m.doSomething(toBeUsed.id)
}

// test

describe("fn", () => {
  
  it("should pick one of items as arg", () => {
    // arrange
    const items:Item[] = [{ id: 'r1'}, { id: 'r2'}, { id: 'r3'}] 
    const doSomething = jest.spyOn(m, 'doSomething')

    // act
    fn(items)

    // assert
    expect(doSomething).toHaveBeenCalledWith(
      // Here, check if arg is one of items.map( i => i.id ) ...?
    )
  })
})

I've looked jest docs' expect section but it seems to me that I cannot check if string is in a specific array (expect.arrayContaining doesn't satisfy this scenario). Any workaround for this?

Upvotes: 0

Views: 334

Answers (1)

Ovidijus Parsiunas
Ovidijus Parsiunas

Reputation: 2732

You will first need to create a utility function which can search for the item inside an items array:

function isItemInTheItemsArray(itemsArr: Item[], targetItem: Item): boolean {
  return Boolean(itemsArr.find((item) => item.id === targetItem.id))
}

Instead of using toHaveBeenCalledWith, you can extract the argument that the doSomething mock was called with using .mock.calls[0][0] (where [0] is the first call and the second [0] is the first argument of that call):

const itemArg = doSomething.mock.calls[0][0];

Finally, you can use the result itemArg variable inside the utility function to verify if it is inside the list and assert it using the .toBeTruthy matcher:

expect(isItemInTheItemsArray(items, itemArg)).toBeTruthy();

Upvotes: 1

Related Questions