Conform more code to strict null checking (#10169)

* Conform more code to strict null checking

* delint

* Iterate

* delint

* Fix bad test
This commit is contained in:
Michael Telatynski 2023-02-16 09:38:44 +00:00 committed by GitHub
parent 5123d7e641
commit e8b92b308b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 283 additions and 287 deletions

View file

@ -57,7 +57,7 @@ describe("PosthogAnalytics", () => {
digest: async (_: AlgorithmIdentifier, encodedMessage: BufferSource) => {
const message = new TextDecoder().decode(encodedMessage);
const hexHash = shaHashes[message];
const bytes = [];
const bytes: number[] = [];
for (let c = 0; c < hexHash.length; c += 2) {
bytes.push(parseInt(hexHash.slice(c, c + 2), 16));
}
@ -68,6 +68,7 @@ describe("PosthogAnalytics", () => {
});
afterEach(() => {
// @ts-ignore
window.crypto = null;
SdkConfig.unset(); // we touch the config, so clean up
});
@ -116,7 +117,7 @@ describe("PosthogAnalytics", () => {
foo: "bar",
});
expect(mocked(fakePosthog).capture.mock.calls[0][0]).toBe("JestTestEvents");
expect(mocked(fakePosthog).capture.mock.calls[0][1]["foo"]).toEqual("bar");
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["foo"]).toEqual("bar");
});
it("Should not track events if anonymous", async () => {
@ -209,7 +210,7 @@ describe("PosthogAnalytics", () => {
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toStrictEqual({
WebLayout: "IRC",
});
});
@ -226,7 +227,7 @@ describe("PosthogAnalytics", () => {
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toStrictEqual({
WebLayout: "Bubble",
});
});
@ -243,7 +244,7 @@ describe("PosthogAnalytics", () => {
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toStrictEqual({
WebLayout: "Group",
});
});
@ -261,7 +262,7 @@ describe("PosthogAnalytics", () => {
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toStrictEqual({
WebLayout: "Compact",
});
});

View file

@ -53,7 +53,7 @@ describe("ScalarAuthClient", function () {
client.getOpenIdToken = jest.fn().mockResolvedValue(tokenObject);
sac.exchangeForScalarToken = jest.fn((arg) => {
if (arg === tokenObject) return Promise.resolve("wokentoken");
return Promise.resolve(arg === tokenObject ? "wokentoken" : "othertoken");
});
await sac.connect();

View file

@ -223,7 +223,7 @@ describe("SlashCommands", () => {
const command = getCommand("/part #foo:bar");
expect(command.cmd).toBeDefined();
expect(command.args).toBeDefined();
await command.cmd!.run("room-id", null, command.args);
await command.cmd!.run("room-id", null, command.args!);
expect(client.leaveRoomChain).toHaveBeenCalledWith("room-id", expect.anything());
});
});
@ -232,7 +232,7 @@ describe("SlashCommands", () => {
const command = findCommand(commandName)!;
it("should return usage if no args", () => {
expect(command.run(roomId, null).error).toBe(command.getUsage());
expect(command.run(roomId, null, undefined).error).toBe(command.getUsage());
});
it("should make things rainbowy", () => {

View file

@ -58,7 +58,7 @@ describe("SlidingSyncManager", () => {
event_id: "$abc123",
sender: client.getUserId()!,
content: {
creator: client.getUserId(),
creator: client.getUserId()!,
},
}),
]);

View file

@ -125,7 +125,7 @@ describe("VoiceMessageRecording", () => {
const encryptedFile = {} as unknown as IEncryptedFile;
beforeEach(() => {
voiceRecording.onDataAvailable(testBuf);
voiceRecording.onDataAvailable!(testBuf);
});
it("contentLength should return the buffer length", () => {
@ -143,9 +143,9 @@ describe("VoiceMessageRecording", () => {
});
describe("upload", () => {
let uploadFileClient: MatrixClient;
let uploadFileRoomId: string;
let uploadBlob: Blob;
let uploadFileClient: MatrixClient | null;
let uploadFileRoomId: string | null;
let uploadBlob: Blob | null;
beforeEach(() => {
uploadFileClient = null;
@ -182,8 +182,8 @@ describe("VoiceMessageRecording", () => {
expect(mocked(uploadFile)).toHaveBeenCalled();
expect(uploadFileClient).toBe(client);
expect(uploadFileRoomId).toBe(roomId);
expect(uploadBlob.type).toBe(contentType);
const blobArray = await uploadBlob.arrayBuffer();
expect(uploadBlob?.type).toBe(contentType);
const blobArray = await uploadBlob!.arrayBuffer();
expect(new Uint8Array(blobArray)).toEqual(testBuf);
});

View file

@ -79,7 +79,7 @@ describe("RoomView", () => {
stores.client = cli;
stores.rightPanelStore.useUnitTestClient(cli);
jest.spyOn(VoipUserMapper.sharedInstance(), "getVirtualRoomForRoom").mockResolvedValue(null);
jest.spyOn(VoipUserMapper.sharedInstance(), "getVirtualRoomForRoom").mockResolvedValue(undefined);
});
afterEach(async () => {
@ -175,7 +175,7 @@ describe("RoomView", () => {
instance = await getRoomViewInstance();
oldRoom = new Room("!old:example.com", cli, cli.getSafeUserId());
rooms.set(oldRoom.roomId, oldRoom);
jest.spyOn(room, "findPredecessor").mockReturnValue({ roomId: oldRoom.roomId, eventId: null });
jest.spyOn(room, "findPredecessor").mockReturnValue({ roomId: oldRoom.roomId });
});
it("and it has 0 unreads, getHiddenHighlightCount should return 0", async () => {

View file

@ -181,7 +181,7 @@ describe("Login", function () {
const { container, rerender } = render(getRawComponent());
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
fireEvent.click(container.querySelector(".mx_SSOButton"));
fireEvent.click(container.querySelector(".mx_SSOButton")!);
expect(platform.startSingleSignOn.mock.calls[0][0].baseUrl).toBe("https://matrix.org");
fetchMock.get("https://server2/_matrix/client/versions", {
@ -190,7 +190,7 @@ describe("Login", function () {
});
rerender(getRawComponent("https://server2"));
fireEvent.click(container.querySelector(".mx_SSOButton"));
fireEvent.click(container.querySelector(".mx_SSOButton")!);
expect(platform.startSingleSignOn.mock.calls[1][0].baseUrl).toBe("https://server2");
});

View file

@ -118,7 +118,7 @@ describe("Registration", function () {
const { container, rerender } = render(getRawComponent());
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
fireEvent.click(container.querySelector(".mx_SSOButton"));
fireEvent.click(container.querySelector(".mx_SSOButton")!);
expect(registerRequest.mock.instances[0].baseUrl).toBe("https://matrix.org");
fetchMock.get("https://server2/_matrix/client/versions", {
@ -128,7 +128,7 @@ describe("Registration", function () {
rerender(getRawComponent("https://server2"));
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
fireEvent.click(container.querySelector(".mx_SSOButton"));
fireEvent.click(container.querySelector(".mx_SSOButton")!);
expect(registerRequest.mock.instances[1].baseUrl).toBe("https://server2");
});
});

View file

@ -84,7 +84,7 @@ describe("<BeaconListItem />", () => {
const member = new RoomMember(roomId, aliceId);
member.name = `Alice`;
const room = mockClient.getRoom(roomId);
const room = mockClient.getRoom(roomId)!;
jest.spyOn(room, "getMember").mockReturnValue(member);
return beacons;
@ -185,7 +185,7 @@ describe("<BeaconListItem />", () => {
const { container } = getComponent({ beacon, onClick });
// click the beacon name
fireEvent.click(container.querySelector(".mx_BeaconStatus_description"));
fireEvent.click(container.querySelector(".mx_BeaconStatus_description")!);
expect(onClick).toHaveBeenCalled();
});
});

View file

@ -47,7 +47,7 @@ describe("<ShareLatestLocation />", () => {
const { container, asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot();
fireEvent.click(container.querySelector(".mx_CopyableText_copyButton"));
fireEvent.click(container.querySelector(".mx_CopyableText_copyButton")!);
await flushPromises();
expect(copyPlaintext).toHaveBeenCalledWith("51,42");

View file

@ -575,7 +575,7 @@ function createMenu(
return mount(
<RoomContext.Provider value={context as IRoomState}>
<MessageContextMenu chevronFace={null} mxEvent={mxEvent} onFinished={jest.fn()} {...props} />
<MessageContextMenu mxEvent={mxEvent} onFinished={jest.fn()} {...props} />
</RoomContext.Provider>,
);
}

View file

@ -32,7 +32,6 @@ describe("AccessSecretStorageDialog", () => {
const defaultProps: ComponentProps<typeof AccessSecretStorageDialog> = {
onFinished: jest.fn(),
checkPrivateKey: jest.fn(),
keyInfo: undefined,
};
const renderComponent = (props = {}): void => {

View file

@ -66,11 +66,11 @@ describe("EventListSummary", function () {
}
const generateMembershipEvent = (
eventId: string,
{ senderId, userId, membership, prevMembership }: MembershipEventParams,
{ senderId, userId, membership, prevMembership }: MembershipEventParams & { userId: string },
): MatrixEvent => {
const member = new RoomMember(roomId, userId);
// Use localpart as display name;
member.name = userId.match(/@([^:]*):/)[1];
member.name = userId.match(/@([^:]*):/)![1];
jest.spyOn(member, "getAvatarUrl").mockReturnValue("avatar.jpeg");
jest.spyOn(member, "getMxcAvatarUrl").mockReturnValue("mxc://avatar.url/image.png");
const e = mkMembership({
@ -89,8 +89,8 @@ describe("EventListSummary", function () {
};
// Generate mock MatrixEvents from the array of parameters
const generateEvents = (parameters: MembershipEventParams[]) => {
const res = [];
const generateEvents = (parameters: Array<MembershipEventParams & { userId: string }>) => {
const res: MatrixEvent[] = [];
for (let i = 0; i < parameters.length; i++) {
res.push(generateMembershipEvent(`event${i}`, parameters[i]));
}
@ -108,7 +108,9 @@ describe("EventListSummary", function () {
events.forEach((e) => {
e.userId = userId;
});
eventsForUsers = eventsForUsers.concat(generateEvents(events));
eventsForUsers = eventsForUsers.concat(
generateEvents(events as Array<MembershipEventParams & { userId: string }>),
);
}
return eventsForUsers;
};

View file

@ -29,7 +29,10 @@ describe("<LearnMore />", () => {
};
const getComponent = (props = {}) => <LearnMore {...defaultProps} {...props} />;
const modalSpy = jest.spyOn(Modal, "createDialog").mockReturnValue(undefined);
const modalSpy = jest.spyOn(Modal, "createDialog").mockReturnValue({
finished: new Promise(() => {}),
close: jest.fn(),
});
beforeEach(() => {
jest.clearAllMocks();

View file

@ -36,7 +36,7 @@ describe("<TooltipTarget />", () => {
// clean up renderer tooltips
const wrapper = document.querySelector(".mx_Tooltip_wrapper");
while (wrapper?.firstChild) {
wrapper.removeChild(wrapper.lastChild);
wrapper.removeChild(wrapper.lastChild!);
}
});

View file

@ -50,10 +50,10 @@ describe("MKeyVerificationConclusion", () => {
}) => {
class MockVerificationRequest extends EventEmitter {
constructor(
public readonly pending: boolean,
public readonly cancelled: boolean,
public readonly done: boolean,
public readonly otherUserId: string,
public readonly pending?: boolean,
public readonly cancelled?: boolean,
public readonly done?: boolean,
public readonly otherUserId?: string,
) {
super();
}

View file

@ -140,7 +140,9 @@ describe("MLocationBody", () => {
});
it("opens map dialog on click", () => {
const modalSpy = jest.spyOn(Modal, "createDialog").mockReturnValue(undefined);
const modalSpy = jest
.spyOn(Modal, "createDialog")
.mockReturnValue({ finished: new Promise(() => {}), close: jest.fn() });
const component = getComponent();
act(() => {

View file

@ -63,7 +63,7 @@ describe("MessageEvent", () => {
event = mkEvent({
event: true,
type: VoiceBroadcastInfoEventType,
user: client.getUserId(),
user: client.getUserId()!,
room: room.roomId,
content: {
state: VoiceBroadcastInfoState.Started,

View file

@ -108,7 +108,7 @@ describe("<PinnedMessagesCard />", () => {
const room = pins.props().room;
const pinListener = mocked(room.currentState).on.mock.calls.find(
([eventName, listener]) => eventName === RoomStateEvent.Events,
)[1];
)![1];
await act(async () => {
// Emit the update

View file

@ -37,7 +37,7 @@ function generateRoomId() {
describe("MemberList", () => {
function createRoom(opts = {}) {
const room = new Room(generateRoomId(), null, client.getUserId());
const room = new Room(generateRoomId(), client, client.getUserId()!);
if (opts) {
Object.assign(room, opts);
}

View file

@ -370,7 +370,7 @@ describe("MessageComposer", () => {
replyToEvent = mkEvent({
event: true,
type: EventType.RoomMessage,
user: cli.getUserId(),
user: cli.getUserId()!,
content: {},
});

View file

@ -377,7 +377,7 @@ describe("RoomHeader (React Testing Library)", () => {
content,
});
room.addLiveEvents([event]);
return { event_id: event.getId() };
return { event_id: event.getId()! };
});
alice = mkRoomMember(room.roomId, "@alice:example.org");

View file

@ -21,7 +21,7 @@ import { Key } from "../../../../src/Keyboard";
import { mockPlatformPeg, unmockPlatformPeg } from "../../../test-utils/platform";
import { KeyboardKey, KeyboardShortcut } from "../../../../src/components/views/settings/KeyboardShortcut";
const renderKeyboardShortcut = (Component: React.FunctionComponentFactory<any>, props: Record<string, any>) => {
const renderKeyboardShortcut = (Component: React.FunctionComponent<any>, props: Record<string, any>) => {
return render(<Component {...props} />).container;
};

View file

@ -30,7 +30,6 @@ describe("<DeviceDetails />", () => {
};
const defaultProps: ComponentProps<typeof DeviceDetails> = {
device: baseDevice,
pusher: null,
isSigningOut: false,
onSignOutDevice: jest.fn(),
saveDeviceName: jest.fn(),

View file

@ -53,7 +53,7 @@ describe("<SelectableDeviceTile />", () => {
const { container } = render(getComponent({ onSelect }));
act(() => {
fireEvent.click(container.querySelector(`#device-tile-checkbox-${device.device_id}`));
fireEvent.click(container.querySelector(`#device-tile-checkbox-${device.device_id}`)!);
});
expect(onSelect).toHaveBeenCalled();

View file

@ -92,7 +92,7 @@ describe("deleteDevices()", () => {
// opened modal
expect(modalSpy).toHaveBeenCalled();
const [, { title, authData, aestheticsForStagePhases }] = modalSpy.mock.calls[0];
const { title, authData, aestheticsForStagePhases } = modalSpy.mock.calls[0][1]!;
// modal opened as expected
expect(title).toEqual("Authentication");

View file

@ -21,7 +21,7 @@ import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import { logger } from "matrix-js-sdk/src/logger";
import { DeviceTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
import { sleep } from "matrix-js-sdk/src/utils";
import { defer, sleep } from "matrix-js-sdk/src/utils";
import {
ClientEvent,
IMyDevice,
@ -927,12 +927,9 @@ describe("<SessionManagerTab />", () => {
// get a handle for resolving the delete call
// because promise flushing after the confirm modal is resolving this too
// and we want to test the loading state here
let resolveDeleteRequest: (v?: IAuthData) => void;
const resolveDeleteRequest = defer<IAuthData>();
mockClient.deleteMultipleDevices.mockImplementation(() => {
const promise = new Promise<IAuthData>((resolve) => {
resolveDeleteRequest = resolve;
});
return promise;
return resolveDeleteRequest.promise;
});
const { getByTestId } = render(getComponent());
@ -972,7 +969,7 @@ describe("<SessionManagerTab />", () => {
undefined,
);
resolveDeleteRequest?.();
resolveDeleteRequest.resolve({});
});
it("signs out of all other devices from other sessions context menu", async () => {

View file

@ -54,7 +54,7 @@ function textMessageReply(body: string, msgtype = "m.text") {
function mergeAdjacentParts(parts: Part[]) {
let prevPart: Part | undefined;
for (let i = 0; i < parts.length; ++i) {
let part = parts[i];
let part: Part | undefined = parts[i];
const isEmpty = !part.text.length;
const isMerged = !isEmpty && prevPart && prevPart.merge?.(part);
if (isEmpty || isMerged) {

View file

@ -38,7 +38,7 @@ async function md2html(markdown: string): Promise<string> {
const pc = createPartCreator();
const oldModel = new EditorModel([], pc, () => {});
await oldModel.update(markdown, "insertText", new DocumentOffset(markdown.length, false));
return htmlSerializeIfNeeded(oldModel, { forceHTML: true });
return htmlSerializeIfNeeded(oldModel, { forceHTML: true })!;
}
function html2md(html: string): string {

View file

@ -143,7 +143,7 @@ describe("useProfileInfo", () => {
});
it("should be able to handle an empty result", async () => {
cli.getProfileInfo = () => null;
cli.getProfileInfo = () => null as unknown as Promise<{}>;
const query = "@user:home.server";
const wrapper = mount(

View file

@ -107,7 +107,7 @@ const setUpClientRoomAndStores = (): {
content,
});
room.addLiveEvents([event]);
return { event_id: event.getId() };
return { event_id: event.getId()! };
});
setupAsyncStoreWithClient(WidgetStore.instance, client);

View file

@ -20,7 +20,7 @@ import { AppModule } from "../../src/modules/AppModule";
describe("AppModule", () => {
describe("constructor", () => {
it("should call the factory immediately", () => {
let module: MockModule;
let module: MockModule | undefined;
const appModule = new AppModule((api) => {
if (module) {
throw new Error("State machine error: Factory called twice");

View file

@ -30,7 +30,7 @@ export class MockModule extends RuntimeModule {
}
export function registerMockModule(): MockModule {
let module: MockModule;
let module: MockModule | undefined;
ModuleRunner.instance.registerModule((api) => {
if (module) {
throw new Error("State machine error: ModuleRunner created the module twice");

View file

@ -800,7 +800,7 @@ describe("SpaceStore", () => {
testUtils.mockStateEventImplementation([childEvent]),
);
client.emit(RoomStateEvent.Events, childEvent, spaceRoom.currentState, undefined);
client.emit(RoomStateEvent.Events, childEvent, spaceRoom.currentState, null);
};
const addMember = (spaceId: string, user: RoomMember) => {
@ -964,7 +964,7 @@ describe("SpaceStore", () => {
}
});
client.emit(RoomStateEvent.Members, event, null, null);
client.emit(RoomStateEvent.Members, event, space.currentState, dm1Partner);
return deferred.resolve(true) as unknown as Promise<boolean>;
});
@ -1279,7 +1279,7 @@ describe("SpaceStore", () => {
user: dm1Partner.userId,
room: space1,
});
client.emit(RoomStateEvent.Members, memberEvent, undefined, undefined);
client.emit(RoomStateEvent.Members, memberEvent, rootSpace.currentState, dm1Partner);
jest.runOnlyPendingTimers();
expect(SpaceStore.instance.getSpaceFilteredUserIds(space1).has(dm1Partner.userId)).toBeTruthy();
const dm1Room = mkRoom(dm1);

View file

@ -21,7 +21,7 @@ import { MatrixClientPeg } from "../../src/MatrixClientPeg";
import { flushPromises } from "../test-utils";
import { VoiceMessageRecording } from "../../src/audio/VoiceMessageRecording";
const stubClient = {} as undefined as MatrixClient;
const stubClient = {} as unknown as MatrixClient;
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(stubClient);
describe("VoiceRecordingStore", () => {

View file

@ -216,7 +216,7 @@ describe("RoomListStore", () => {
// But when we update the feature flag
featureFlagValue = true;
watchCallback(
watchCallback!(
"feature_dynamic_room_predecessors",
"",
SettingLevel.DEFAULT,

View file

@ -68,6 +68,7 @@ describe("RecentAlgorithm", () => {
it("returns a fake ts for rooms without a timeline", () => {
const room = mkRoom(cli, "!new:example.org");
// @ts-ignore
room.timeline = undefined;
expect(algorithm.getLastTs(room, "@john:matrix.org")).toBe(Number.MAX_SAFE_INTEGER);
});

View file

@ -196,7 +196,7 @@ describe("geolocation utilities", () => {
// suppress expected errors from test log
jest.spyOn(logger, "error").mockImplementation(() => {});
geolocation.watchPosition.mockImplementation((_callback, error) => {
error(getMockGeolocationPositionError(1, "message"));
error!(getMockGeolocationPositionError(1, "message"));
return -1;
});
const positionHandler = jest.fn();
@ -224,7 +224,7 @@ describe("geolocation utilities", () => {
jest.spyOn(logger, "error").mockImplementation(() => {});
const timeoutError = getMockGeolocationPositionError(3, "message");
geolocation.getCurrentPosition.mockImplementation((callback, error) => error(timeoutError));
geolocation.getCurrentPosition.mockImplementation((callback, error) => error!(timeoutError));
await expect(() => getCurrentPosition()).rejects.toThrow(GeolocationError.Timeout);
});

View file

@ -135,7 +135,7 @@ describe("VoiceBroadcastRecording", () => {
event_id: infoEvent.getId(),
},
} as VoiceBroadcastInfoEventContent,
client.getUserId(),
client.getUserId()!,
);
});
};

View file

@ -49,14 +49,14 @@ describe("VoiceBroadcastRecordingsStore", () => {
infoEvent = mkVoiceBroadcastInfoStateEvent(
roomId,
VoiceBroadcastInfoState.Started,
client.getUserId(),
client.getDeviceId(),
client.getUserId()!,
client.getDeviceId()!,
);
otherInfoEvent = mkVoiceBroadcastInfoStateEvent(
roomId,
VoiceBroadcastInfoState.Started,
client.getUserId(),
client.getDeviceId(),
client.getUserId()!,
client.getDeviceId()!,
);
recording = new VoiceBroadcastRecording(infoEvent, client);
otherRecording = new VoiceBroadcastRecording(otherInfoEvent, client);

View file

@ -54,7 +54,7 @@ describe("VoiceBroadcastResumer", () => {
event_id: startedInfoEvent.getId(),
},
} as VoiceBroadcastInfoEventContent,
client.getUserId(),
client.getUserId()!,
);
});
};

View file

@ -161,7 +161,7 @@ describe("startNewVoiceBroadcastRecording", () => {
device_id: client.getDeviceId(),
state: VoiceBroadcastInfoState.Started,
},
client.getUserId(),
client.getUserId()!,
);
expect(recording!.infoEvent).toBe(infoEvent);
expect(recording!.start).toHaveBeenCalled();