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

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay