From 9d0239106251a44b0d921d67e97bcf60f4f7fb7a Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 4 Aug 2020 12:24:31 -0600 Subject: [PATCH] [CORL-1239] Swap setTimeout for setLongTimeout (#3071) * fix: ensure user editable time use setLongTimeout * fix: fixed wrong type * fix: fixed snapshots Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../DecisionHistoryLoading.spec.tsx.snap | 4 +--- .../App/GlobalNotification/useNotification.ts | 3 ++- .../routes/AuthCheck/RestrictedContainer.tsx | 4 ++-- .../stream/local/initLocalState.spec.ts | 4 ++-- .../mutations/SetCommentIDMutation.spec.ts | 7 ++++--- .../Comments/Comment/CommentContainer.tsx | 3 ++- .../EditCommentFormContainer.tsx | 4 +++- .../ReplyCommentFormContainer.spec.tsx | 21 ++++++++++--------- .../PermalinkViewQuery.spec.tsx.snap | 4 +--- .../PostCommentFormContainer.spec.tsx | 17 ++++++++------- .../StoryClosedTimeoutContainer.tsx | 3 ++- .../stream/tabs/Configure/ConfigureQuery.tsx | 2 +- .../tabs/Discussions/DiscussionsQuery.tsx | 2 +- .../stream/tabs/Profile/ProfileQuery.tsx | 2 +- .../client/ui/components/v2/Delay/Delay.tsx | 11 ++++------ src/core/common/helpers/waitFor.ts | 11 +++++----- src/core/common/utils/index.ts | 1 - src/core/common/utils/timeout.ts | 6 ------ src/core/server/services/fetch/abortAfter.ts | 3 ++- src/core/server/services/fetch/fetch.ts | 3 ++- 20 files changed, 55 insertions(+), 60 deletions(-) delete mode 100644 src/core/common/utils/timeout.ts diff --git a/src/core/client/admin/App/DecisionHistory/__snapshots__/DecisionHistoryLoading.spec.tsx.snap b/src/core/client/admin/App/DecisionHistory/__snapshots__/DecisionHistoryLoading.spec.tsx.snap index 7aa275f96..2fb34d770 100644 --- a/src/core/client/admin/App/DecisionHistory/__snapshots__/DecisionHistoryLoading.spec.tsx.snap +++ b/src/core/client/admin/App/DecisionHistory/__snapshots__/DecisionHistoryLoading.spec.tsx.snap @@ -11,9 +11,7 @@ exports[`renders correctly 1`] = ` className="DecisionHistoryLoading-container" justifyContent="center" > - + diff --git a/src/core/client/admin/App/GlobalNotification/useNotification.ts b/src/core/client/admin/App/GlobalNotification/useNotification.ts index 9aea0cac6..c66a354fa 100644 --- a/src/core/client/admin/App/GlobalNotification/useNotification.ts +++ b/src/core/client/admin/App/GlobalNotification/useNotification.ts @@ -1,4 +1,5 @@ import { useRouter } from "found"; +import { setLongTimeout } from "long-settimeout"; import { ReactNode, useContext } from "react"; import { NotificationContext } from "./GlobalNotificationContext"; @@ -17,7 +18,7 @@ function useNotification() { const setMessage = (message: ReactNode, timeout?: number) => { dispatch({ type: "SET_MESSAGE", message }); if (timeout) { - setTimeout(() => { + setLongTimeout(() => { dispatch({ type: "CLEAR_MESSAGE" }); }, timeout); } diff --git a/src/core/client/admin/routes/AuthCheck/RestrictedContainer.tsx b/src/core/client/admin/routes/AuthCheck/RestrictedContainer.tsx index 37038d9bd..57981d098 100644 --- a/src/core/client/admin/routes/AuthCheck/RestrictedContainer.tsx +++ b/src/core/client/admin/routes/AuthCheck/RestrictedContainer.tsx @@ -3,7 +3,7 @@ import React, { Component } from "react"; import { graphql } from "react-relay"; import { SetRedirectPathMutation } from "coral-admin/mutations"; -import { timeout } from "coral-common/utils"; +import { waitFor } from "coral-common/helpers"; import { MutationProp, withFragmentContainer, @@ -31,7 +31,7 @@ class RestrictedContainer extends Component { private handleSignInAs = async () => { await this.props.signOut(); // Wait for new context to propagate. - await timeout(); + await waitFor(); void this.props.setRedirectPath({ path: location.pathname + location.search + location.hash, }); diff --git a/src/core/client/stream/local/initLocalState.spec.ts b/src/core/client/stream/local/initLocalState.spec.ts index 47f1b69fe..b10592836 100644 --- a/src/core/client/stream/local/initLocalState.spec.ts +++ b/src/core/client/stream/local/initLocalState.spec.ts @@ -1,6 +1,6 @@ import { Environment, RecordSource } from "relay-runtime"; -import { timeout } from "coral-common/utils"; +import { waitFor } from "coral-common/helpers"; import { CoralContext } from "coral-framework/lib/bootstrap"; import { LOCAL_ID } from "coral-framework/lib/relay"; import { createPromisifiedStorage } from "coral-framework/lib/storage"; @@ -27,7 +27,7 @@ it("init local state", async () => { localStorage: createPromisifiedStorage(), }; await initLocalState(environment, context as any); - await timeout(); + await waitFor(); expect(JSON.stringify(source.toJSON(), null, 2)).toMatchSnapshot(); }); diff --git a/src/core/client/stream/mutations/SetCommentIDMutation.spec.ts b/src/core/client/stream/mutations/SetCommentIDMutation.spec.ts index b33aeacab..c6dfcafc6 100644 --- a/src/core/client/stream/mutations/SetCommentIDMutation.spec.ts +++ b/src/core/client/stream/mutations/SetCommentIDMutation.spec.ts @@ -1,7 +1,8 @@ import { Environment, RecordSource } from "relay-runtime"; import sinon from "sinon"; -import { parseQuery, timeout } from "coral-common/utils"; +import { waitFor } from "coral-common/helpers"; +import { parseQuery } from "coral-common/utils"; import { LOCAL_ID } from "coral-framework/lib/relay"; import { createRelayEnvironment } from "coral-framework/testHelpers"; @@ -39,7 +40,7 @@ it("Should call setCommentID in pym", async () => { }, }; await commit(environment, { id }, context as any); - await timeout(); + await waitFor(); expect(source.get(LOCAL_ID)!.commentID).toEqual(id); context.pym.sendMessage.verify(); }); @@ -51,7 +52,7 @@ it("Should call setCommentID in pym with empty id", async () => { }, }; await commit(environment, { id: null }, context as any); - await timeout(); + await waitFor(); expect(source.get(LOCAL_ID)!.commentID).toEqual(null); expect(parseQuery(location.search).commentID).toBeUndefined(); context.pym.sendMessage.verify(); diff --git a/src/core/client/stream/tabs/Comments/Comment/CommentContainer.tsx b/src/core/client/stream/tabs/Comments/Comment/CommentContainer.tsx index 4790aba8a..b456b989a 100644 --- a/src/core/client/stream/tabs/Comments/Comment/CommentContainer.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/CommentContainer.tsx @@ -1,6 +1,7 @@ import { Localized } from "@fluent/react/compat"; import cn from "classnames"; import { EventEmitter2 } from "eventemitter2"; +import { setLongTimeout } from "long-settimeout"; import React, { Component, MouseEvent } from "react"; import { graphql } from "react-relay"; @@ -179,7 +180,7 @@ export class CommentContainer extends Component { new Date(this.props.comment.editing.editableUntil!).getTime() - Date.now(); if (ms > 0) { - return setTimeout(() => this.setState({ editable: false }), ms); + return setLongTimeout(() => this.setState({ editable: false }), ms); } return; } diff --git a/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx b/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx index 6168bb198..d8be0237c 100644 --- a/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx @@ -1,4 +1,5 @@ import { CoralRTE } from "@coralproject/rte"; +import { setLongTimeout } from "long-settimeout"; import React, { Component } from "react"; import { graphql } from "react-relay"; @@ -15,6 +16,7 @@ import CLASSES from "coral-stream/classes"; import { EditCommentFormContainer_comment as CommentData } from "coral-stream/__generated__/EditCommentFormContainer_comment.graphql"; import { EditCommentFormContainer_settings as SettingsData } from "coral-stream/__generated__/EditCommentFormContainer_settings.graphql"; import { EditCommentFormContainer_story as StoryData } from "coral-stream/__generated__/EditCommentFormContainer_story.graphql"; + import { getSubmitStatus, shouldTriggerSettingsRefresh, @@ -99,7 +101,7 @@ export class EditCommentFormContainer extends Component { new Date(this.props.comment.editing.editableUntil!).getTime() - Date.now(); if (ms > 0) { - return setTimeout(() => this.setState({ expired: true }), ms); + return setLongTimeout(() => this.setState({ expired: true }), ms); } return; } diff --git a/src/core/client/stream/tabs/Comments/Comment/ReplyCommentForm/ReplyCommentFormContainer.spec.tsx b/src/core/client/stream/tabs/Comments/Comment/ReplyCommentForm/ReplyCommentFormContainer.spec.tsx index 21d856a61..1f0739c5c 100644 --- a/src/core/client/stream/tabs/Comments/Comment/ReplyCommentForm/ReplyCommentFormContainer.spec.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/ReplyCommentForm/ReplyCommentFormContainer.spec.tsx @@ -4,7 +4,8 @@ import React from "react"; import { createRenderer } from "react-test-renderer/shallow"; import sinon from "sinon"; -import { pureMerge, timeout } from "coral-common/utils"; +import { waitFor } from "coral-common/helpers"; +import { pureMerge } from "coral-common/utils"; import { createPromisifiedStorage } from "coral-framework/lib/storage"; import { removeFragmentRefs, wait } from "coral-framework/testHelpers"; import { DeepPartial, PropTypesOf } from "coral-framework/types"; @@ -75,7 +76,7 @@ it("renders correctly", async () => { const renderer = createRenderer(); renderer.render(); - await timeout(); + await waitFor(); expect(renderer.getRenderOutput()).toMatchSnapshot(); }); @@ -89,7 +90,7 @@ it("renders with initialValues", async () => { const renderer = createRenderer(); renderer.render(); - await timeout(); + await waitFor(); expect(renderer.getRenderOutput()).toMatchSnapshot(); }); @@ -102,7 +103,7 @@ it("save values", async () => { ); const wrapper = shallow(); - await timeout(); + await waitFor(); wrapper.update(); wrapper .first() @@ -131,7 +132,7 @@ it("creates a comment", async () => { ); const wrapper = shallow(); - await timeout(); + await waitFor(); wrapper.update(); wrapper.first().props().onSubmit(input, form); expect( @@ -145,7 +146,7 @@ it("creates a comment", async () => { ...input, }) ).toBeTruthy(); - await timeout(); + await waitFor(); expect(onCloseStub.calledOnce).toBe(true); }); @@ -161,7 +162,7 @@ it("closes on cancel", async () => { ); const wrapper = shallow(); - await timeout(); + await waitFor(); wrapper.update(); wrapper.findWhere((w) => !!w.prop("onCancel")).prop("onCancel")(); @@ -183,7 +184,7 @@ it("autofocuses", async () => { }); const wrapper = shallow(); - await timeout(); + await waitFor(); wrapper.update(); wrapper .findWhere((n) => n.prop("rteRef")) @@ -206,7 +207,7 @@ it("renders when story has been closed", async () => { const renderer = createRenderer(); renderer.render(); - await timeout(); + await waitFor(); expect(renderer.getRenderOutput()).toMatchSnapshot(); }); @@ -221,6 +222,6 @@ it("renders when commenting has been disabled", async () => { }); const renderer = createRenderer(); renderer.render(); - await timeout(); + await waitFor(); expect(renderer.getRenderOutput()).toMatchSnapshot(); }); diff --git a/src/core/client/stream/tabs/Comments/PermalinkView/__snapshots__/PermalinkViewQuery.spec.tsx.snap b/src/core/client/stream/tabs/Comments/PermalinkView/__snapshots__/PermalinkViewQuery.spec.tsx.snap index 45a9c24f5..6998c6ffe 100644 --- a/src/core/client/stream/tabs/Comments/PermalinkView/__snapshots__/PermalinkViewQuery.spec.tsx.snap +++ b/src/core/client/stream/tabs/Comments/PermalinkView/__snapshots__/PermalinkViewQuery.spec.tsx.snap @@ -7,9 +7,7 @@ exports[`renders error 1`] = ` `; exports[`renders loading 1`] = ` - + `; diff --git a/src/core/client/stream/tabs/Comments/Stream/PostCommentForm/PostCommentFormContainer.spec.tsx b/src/core/client/stream/tabs/Comments/Stream/PostCommentForm/PostCommentFormContainer.spec.tsx index 3454de135..440156c61 100644 --- a/src/core/client/stream/tabs/Comments/Stream/PostCommentForm/PostCommentFormContainer.spec.tsx +++ b/src/core/client/stream/tabs/Comments/Stream/PostCommentForm/PostCommentFormContainer.spec.tsx @@ -3,7 +3,8 @@ import { noop } from "lodash"; import React from "react"; import sinon from "sinon"; -import { pureMerge, timeout } from "coral-common/utils"; +import { waitFor } from "coral-common/helpers"; +import { pureMerge } from "coral-common/utils"; import { createPromisifiedStorage } from "coral-framework/lib/storage"; import { act, removeFragmentRefs, wait } from "coral-framework/testHelpers"; import { DeepPartial, PropTypesOf } from "coral-framework/types"; @@ -110,7 +111,7 @@ it("save values", async () => { await props.sessionStorage.setItem(contextKey, "Hello World!"); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.update(); @@ -151,7 +152,7 @@ it("creates a comment", async () => { }); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.update(); @@ -190,7 +191,7 @@ it("renders when story has been closed (collapsing)", async () => { }, }); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.update(); @@ -211,7 +212,7 @@ it("renders when commenting has been disabled (collapsing)", async () => { }, }); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.update(); @@ -244,7 +245,7 @@ it("renders when story has been closed (non-collapsing)", async () => { }, }); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.setProps(nextProps); @@ -273,7 +274,7 @@ it("renders when commenting has been disabled (non-collapsing)", async () => { }, }); const wrapper = shallow(); - await timeout(); + await waitFor(); act(() => { wrapper.setProps(nextProps); @@ -291,7 +292,7 @@ it("renders when user is scheduled to be deleted", async () => { }, }); const wrapper = shallow(); - await timeout(); + await waitFor(); await act(async () => { await wait(() => expect(wrapper).toMatchSnapshot()); diff --git a/src/core/client/stream/tabs/Comments/Stream/StoryClosedTimeout/StoryClosedTimeoutContainer.tsx b/src/core/client/stream/tabs/Comments/Stream/StoryClosedTimeout/StoryClosedTimeoutContainer.tsx index 463ce86b0..0bb596fae 100644 --- a/src/core/client/stream/tabs/Comments/Stream/StoryClosedTimeout/StoryClosedTimeoutContainer.tsx +++ b/src/core/client/stream/tabs/Comments/Stream/StoryClosedTimeout/StoryClosedTimeoutContainer.tsx @@ -1,3 +1,4 @@ +import { setLongTimeout } from "long-settimeout"; import React from "react"; import { graphql } from "react-relay"; @@ -18,7 +19,7 @@ interface Props { function createTimeout(callback: () => void, closedAt: string) { const diff = new Date(closedAt).valueOf() - Date.now(); if (diff > 0) { - return setTimeout(callback, diff); + return setLongTimeout(callback, diff); } return null; } diff --git a/src/core/client/stream/tabs/Configure/ConfigureQuery.tsx b/src/core/client/stream/tabs/Configure/ConfigureQuery.tsx index a4bbc87a1..2b2083c00 100644 --- a/src/core/client/stream/tabs/Configure/ConfigureQuery.tsx +++ b/src/core/client/stream/tabs/Configure/ConfigureQuery.tsx @@ -24,7 +24,7 @@ const loadConfigureContainer = () => ); // (cvle) For some reason without `setTimeout` this request will block other requests. const preloadConfigureContainer = once(() => - setTimeout(loadConfigureContainer) + setTimeout(loadConfigureContainer, 0) ); const LazyConfigureContainer = React.lazy(loadConfigureContainer); diff --git a/src/core/client/stream/tabs/Discussions/DiscussionsQuery.tsx b/src/core/client/stream/tabs/Discussions/DiscussionsQuery.tsx index feb2851a7..e2959f1d4 100644 --- a/src/core/client/stream/tabs/Discussions/DiscussionsQuery.tsx +++ b/src/core/client/stream/tabs/Discussions/DiscussionsQuery.tsx @@ -25,7 +25,7 @@ const loadDiscussionsContainer = () => ); // (cvle) For some reason without `setTimeout` this request will block other requests. const preloadDiscussionsContainer = once(() => - setTimeout(loadDiscussionsContainer) + setTimeout(loadDiscussionsContainer, 0) ); const LazyDiscussionsContainer = React.lazy(loadDiscussionsContainer); diff --git a/src/core/client/stream/tabs/Profile/ProfileQuery.tsx b/src/core/client/stream/tabs/Profile/ProfileQuery.tsx index 1376f9b87..3b36dc183 100644 --- a/src/core/client/stream/tabs/Profile/ProfileQuery.tsx +++ b/src/core/client/stream/tabs/Profile/ProfileQuery.tsx @@ -22,7 +22,7 @@ const loadProfileContainer = () => return x; }); // (cvle) For some reason without `setTimeout` this request will block other requests. -const preloadProfileContainer = once(() => setTimeout(loadProfileContainer)); +const preloadProfileContainer = once(() => setTimeout(loadProfileContainer, 0)); const LazyProfileContainer = React.lazy(loadProfileContainer); diff --git a/src/core/client/ui/components/v2/Delay/Delay.tsx b/src/core/client/ui/components/v2/Delay/Delay.tsx index 3c90d65dd..e65eb22ed 100644 --- a/src/core/client/ui/components/v2/Delay/Delay.tsx +++ b/src/core/client/ui/components/v2/Delay/Delay.tsx @@ -1,3 +1,4 @@ +import { clearLongTimeout, setLongTimeout } from "long-settimeout"; import React, { FunctionComponent, useEffect, useState } from "react"; interface Props { @@ -5,14 +6,14 @@ interface Props { children: React.ReactNode; } -const Delay: FunctionComponent = ({ ms, children }) => { +const Delay: FunctionComponent = ({ ms = 500, children }) => { const [render, setRender] = useState(false); useEffect(() => { - const timeout = setTimeout(() => { + const timeout = setLongTimeout(() => { setRender(true); }, ms); return () => { - clearTimeout(timeout); + clearLongTimeout(timeout); }; }, [ms]); if (!render) { @@ -21,8 +22,4 @@ const Delay: FunctionComponent = ({ ms, children }) => { return <>{children}; }; -Delay.defaultProps = { - ms: 500, -}; - export default Delay; diff --git a/src/core/common/helpers/waitFor.ts b/src/core/common/helpers/waitFor.ts index 5349f1e66..9802f8a42 100644 --- a/src/core/common/helpers/waitFor.ts +++ b/src/core/common/helpers/waitFor.ts @@ -1,7 +1,6 @@ -export default function waitFor(timeout: number): Promise { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, timeout); - }); +import { setLongTimeout } from "long-settimeout"; + +/** A promisified timeout. */ +export default function waitFor(ms = 0): Promise { + return new Promise((resolve) => setLongTimeout(resolve, ms)); } diff --git a/src/core/common/utils/index.ts b/src/core/common/utils/index.ts index 4dedb2a47..c822d84d1 100644 --- a/src/core/common/utils/index.ts +++ b/src/core/common/utils/index.ts @@ -1,4 +1,3 @@ -export { default as timeout } from "./timeout"; export { default as animationFrame } from "./animationFrame"; export { default as pascalCase } from "./pascalCase"; export { default as oncePerFrame } from "./oncePerFrame"; diff --git a/src/core/common/utils/timeout.ts b/src/core/common/utils/timeout.ts deleted file mode 100644 index 1978aa485..000000000 --- a/src/core/common/utils/timeout.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { setLongTimeout } from "long-settimeout"; - -/** A promisified timeout. */ -export default function timeout(ms = 0) { - return new Promise((resolve) => setLongTimeout(resolve, ms)); -} diff --git a/src/core/server/services/fetch/abortAfter.ts b/src/core/server/services/fetch/abortAfter.ts index 180706a58..d07b601be 100644 --- a/src/core/server/services/fetch/abortAfter.ts +++ b/src/core/server/services/fetch/abortAfter.ts @@ -1,8 +1,9 @@ import AbortController from "abort-controller"; +import { setLongTimeout } from "long-settimeout"; function abortAfter(ms: number) { const controller = new AbortController(); - const timeout = setTimeout(() => { + const timeout = setLongTimeout(() => { controller.abort(); }, ms); diff --git a/src/core/server/services/fetch/fetch.ts b/src/core/server/services/fetch/fetch.ts index 6137d965f..dcc8e112e 100644 --- a/src/core/server/services/fetch/fetch.ts +++ b/src/core/server/services/fetch/fetch.ts @@ -1,6 +1,7 @@ import http from "http"; import https from "https"; import { capitalize } from "lodash"; +import { clearLongTimeout } from "long-settimeout"; import fetch, { RequestInit, Response } from "node-fetch"; import { URL } from "url"; @@ -119,7 +120,7 @@ export const createFetch = ({ return res; } finally { - clearTimeout(abort.timeout); + clearLongTimeout(abort.timeout); } }; };