diff --git a/apps/web/src/components/views/elements/LanguageDropdown.tsx b/apps/web/src/components/views/elements/LanguageDropdown.tsx index a61bc8281e..5948a49148 100644 --- a/apps/web/src/components/views/elements/LanguageDropdown.tsx +++ b/apps/web/src/components/views/elements/LanguageDropdown.tsx @@ -39,6 +39,8 @@ interface IState { } export default class LanguageDropdown extends React.Component { + private unmounted = false; + public constructor(props: IProps) { super(props); @@ -49,8 +51,11 @@ export default class LanguageDropdown extends React.Component { } public componentDidMount(): void { + this.unmounted = false; + getAllLanguagesWithLabels() .then((langs) => { + if (this.unmounted) return; langs.sort(function (a, b) { if (a.labelInTargetLanguage < b.labelInTargetLanguage) return -1; if (a.labelInTargetLanguage > b.labelInTargetLanguage) return 1; @@ -59,6 +64,7 @@ export default class LanguageDropdown extends React.Component { this.setState({ langs }); }) .catch(() => { + if (this.unmounted) return; this.setState({ langs: [ { @@ -78,6 +84,10 @@ export default class LanguageDropdown extends React.Component { } } + public componentWillUnmount(): void { + this.unmounted = true; + } + private onSearchChange = (search: string): void => { this.setState({ searchQuery: search, diff --git a/apps/web/src/test/setupTests.ts b/apps/web/src/test/setupTests.ts index 6368d6e52b..13f8f64cb0 100644 --- a/apps/web/src/test/setupTests.ts +++ b/apps/web/src/test/setupTests.ts @@ -18,9 +18,26 @@ declare global { globalThis.IS_REACT_ACT_ENVIRONMENT = true; +// Ignore benign post-teardown exceptions as they cause flakes +const guardState = globalThis as unknown as { __vitestTestRunning?: boolean; __teardownGuardInstalled?: boolean }; +if (!guardState.__teardownGuardInstalled) { + guardState.__teardownGuardInstalled = true; + const isPostTeardownStraggler = (): boolean => !guardState.__vitestTestRunning || typeof window === "undefined"; + process.on("uncaughtException", (err) => { + if (isPostTeardownStraggler()) return; + throw err; + }); + process.on("unhandledRejection", (reason) => { + if (isPostTeardownStraggler()) return; + throw reason; + }); +} + manageFetchMockGlobally(); beforeEach(() => { + guardState.__vitestTestRunning = true; + vi.stubEnv("TZ", "UTC"); // set up fetch API mock @@ -31,7 +48,10 @@ beforeEach(() => { setupLanguageMock(); }); -afterEach(() => fetchMock.callHistory.flush()); +afterEach(() => { + guardState.__vitestTestRunning = false; + return fetchMock.callHistory.flush(); +}); // uninitialised SdkConfig causes lots of warnings in console, init with defaults SdkConfig.put(DEFAULTS);