5663 i should be able to accept an invite even if i have an inactive workspace (#5839)
- make invitation and reset password available on every page - add a sleep after setKeyPair as tokens are sometimes not updated when redirecting to Index - refactor sleep
This commit is contained in:
@ -52,27 +52,27 @@ const testCases = [
|
|||||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.Completed, res: defaultHomePagePath },
|
{ loc: AppPath.SignInUp, status: OnboardingStatus.Completed, res: defaultHomePagePath },
|
||||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.CompletedWithoutSubscription, res: defaultHomePagePath },
|
{ loc: AppPath.SignInUp, status: OnboardingStatus.CompletedWithoutSubscription, res: defaultHomePagePath },
|
||||||
|
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.Incomplete, res: AppPath.PlanRequired },
|
{ loc: AppPath.Invite, status: OnboardingStatus.Incomplete, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.Canceled, res: '/settings/billing' },
|
{ loc: AppPath.Invite, status: OnboardingStatus.Canceled, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.Unpaid, res: '/settings/billing' },
|
{ loc: AppPath.Invite, status: OnboardingStatus.Unpaid, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.PastDue, res: undefined },
|
{ loc: AppPath.Invite, status: OnboardingStatus.PastDue, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingUserCreation, res: undefined },
|
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingUserCreation, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingWorkspaceActivation, res: AppPath.CreateWorkspace },
|
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingWorkspaceActivation, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingProfileCreation, res: AppPath.CreateProfile },
|
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingProfileCreation, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingSyncEmail, res: AppPath.SyncEmails },
|
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingSyncEmail, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingInviteTeam, res: AppPath.InviteTeam },
|
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingInviteTeam, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.Completed, res: undefined },
|
{ loc: AppPath.Invite, status: OnboardingStatus.Completed, res: undefined },
|
||||||
{ loc: AppPath.Invite, status: OnboardingStatus.CompletedWithoutSubscription, res: undefined },
|
{ loc: AppPath.Invite, status: OnboardingStatus.CompletedWithoutSubscription, res: undefined },
|
||||||
|
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Incomplete, res: AppPath.PlanRequired },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Incomplete, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Canceled, res: '/settings/billing' },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Canceled, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Unpaid, res: '/settings/billing' },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Unpaid, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.PastDue, res: undefined },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.PastDue, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingUserCreation, res: undefined },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingUserCreation, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingWorkspaceActivation, res: AppPath.CreateWorkspace },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingWorkspaceActivation, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingProfileCreation, res: AppPath.CreateProfile },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingProfileCreation, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingSyncEmail, res: AppPath.SyncEmails },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingSyncEmail, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingInviteTeam, res: AppPath.InviteTeam },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingInviteTeam, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Completed, res: undefined },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Completed, res: undefined },
|
||||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.CompletedWithoutSubscription, res: undefined },
|
{ loc: AppPath.ResetPassword, status: OnboardingStatus.CompletedWithoutSubscription, res: undefined },
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,10 @@ export const usePageChangeEffectNavigateLocation = () => {
|
|||||||
isMatchingLocation(AppPath.PlanRequired) ||
|
isMatchingLocation(AppPath.PlanRequired) ||
|
||||||
isMatchingLocation(AppPath.PlanRequiredSuccess);
|
isMatchingLocation(AppPath.PlanRequiredSuccess);
|
||||||
|
|
||||||
|
if (isMatchingOpenRoute) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
onboardingStatus === OnboardingStatus.OngoingUserCreation &&
|
onboardingStatus === OnboardingStatus.OngoingUserCreation &&
|
||||||
!isMatchingOngoingUserCreationRoute
|
!isMatchingOngoingUserCreationRoute
|
||||||
@ -89,8 +93,7 @@ export const usePageChangeEffectNavigateLocation = () => {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
onboardingStatus === OnboardingStatus.Completed &&
|
onboardingStatus === OnboardingStatus.Completed &&
|
||||||
isMatchingOnboardingRoute &&
|
isMatchingOnboardingRoute
|
||||||
!isMatchingOpenRoute
|
|
||||||
) {
|
) {
|
||||||
return defaultHomePagePath;
|
return defaultHomePagePath;
|
||||||
}
|
}
|
||||||
@ -98,7 +101,6 @@ export const usePageChangeEffectNavigateLocation = () => {
|
|||||||
if (
|
if (
|
||||||
onboardingStatus === OnboardingStatus.CompletedWithoutSubscription &&
|
onboardingStatus === OnboardingStatus.CompletedWithoutSubscription &&
|
||||||
isMatchingOnboardingRoute &&
|
isMatchingOnboardingRoute &&
|
||||||
!isMatchingOpenRoute &&
|
|
||||||
!isMatchingLocation(AppPath.PlanRequired)
|
!isMatchingLocation(AppPath.PlanRequired)
|
||||||
) {
|
) {
|
||||||
return defaultHomePagePath;
|
return defaultHomePagePath;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
mockDefaultWorkspace,
|
mockDefaultWorkspace,
|
||||||
mockedWorkspaceMemberData,
|
mockedWorkspaceMemberData,
|
||||||
} from '~/testing/mock-data/users';
|
} from '~/testing/mock-data/users';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { CommandMenu } from '../CommandMenu';
|
import { CommandMenu } from '../CommandMenu';
|
||||||
|
|
||||||
|
|||||||
@ -6,24 +6,10 @@ import {
|
|||||||
displayedExportProgress,
|
displayedExportProgress,
|
||||||
download,
|
download,
|
||||||
generateCsv,
|
generateCsv,
|
||||||
sleep,
|
|
||||||
} from '../useExportTableData';
|
} from '../useExportTableData';
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
describe('sleep', () => {
|
|
||||||
it('waits the provided number of milliseconds', async () => {
|
|
||||||
const spy = jest.fn();
|
|
||||||
sleep(1000).then(spy);
|
|
||||||
|
|
||||||
jest.advanceTimersByTime(999);
|
|
||||||
expect(spy).not.toHaveBeenCalled();
|
|
||||||
jest.advanceTimersByTime(1);
|
|
||||||
await Promise.resolve(); // let queued promises execute
|
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('download', () => {
|
describe('download', () => {
|
||||||
it('creates a download link and clicks it', () => {
|
it('creates a download link and clicks it', () => {
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
|
|||||||
@ -8,12 +8,10 @@ import { useRecordTableStates } from '@/object-record/record-table/hooks/interna
|
|||||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||||
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { useFindManyParams } from '../../hooks/useLoadRecordIndexTable';
|
import { useFindManyParams } from '../../hooks/useLoadRecordIndexTable';
|
||||||
|
|
||||||
export const sleep = (ms: number) =>
|
|
||||||
new Promise((resolve) => setTimeout(resolve, ms));
|
|
||||||
|
|
||||||
export const download = (blob: Blob, filename: string) => {
|
export const download = (blob: Blob, filename: string) => {
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { RelationPickerDecorator } from '~/testing/decorators/RelationPickerDeco
|
|||||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { getPeopleMock } from '~/testing/mock-data/people';
|
import { getPeopleMock } from '~/testing/mock-data/people';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { EntityForSelect } from '../../types/EntityForSelect';
|
import { EntityForSelect } from '../../types/EntityForSelect';
|
||||||
import { SingleEntitySelect } from '../SingleEntitySelect';
|
import { SingleEntitySelect } from '../SingleEntitySelect';
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { defaultSpreadsheetImportProps } from '@/spreadsheet-import/provider/components/SpreadsheetImport';
|
import { defaultSpreadsheetImportProps } from '@/spreadsheet-import/provider/components/SpreadsheetImport';
|
||||||
import { Fields, SpreadsheetOptions } from '@/spreadsheet-import/types';
|
import { Fields, SpreadsheetOptions } from '@/spreadsheet-import/types';
|
||||||
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{
|
{
|
||||||
@ -102,22 +103,16 @@ export const mockRsiValues = mockComponentBehaviourForTypes({
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
uploadStepHook: async (data) => {
|
uploadStepHook: async (data) => {
|
||||||
await new Promise((resolve) => {
|
await sleep(4000, (resolve) => resolve(data));
|
||||||
setTimeout(() => resolve(data), 4000);
|
|
||||||
});
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
selectHeaderStepHook: async (hData, data) => {
|
selectHeaderStepHook: async (hData, data) => {
|
||||||
await new Promise((resolve) => {
|
await sleep(4000, (resolve) =>
|
||||||
setTimeout(
|
resolve({
|
||||||
() =>
|
headerValues: hData,
|
||||||
resolve({
|
data,
|
||||||
headerValues: hData,
|
}),
|
||||||
data,
|
);
|
||||||
}),
|
|
||||||
4000,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
headerValues: hData,
|
headerValues: hData,
|
||||||
data,
|
data,
|
||||||
@ -125,9 +120,7 @@ export const mockRsiValues = mockComponentBehaviourForTypes({
|
|||||||
},
|
},
|
||||||
// Runs after column matching and on entry change, more performant
|
// Runs after column matching and on entry change, more performant
|
||||||
matchColumnsStepHook: async (data) => {
|
matchColumnsStepHook: async (data) => {
|
||||||
await new Promise((resolve) => {
|
await sleep(4000, (resolve) => resolve(data));
|
||||||
setTimeout(() => resolve(data), 4000);
|
|
||||||
});
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { expect, userEvent, within } from '@storybook/test';
|
|||||||
import { ComponentDecorator } from 'twenty-ui';
|
import { ComponentDecorator } from 'twenty-ui';
|
||||||
|
|
||||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { IconPicker, IconPickerProps } from '../IconPicker';
|
import { IconPicker, IconPickerProps } from '../IconPicker';
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { tokenPairState } from '@/auth/states/tokenPairState';
|
|||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { useGenerateJwtMutation } from '~/generated/graphql';
|
import { useGenerateJwtMutation } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
export const useWorkspaceSwitching = () => {
|
export const useWorkspaceSwitching = () => {
|
||||||
const setTokenPair = useSetRecoilState(tokenPairState);
|
const setTokenPair = useSetRecoilState(tokenPairState);
|
||||||
@ -29,6 +30,7 @@ export const useWorkspaceSwitching = () => {
|
|||||||
|
|
||||||
const { tokens } = jwt.data.generateJWT;
|
const { tokens } = jwt.data.generateJWT;
|
||||||
setTokenPair(tokens);
|
setTokenPair(tokens);
|
||||||
|
await sleep(0); // This hacky workaround is necessary to ensure the tokens stored in the cookie are updated correctly.
|
||||||
window.location.href = AppPath.Index;
|
window.location.href = AppPath.Index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,6 @@ export const Invite = () => {
|
|||||||
<>
|
<>
|
||||||
<StyledContentContainer>
|
<StyledContentContainer>
|
||||||
<MainButton
|
<MainButton
|
||||||
variant="secondary"
|
|
||||||
title="Continue"
|
title="Continue"
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={handleUserJoinWorkspace}
|
onClick={handleUserJoinWorkspace}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { ImpersonateEffect } from '../ImpersonateEffect';
|
import { ImpersonateEffect } from '../ImpersonateEffect';
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title: 'Pages/Onboarding/ChooseYourPlan',
|
title: 'Pages/Onboarding/ChooseYourPlan',
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsBilling } from '../SettingsBilling';
|
import { SettingsBilling } from '../SettingsBilling';
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsWorkspaceMembers } from '../SettingsWorkspaceMembers';
|
import { SettingsWorkspaceMembers } from '../SettingsWorkspaceMembers';
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsAccountsCalendars } from '../SettingsAccountsCalendars';
|
import { SettingsAccountsCalendars } from '../SettingsAccountsCalendars';
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { mockedConnectedAccounts } from '~/testing/mock-data/accounts';
|
import { mockedConnectedAccounts } from '~/testing/mock-data/accounts';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsAccountsCalendarsSettings } from '../SettingsAccountsCalendarsSettings';
|
import { SettingsAccountsCalendarsSettings } from '../SettingsAccountsCalendarsSettings';
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsObjectDetail } from '../SettingsObjectDetail';
|
import { SettingsObjectDetail } from '../SettingsObjectDetail';
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsObjectEdit } from '../SettingsObjectEdit';
|
import { SettingsObjectEdit } from '../SettingsObjectEdit';
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { SettingsObjects } from '../SettingsObjects';
|
import { SettingsObjects } from '../SettingsObjects';
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title: 'Pages/Settings/Developers/SettingsDevelopers',
|
title: 'Pages/Settings/Developers/SettingsDevelopers',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title: 'Pages/Settings/Integrations/SettingsIntegrationDatabase',
|
title: 'Pages/Settings/Integrations/SettingsIntegrationDatabase',
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title:
|
title:
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title: 'Pages/Settings/Integrations/SettingsIntegrationNewDatabaseConnection',
|
title: 'Pages/Settings/Integrations/SettingsIntegrationNewDatabaseConnection',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title:
|
title:
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
PageDecoratorArgs,
|
PageDecoratorArgs,
|
||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
const meta: Meta<PageDecoratorArgs> = {
|
const meta: Meta<PageDecoratorArgs> = {
|
||||||
title: 'Pages/Settings/Integrations/SettingsIntegrations',
|
title: 'Pages/Settings/Integrations/SettingsIntegrations',
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
} from '~/testing/decorators/PageDecorator';
|
} from '~/testing/decorators/PageDecorator';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { mockedWorkspaceMemberData } from '~/testing/mock-data/users';
|
import { mockedWorkspaceMemberData } from '~/testing/mock-data/users';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
import { Tasks } from '../Tasks';
|
import { Tasks } from '../Tasks';
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { profilingQueueState } from '~/testing/profiling/states/profilingQueueSt
|
|||||||
import { profilingSessionRunsState } from '~/testing/profiling/states/profilingSessionRunsState';
|
import { profilingSessionRunsState } from '~/testing/profiling/states/profilingSessionRunsState';
|
||||||
import { profilingSessionStatusState } from '~/testing/profiling/states/profilingSessionStatusState';
|
import { profilingSessionStatusState } from '~/testing/profiling/states/profilingSessionStatusState';
|
||||||
import { getTestArray } from '~/testing/profiling/utils/getTestArray';
|
import { getTestArray } from '~/testing/profiling/utils/getTestArray';
|
||||||
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
export const ProfilingQueueEffect = ({
|
export const ProfilingQueueEffect = ({
|
||||||
profilingId,
|
profilingId,
|
||||||
@ -84,7 +85,7 @@ export const ProfilingQueueEffect = ({
|
|||||||
? TIME_BETWEEN_TEST_RUNS_IN_MS * 2
|
? TIME_BETWEEN_TEST_RUNS_IN_MS * 2
|
||||||
: TIME_BETWEEN_TEST_RUNS_IN_MS;
|
: TIME_BETWEEN_TEST_RUNS_IN_MS;
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, timeInMs));
|
await sleep(timeInMs);
|
||||||
|
|
||||||
const nextIndex = currentProfilingRunIndex + 1;
|
const nextIndex = currentProfilingRunIndex + 1;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export const sleep = async (ms: number) =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
35
packages/twenty-front/src/utils/__tests__/sleep.test.ts
Normal file
35
packages/twenty-front/src/utils/__tests__/sleep.test.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { sleep } from '~/utils/sleep';
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
describe('sleep', () => {
|
||||||
|
it('waits the provided number of milliseconds', async () => {
|
||||||
|
const spy = jest.fn();
|
||||||
|
const promise = sleep(1000).then(spy);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(999);
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
jest.advanceTimersByTime(1);
|
||||||
|
await promise; // let queued promises execute
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('call callback after the wait', async () => {
|
||||||
|
const spy = jest.fn();
|
||||||
|
let increment = 1;
|
||||||
|
const callback = jest.fn((resolve) => {
|
||||||
|
increment += 1;
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
const promise = sleep(1000, callback).then(spy);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(999);
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
expect(callback).not.toHaveBeenCalled();
|
||||||
|
expect(increment).toEqual(1);
|
||||||
|
jest.advanceTimersByTime(1);
|
||||||
|
await promise; // let queued promises execute
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
|
expect(increment).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
8
packages/twenty-front/src/utils/sleep.ts
Normal file
8
packages/twenty-front/src/utils/sleep.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export const sleep = async (
|
||||||
|
ms: number,
|
||||||
|
callback?: (resolve: (value: any) => void) => void,
|
||||||
|
) =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
const handler = callback ? () => callback(resolve) : resolve;
|
||||||
|
setTimeout(handler, ms);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user