Skip to content

Flawed DeviceList.spec.ts does not wait for async call and assertions #2977

@MadLittleMods

Description

@MadLittleMods

Found while working on #2973 with the jest/valid-expect-in-promise lint


The following test in DeviceList.spec.ts does not wait for the dl.saveIfDirty() async call and assertions

it("should have an outdated devicelist on an invalidation while an " + "update is in progress", function () {
const dl = createTestDeviceList();
dl.startTrackingDeviceList("@test1:sw1v.org");
const queryDefer1 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValue(queryDefer1.promise);
const prom1 = dl.refreshOutdatedDeviceLists();
expect(downloadSpy).toHaveBeenCalledWith(["@test1:sw1v.org"], {});
downloadSpy.mockReset();
// outdated notif arrives while the request is in flight.
const queryDefer2 = utils.defer();
downloadSpy.mockReturnValue(queryDefer2.promise);
dl.invalidateUserDeviceList("@test1:sw1v.org");
dl.refreshOutdatedDeviceLists();
dl.saveIfDirty()
.then(() => {
// the first request completes
queryDefer1.resolve({
failures: {},
device_keys: {
"@test1:sw1v.org": {},
},
});
return prom1;
})
.then(() => {
// uh-oh; user restarts before second request completes. The new instance
// should know we never got a complete device list.
logger.log("Creating new devicelist to simulate app reload");
downloadSpy.mockReset();
const dl2 = createTestDeviceList();
const queryDefer3 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValue(queryDefer3.promise);
const prom3 = dl2.refreshOutdatedDeviceLists();
expect(downloadSpy).toHaveBeenCalledWith(["@test1:sw1v.org"], {});
dl2.stop();
queryDefer3.resolve(utils.deepCopy(signedDeviceList));
// allow promise chain to complete
return prom3;
})
.then(() => {
const storedKeys = dl.getRawStoredDevicesForUser("@test1:sw1v.org");
expect(Object.keys(storedKeys)).toEqual(["HGKAWHRVJQ"]);
dl.stop();
});
});

If you try to fix the issue by waiting for the async calls, the test no longer passes which means the test was failing before but we are not catching it.

async/await conversion
it("should have an outdated devicelist on an invalidation while an " + "update is in progress", async () => {
        const dl = createTestDeviceList();

        dl.startTrackingDeviceList("@test1:sw1v.org");

        const queryDefer1 = utils.defer<IDownloadKeyResult>();
        downloadSpy.mockReturnValue(queryDefer1.promise);

        const prom1 = dl.refreshOutdatedDeviceLists();
        expect(downloadSpy).toHaveBeenCalledWith(["@test1:sw1v.org"], {});
        downloadSpy.mockReset();

        // outdated notif arrives while the request is in flight.
        const queryDefer2 = utils.defer();
        downloadSpy.mockReturnValue(queryDefer2.promise);

        dl.invalidateUserDeviceList("@test1:sw1v.org");
        dl.refreshOutdatedDeviceLists();

        await dl.saveIfDirty();

        // the first request completes
        queryDefer1.resolve({
            failures: {},
            device_keys: {
                "@test1:sw1v.org": {},
            },
        });
        await prom1;

        // uh-oh; user restarts before second request completes. The new instance
        // should know we never got a complete device list.
        logger.log("Creating new devicelist to simulate app reload");
        downloadSpy.mockReset();
        const dl2 = createTestDeviceList();
        const queryDefer3 = utils.defer<IDownloadKeyResult>();
        downloadSpy.mockReturnValue(queryDefer3.promise);

        const prom3 = dl2.refreshOutdatedDeviceLists();
        expect(downloadSpy).toHaveBeenCalledWith(["@test1:sw1v.org"], {});
        dl2.stop();

        queryDefer3.resolve(utils.deepCopy(signedDeviceList));

        // allow promise chain to complete
        await prom3;

        const storedKeys = dl.getRawStoredDevicesForUser("@test1:sw1v.org");
        expect(Object.keys(storedKeys)).toEqual(["HGKAWHRVJQ"]);
        dl.stop();
    });

Metadata

Metadata

Assignees

Labels

A-TestingTesting, code coverage, etc.T-TaskTasks for the team like planning

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions