DEV Community

Kinga
Kinga

Posted on

jest.SpyOn @pnp/sp select() and filter()

It's a "Note to self" but maybe someone will find it useful.

Building on top of State of SPFx unit testing in 2023 I'd like to make sure that the select and filter methods are invoked correctly from my function.

The code

I have a ListDataProvider class which provides a GetListItemsBy method. Depending on the parameters provided I will call eiter this.spfiContext.web.lists.getByTitle(listTitle).items.select(...viewFields).filter(filterBy)<T>( or return await this.spfiContext.web.lists.getByTitle(listTitle).items.select(...viewFields)<T>();

ListDataProvider.ts

export type IListSelect={
    listTitle: string; viewFields: string[];
}
export type IListFilter = IListSelect & {
    filterByField: string; filterByVal: string[]; filterBySyntax?: string;
}
export default class ListDataProvider {
    constructor(protected spfiContext: SPFI) { }
    public async GetListItemsBy<T>(p: IListSelect | IListFilter): Promise<T>    {

        const { listTitle, viewFields } = p as IListSelect;
        const { filterByField, filterByVal, filterBySyntax } = p as IListFilter;

        if (filterBySyntax !== undefined || filterByField !== undefined ) {
            const filterBy = filterBySyntax
                ? `${this.getFilterBy(filterByField, filterByVal)} or ${this.getFilterByContains(filterByField, filterByVal, filterBySyntax)}`
                : this.getFilterBy(filterByField, filterByVal);
            return await this.spfiContext.web.lists.getByTitle(listTitle).items.select(...viewFields).filter(filterBy)<T>();
        }
        else{
            return await this.spfiContext.web.lists.getByTitle(listTitle).items.select(...viewFields)<T>();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The test

To test the ListDataProvider I will mock the SPFI with select [and filter]:

ListDataProvider.test.ts

it("should call correct method when calling GetListItemsBy with no filter")

Calling this.spfiContext.web.lists.getByTitle("TestList").items.select("Title")()

    it("should call correct method when calling GetListItemsBy with no filter", async () => {

        mockSPFI = {
            web: {
                lists: {
                    getByTitle: jest.fn().mockReturnValue({
                        items: {
                            select: () => (() => ({ Title: "test" }))
                        }
                    })
                }
            }
        } as unknown as SPFI;

        jest.spyOn(mockSPFI.web.lists.getByTitle("TestList").items, "select");

        const provider = new ListDataProvider(mockSPFI);
        const results: Record<string, string> = await provider.GetListItemsBy({
            listTitle: "TestList",
            viewFields: ["Title"],
        })

        expect(results["Title"]).toBe("test");
        expect(mockSPFI.web.lists.getByTitle).toBeCalledWith("TestList");
        expect(mockSPFI.web.lists.getByTitle("TestList").items.select).toBeCalledWith("Title")
    });
Enter fullscreen mode Exit fullscreen mode

it("should call correct method when calling GetListItemsBy with filter")

Calling this.spfiContext.web.lists.getByTitle("TestList").items.select("Title").filter("Title eq 'test'")()

    it("should call correct method when calling GetListItemsBy with filter", async () => {

        mockSPFI = {
            web: {
                lists: {
                    getByTitle: jest.fn().mockReturnValue({
                        items: {
                            select: jest.fn().mockReturnValue({
                                filter: () => (() => ({ Title: "test" }))
                            })
                        }
                    })
                }
            }
        } as unknown as SPFI;

        jest.spyOn(mockSPFI.web.lists.getByTitle("TestList").items, "select");
        jest.spyOn(mockSPFI.web.lists.getByTitle("TestList").items.select("Title"), "filter")

        const provider = new ListDataProvider(mockSPFI);
        const results: Record<string, string> = await provider.GetListItemsBy({
            listTitle: "TestList",
            viewFields: ["Title"],
            filterByField: "Title",
            filterByVal: ["test"]
        })

        expect(results["Title"]).toBe("test");
        expect(mockSPFI.web.lists.getByTitle).toBeCalledWith("TestList");
        expect(mockSPFI.web.lists.getByTitle("TestList").items.select).toBeCalledWith("Title")
        expect(mockSPFI.web.lists.getByTitle("TestList").items.select("").filter).toBeCalledWith("Title eq 'test'")
    });
Enter fullscreen mode Exit fullscreen mode

it("should call correct method when calling GetListItemsBy with filter and filterBySyntax")

Calling this.spfiContext.web.lists.getByTitle("TestList").items.select("Title").filter("ID eq '1506' or substringof('-1506-',ID)")()

    it("should call correct method when calling GetListItemsBy with filter and filterBySyntax", async () => {

        mockSPFI = {
            web: {
                lists: {
                    getByTitle: jest.fn().mockReturnValue({
                        items: {
                            select: jest.fn().mockReturnValue({
                                filter: () => (() => ({ Title: "test" }))
                            })
                        }
                    })
                }
            }
        } as unknown as SPFI;

        jest.spyOn(mockSPFI.web.lists.getByTitle("TestList").items, "select");
        jest.spyOn(mockSPFI.web.lists.getByTitle("TestList").items.select("Title"), "filter")

        const provider = new ListDataProvider(mockSPFI);
        const results: Record<string, string> = await provider.GetListItemsBy({
            listTitle: "TestList",
            viewFields: ["Title"],
            filterByField: "ID",
            filterByVal: ["1506"],
            filterBySyntax: "-value-"
        })

        expect(results["Title"]).toBe("test");
        expect(mockSPFI.web.lists.getByTitle).toBeCalledWith("TestList");
        expect(mockSPFI.web.lists.getByTitle("TestList").items.select).toBeCalledWith("Title")
        expect(mockSPFI.web.lists.getByTitle("TestList").items.select("").filter).toBeCalledWith("ID eq '1506' or substringof('-1506-',ID)")
    });
Enter fullscreen mode Exit fullscreen mode

Top comments (0)