mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-22 16:01:33 +03:00
feat(core): add sign out confirm modal (#4592)
This commit is contained in:
parent
c1d386d932
commit
07b5d18441
@ -11,6 +11,7 @@ export const openWorkspacesModalAtom = atom(false);
|
|||||||
export const openCreateWorkspaceModalAtom = atom<CreateWorkspaceMode>(false);
|
export const openCreateWorkspaceModalAtom = atom<CreateWorkspaceMode>(false);
|
||||||
export const openQuickSearchModalAtom = atom(false);
|
export const openQuickSearchModalAtom = atom(false);
|
||||||
export const openOnboardingModalAtom = atom(false);
|
export const openOnboardingModalAtom = atom(false);
|
||||||
|
export const openSignOutModalAtom = atom(false);
|
||||||
|
|
||||||
export type SettingAtom = Pick<SettingProps, 'activeTab' | 'workspaceId'> & {
|
export type SettingAtom = Pick<SettingProps, 'activeTab' | 'workspaceId'> & {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -23,10 +23,8 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import { authAtom } from '../../../../atoms';
|
import { authAtom, openSignOutModalAtom } from '../../../../atoms';
|
||||||
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
||||||
import { useNavigateHelper } from '../../../../hooks/use-navigate-helper';
|
|
||||||
import { signOutCloud } from '../../../../utils/cloud-utils';
|
|
||||||
import { Upload } from '../../../pure/file-upload';
|
import { Upload } from '../../../pure/file-upload';
|
||||||
import * as style from './style.css';
|
import * as style from './style.css';
|
||||||
|
|
||||||
@ -168,8 +166,8 @@ const StoragePanel = () => {
|
|||||||
export const AccountSetting: FC = () => {
|
export const AccountSetting: FC = () => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const user = useCurrentUser();
|
const user = useCurrentUser();
|
||||||
const { jumpToIndex } = useNavigateHelper();
|
|
||||||
const setAuthModal = useSetAtom(authAtom);
|
const setAuthModal = useSetAtom(authAtom);
|
||||||
|
const setSignOutModal = useSetAtom(openSignOutModalAtom);
|
||||||
|
|
||||||
const onChangeEmail = useCallback(() => {
|
const onChangeEmail = useCallback(() => {
|
||||||
setAuthModal({
|
setAuthModal({
|
||||||
@ -189,6 +187,10 @@ export const AccountSetting: FC = () => {
|
|||||||
});
|
});
|
||||||
}, [setAuthModal, user.email, user.hasPassword]);
|
}, [setAuthModal, user.email, user.hasPassword]);
|
||||||
|
|
||||||
|
const onOpenSignOutModal = useCallback(() => {
|
||||||
|
setSignOutModal(true);
|
||||||
|
}, [setSignOutModal]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingHeader
|
<SettingHeader
|
||||||
@ -220,13 +222,7 @@ export const AccountSetting: FC = () => {
|
|||||||
desc={t['com.affine.setting.sign.out.message']()}
|
desc={t['com.affine.setting.sign.out.message']()}
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
data-testid="sign-out-button"
|
data-testid="sign-out-button"
|
||||||
onClick={useCallback(() => {
|
onClick={onOpenSignOutModal}
|
||||||
signOutCloud()
|
|
||||||
.then(() => {
|
|
||||||
jumpToIndex();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}, [jumpToIndex])}
|
|
||||||
>
|
>
|
||||||
<ArrowRightSmallIcon />
|
<ArrowRightSmallIcon />
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
|
46
apps/core/src/components/affine/sign-out-modal/index.tsx
Normal file
46
apps/core/src/components/affine/sign-out-modal/index.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
|
import {
|
||||||
|
ConfirmModal,
|
||||||
|
type ConfirmModalProps,
|
||||||
|
} from '@toeverything/components/modal';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
type SignOutConfirmModalI18NKeys =
|
||||||
|
| 'title'
|
||||||
|
| 'description'
|
||||||
|
| 'cancel'
|
||||||
|
| 'confirm';
|
||||||
|
|
||||||
|
export const SignOutModal = ({ ...props }: ConfirmModalProps) => {
|
||||||
|
const { title, description, cancelText, confirmButtonOptions = {} } = props;
|
||||||
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
|
const defaultTexts = useMemo(() => {
|
||||||
|
const getDefaultText = (key: SignOutConfirmModalI18NKeys) => {
|
||||||
|
return t[`com.affine.auth.sign-out.confirm-modal.${key}`]();
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
title: getDefaultText('title'),
|
||||||
|
description: getDefaultText('description'),
|
||||||
|
cancelText: getDefaultText('cancel'),
|
||||||
|
children: getDefaultText('confirm'),
|
||||||
|
};
|
||||||
|
}, [t]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmModal
|
||||||
|
title={title ?? defaultTexts.title}
|
||||||
|
description={description ?? defaultTexts.description}
|
||||||
|
cancelText={cancelText ?? defaultTexts.cancelText}
|
||||||
|
confirmButtonOptions={{
|
||||||
|
type: 'error',
|
||||||
|
['data-testid' as string]: 'confirm-sign-out-button',
|
||||||
|
children: confirmButtonOptions.children ?? defaultTexts.children,
|
||||||
|
}}
|
||||||
|
contentOptions={{
|
||||||
|
['data-testid' as string]: 'confirm-sign-out-modal',
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -10,15 +10,15 @@ import { Menu, MenuIcon, MenuItem } from '@toeverything/components/menu';
|
|||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { openSettingModalAtom } from '../../../../../atoms';
|
import {
|
||||||
import { signOutCloud } from '../../../../../utils/cloud-utils';
|
openSettingModalAtom,
|
||||||
import { useNavigateHelper } from '../.././../../../hooks/use-navigate-helper';
|
openSignOutModalAtom,
|
||||||
|
} from '../../../../../atoms';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
||||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||||
|
const setOpenSignOutModalAtom = useSetAtom(openSignOutModalAtom);
|
||||||
const { jumpToIndex } = useNavigateHelper();
|
|
||||||
|
|
||||||
const onOpenAccountSetting = useCallback(() => {
|
const onOpenAccountSetting = useCallback(() => {
|
||||||
setSettingModalAtom(prev => ({
|
setSettingModalAtom(prev => ({
|
||||||
@ -28,14 +28,10 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
|||||||
}));
|
}));
|
||||||
}, [setSettingModalAtom]);
|
}, [setSettingModalAtom]);
|
||||||
|
|
||||||
const onSignOut = useCallback(async () => {
|
const onOpenSignOutModal = useCallback(() => {
|
||||||
signOutCloud()
|
|
||||||
.then(() => {
|
|
||||||
jumpToIndex();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
}, [onEventEnd, jumpToIndex]);
|
setOpenSignOutModalAtom(true);
|
||||||
|
}, [onEventEnd, setOpenSignOutModalAtom]);
|
||||||
|
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
@ -47,7 +43,7 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
|||||||
<AccountIcon />
|
<AccountIcon />
|
||||||
</MenuIcon>
|
</MenuIcon>
|
||||||
}
|
}
|
||||||
data-testid="editor-option-menu-import"
|
data-testid="workspace-modal-account-settings-option"
|
||||||
onClick={onOpenAccountSetting}
|
onClick={onOpenAccountSetting}
|
||||||
>
|
>
|
||||||
{t['com.affine.workspace.cloud.account.settings']()}
|
{t['com.affine.workspace.cloud.account.settings']()}
|
||||||
@ -59,8 +55,8 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
|||||||
<SignOutIcon />
|
<SignOutIcon />
|
||||||
</MenuIcon>
|
</MenuIcon>
|
||||||
}
|
}
|
||||||
data-testid="editor-option-menu-import"
|
data-testid="workspace-modal-sign-out-option"
|
||||||
onClick={onSignOut}
|
onClick={onOpenSignOutModal}
|
||||||
>
|
>
|
||||||
{t['com.affine.workspace.cloud.account.logout']()}
|
{t['com.affine.workspace.cloud.account.logout']()}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -86,7 +82,7 @@ export const UserAccountItem = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
data-testid="more-button"
|
data-testid="workspace-modal-account-option"
|
||||||
icon={<MoreHorizontalIcon />}
|
icon={<MoreHorizontalIcon />}
|
||||||
type="plain"
|
type="plain"
|
||||||
/>
|
/>
|
||||||
|
@ -2,36 +2,52 @@ import { NotFoundPage } from '@affine/component/not-found-page';
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { useSession } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import { SignOutModal } from '../components/affine/sign-out-modal';
|
||||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||||
import { signOutCloud } from '../utils/cloud-utils';
|
import { signOutCloud } from '../utils/cloud-utils';
|
||||||
|
|
||||||
export const Component = (): ReactElement => {
|
export const Component = (): ReactElement => {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const { jumpToIndex } = useNavigateHelper();
|
const { jumpToIndex } = useNavigateHelper();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const handleBackButtonClick = useCallback(
|
const handleBackButtonClick = useCallback(
|
||||||
() => jumpToIndex(RouteLogic.REPLACE),
|
() => jumpToIndex(RouteLogic.REPLACE),
|
||||||
[jumpToIndex]
|
[jumpToIndex]
|
||||||
);
|
);
|
||||||
const handleSignOut = useCallback(async () => {
|
|
||||||
|
const handleOpenSignOutModal = useCallback(() => {
|
||||||
|
setOpen(true);
|
||||||
|
}, [setOpen]);
|
||||||
|
|
||||||
|
const onConfirmSignOut = useCallback(async () => {
|
||||||
|
setOpen(false);
|
||||||
await signOutCloud({
|
await signOutCloud({
|
||||||
callbackUrl: '/signIn',
|
callbackUrl: '/signIn',
|
||||||
});
|
});
|
||||||
}, []);
|
}, [setOpen]);
|
||||||
return (
|
return (
|
||||||
<NotFoundPage
|
<>
|
||||||
user={
|
<NotFoundPage
|
||||||
session?.user
|
user={
|
||||||
? {
|
session?.user
|
||||||
name: session.user.name || '',
|
? {
|
||||||
email: session.user.email || '',
|
name: session.user.name || '',
|
||||||
avatar: session.user.image || '',
|
email: session.user.email || '',
|
||||||
}
|
avatar: session.user.image || '',
|
||||||
: null
|
}
|
||||||
}
|
: null
|
||||||
onBack={handleBackButtonClick}
|
}
|
||||||
onSignOut={handleSignOut}
|
onBack={handleBackButtonClick}
|
||||||
/>
|
onSignOut={handleOpenSignOutModal}
|
||||||
|
/>
|
||||||
|
<SignOutModal
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
onConfirm={onConfirmSignOut}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,9 +10,11 @@ import {
|
|||||||
openCreateWorkspaceModalAtom,
|
openCreateWorkspaceModalAtom,
|
||||||
openDisableCloudAlertModalAtom,
|
openDisableCloudAlertModalAtom,
|
||||||
openSettingModalAtom,
|
openSettingModalAtom,
|
||||||
|
openSignOutModalAtom,
|
||||||
} from '../atoms';
|
} from '../atoms';
|
||||||
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
||||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||||
|
import { signOutCloud } from '../utils/cloud-utils';
|
||||||
|
|
||||||
const SettingModal = lazy(() =>
|
const SettingModal = lazy(() =>
|
||||||
import('../components/affine/setting-modal').then(module => ({
|
import('../components/affine/setting-modal').then(module => ({
|
||||||
@ -45,6 +47,12 @@ const OnboardingModal = lazy(() =>
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const SignOutModal = lazy(() =>
|
||||||
|
import('../components/affine/sign-out-modal').then(module => ({
|
||||||
|
default: module.SignOutModal,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
export const Setting = () => {
|
export const Setting = () => {
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const [{ open, workspaceId, activeTab }, setOpenSettingModalAtom] =
|
const [{ open, workspaceId, activeTab }, setOpenSettingModalAtom] =
|
||||||
@ -141,6 +149,24 @@ export function CurrentWorkspaceModals() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SignOutConfirmModal = () => {
|
||||||
|
const { jumpToIndex } = useNavigateHelper();
|
||||||
|
const [open, setOpen] = useAtom(openSignOutModalAtom);
|
||||||
|
|
||||||
|
const onConfirm = useCallback(async () => {
|
||||||
|
setOpen(false);
|
||||||
|
signOutCloud()
|
||||||
|
.then(() => {
|
||||||
|
jumpToIndex();
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}, [jumpToIndex, setOpen]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SignOutModal open={open} onOpenChange={setOpen} onConfirm={onConfirm} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const AllWorkspaceModals = (): ReactElement => {
|
export const AllWorkspaceModals = (): ReactElement => {
|
||||||
const [isOpenCreateWorkspaceModal, setOpenCreateWorkspaceModal] = useAtom(
|
const [isOpenCreateWorkspaceModal, setOpenCreateWorkspaceModal] = useAtom(
|
||||||
openCreateWorkspaceModalAtom
|
openCreateWorkspaceModalAtom
|
||||||
@ -172,6 +198,9 @@ export const AllWorkspaceModals = (): ReactElement => {
|
|||||||
<Suspense>
|
<Suspense>
|
||||||
<AuthModal />
|
<AuthModal />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
<Suspense>
|
||||||
|
<SignOutConfirmModal />
|
||||||
|
</Suspense>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,7 @@ const LocalShareMenu = (props: ShareMenuProps) => {
|
|||||||
items={<ShareMenuContent {...props} />}
|
items={<ShareMenuContent {...props} />}
|
||||||
contentOptions={{
|
contentOptions={{
|
||||||
className: styles.menuStyle,
|
className: styles.menuStyle,
|
||||||
|
['data-testid' as string]: 'local-share-menu',
|
||||||
}}
|
}}
|
||||||
rootOptions={{
|
rootOptions={{
|
||||||
modal: false,
|
modal: false,
|
||||||
@ -81,6 +82,7 @@ const CloudShareMenu = (props: ShareMenuProps) => {
|
|||||||
items={<ShareMenuContent {...props} />}
|
items={<ShareMenuContent {...props} />}
|
||||||
contentOptions={{
|
contentOptions={{
|
||||||
className: styles.menuStyle,
|
className: styles.menuStyle,
|
||||||
|
['data-testid' as string]: 'cloud-share-menu',
|
||||||
}}
|
}}
|
||||||
rootOptions={{
|
rootOptions={{
|
||||||
modal: false,
|
modal: false,
|
||||||
|
@ -633,5 +633,9 @@
|
|||||||
"com.affine.share-menu.publish-to-web.description": "Let anyone with a link view a read-only version of this page.",
|
"com.affine.share-menu.publish-to-web.description": "Let anyone with a link view a read-only version of this page.",
|
||||||
"com.affine.share-menu.share-privately": "Share Privately",
|
"com.affine.share-menu.share-privately": "Share Privately",
|
||||||
"com.affine.share-menu.share-privately.description": "Only members of this Workspace can open this link.",
|
"com.affine.share-menu.share-privately.description": "Only members of this Workspace can open this link.",
|
||||||
"com.affine.share-menu.copy-private-link": "Copy Private Link"
|
"com.affine.share-menu.copy-private-link": "Copy Private Link",
|
||||||
|
"com.affine.auth.sign-out.confirm-modal.title": "Sign out?",
|
||||||
|
"com.affine.auth.sign-out.confirm-modal.description": "After signing out, the Cloud Workspaces associated with this account will be removed from the current device, and signing in again will add them back.",
|
||||||
|
"com.affine.auth.sign-out.confirm-modal.cancel": "Cancel",
|
||||||
|
"com.affine.auth.sign-out.confirm-modal.confirm": "Sign Out"
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
} from '@affine-test/kit/utils/setting';
|
} from '@affine-test/kit/utils/setting';
|
||||||
import {
|
import {
|
||||||
clickSideBarAllPageButton,
|
clickSideBarAllPageButton,
|
||||||
|
clickSideBarCurrentWorkspaceBanner,
|
||||||
clickSideBarSettingButton,
|
clickSideBarSettingButton,
|
||||||
} from '@affine-test/kit/utils/sidebar';
|
} from '@affine-test/kit/utils/sidebar';
|
||||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||||
@ -189,6 +190,7 @@ test.describe('collaboration', () => {
|
|||||||
await clickSideBarSettingButton(page);
|
await clickSideBarSettingButton(page);
|
||||||
await clickUserInfoCard(page);
|
await clickUserInfoCard(page);
|
||||||
await page.getByTestId('sign-out-button').click();
|
await page.getByTestId('sign-out-button').click();
|
||||||
|
await page.getByTestId('confirm-sign-out-button').click();
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
expect(page.url()).toBe(url);
|
expect(page.url()).toBe(url);
|
||||||
});
|
});
|
||||||
@ -260,3 +262,26 @@ test.describe('collaboration members', () => {
|
|||||||
expect(await page.locator('[data-testid="member-item"]').count()).toBe(3);
|
expect(await page.locator('[data-testid="member-item"]').count()).toBe(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.describe('sign out', () => {
|
||||||
|
test('can sign out', async ({ page }) => {
|
||||||
|
await page.reload();
|
||||||
|
await waitForEditorLoad(page);
|
||||||
|
await createLocalWorkspace(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
page
|
||||||
|
);
|
||||||
|
await clickSideBarAllPageButton(page);
|
||||||
|
const currentUrl = page.url();
|
||||||
|
await clickSideBarCurrentWorkspaceBanner(page);
|
||||||
|
await page.getByTestId('workspace-modal-account-option').click();
|
||||||
|
await page.getByTestId('workspace-modal-sign-out-option').click();
|
||||||
|
await page.getByTestId('confirm-sign-out-button').click();
|
||||||
|
await clickSideBarCurrentWorkspaceBanner(page);
|
||||||
|
const signInButton = page.getByTestId('cloud-signin-button');
|
||||||
|
await expect(signInButton).toBeVisible();
|
||||||
|
expect(page.url()).toBe(currentUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -2,7 +2,10 @@ import { platform } from 'node:os';
|
|||||||
|
|
||||||
import { test } from '@affine-test/kit/electron';
|
import { test } from '@affine-test/kit/electron';
|
||||||
import { getBlockSuiteEditorTitle } from '@affine-test/kit/utils/page-logic';
|
import { getBlockSuiteEditorTitle } from '@affine-test/kit/utils/page-logic';
|
||||||
import { clickSideBarSettingButton } from '@affine-test/kit/utils/sidebar';
|
import {
|
||||||
|
clickSideBarCurrentWorkspaceBanner,
|
||||||
|
clickSideBarSettingButton,
|
||||||
|
} from '@affine-test/kit/utils/sidebar';
|
||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
test('new page', async ({ page, workspace }) => {
|
test('new page', async ({ page, workspace }) => {
|
||||||
@ -156,7 +159,7 @@ test('windows only check', async ({ page }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('delete workspace', async ({ page }) => {
|
test('delete workspace', async ({ page }) => {
|
||||||
await page.getByTestId('current-workspace').click();
|
await clickSideBarCurrentWorkspaceBanner(page);
|
||||||
await page.getByTestId('new-workspace').click();
|
await page.getByTestId('new-workspace').click();
|
||||||
await page
|
await page
|
||||||
.getByTestId('create-workspace-input')
|
.getByTestId('create-workspace-input')
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import { test } from '@affine-test/kit/electron';
|
import { test } from '@affine-test/kit/electron';
|
||||||
|
import { clickSideBarCurrentWorkspaceBanner } from '@affine-test/kit/utils/sidebar';
|
||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ test.fixme('export then add', async ({ page, appInfo, workspace }) => {
|
|||||||
// add workspace
|
// add workspace
|
||||||
// we are reusing the same db file so that we don't need to maintain one
|
// we are reusing the same db file so that we don't need to maintain one
|
||||||
// in the codebase
|
// in the codebase
|
||||||
await page.getByTestId('current-workspace').click();
|
await clickSideBarCurrentWorkspaceBanner(page);
|
||||||
await page.getByTestId('add-or-new-workspace').click();
|
await page.getByTestId('add-or-new-workspace').click();
|
||||||
|
|
||||||
await page.evaluate(tmpPath => {
|
await page.evaluate(tmpPath => {
|
||||||
|
@ -7,7 +7,7 @@ test('goto not found page', async ({ page }) => {
|
|||||||
await openHomePage(page);
|
await openHomePage(page);
|
||||||
await waitForEditorLoad(page);
|
await waitForEditorLoad(page);
|
||||||
const currentUrl = page.url();
|
const currentUrl = page.url();
|
||||||
const invalidUrl = currentUrl.replace('hello-world', 'invalid');
|
const invalidUrl = currentUrl.concat('invalid');
|
||||||
await page.goto(invalidUrl);
|
await page.goto(invalidUrl);
|
||||||
await expect(page.getByTestId('not-found')).toBeVisible({
|
await expect(page.getByTestId('not-found')).toBeVisible({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
@ -9,7 +9,12 @@ import {
|
|||||||
} from '@affine-test/kit/utils/sidebar';
|
} from '@affine-test/kit/utils/sidebar';
|
||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
import { hash } from '@node-rs/argon2';
|
import { hash } from '@node-rs/argon2';
|
||||||
import type { BrowserContext, Cookie, Page } from '@playwright/test';
|
import {
|
||||||
|
type BrowserContext,
|
||||||
|
type Cookie,
|
||||||
|
expect,
|
||||||
|
type Page,
|
||||||
|
} from '@playwright/test';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export async function getCurrentMailMessageCount() {
|
export async function getCurrentMailMessageCount() {
|
||||||
@ -176,8 +181,33 @@ export async function enableCloudWorkspace(page: Page) {
|
|||||||
await waitForEditorLoad(page);
|
await waitForEditorLoad(page);
|
||||||
await clickNewPageButton(page);
|
await clickNewPageButton(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function enableCloudWorkspaceFromShareButton(page: Page) {
|
export async function enableCloudWorkspaceFromShareButton(page: Page) {
|
||||||
await page.getByTestId('local-share-menu-button').click();
|
const shareMenuButton = page.getByTestId('local-share-menu-button');
|
||||||
|
expect(await shareMenuButton.isVisible()).toBeTruthy();
|
||||||
|
|
||||||
|
// FIXME: this is a workaround for the flaky test
|
||||||
|
// For unknown reasons,
|
||||||
|
// the online ci test on GitHub is unable to detect the local-share-menu,
|
||||||
|
// although it works fine in local testing.
|
||||||
|
// To ensure the tests pass consistently, I’ve made the following temporary adjustments.
|
||||||
|
// {
|
||||||
|
const maxAttempts = 5;
|
||||||
|
let attempt = 0;
|
||||||
|
let menuVisible = false;
|
||||||
|
|
||||||
|
while (!menuVisible && attempt < maxAttempts) {
|
||||||
|
try {
|
||||||
|
await shareMenuButton.click();
|
||||||
|
menuVisible = await page.getByTestId('local-share-menu').isVisible();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Attempt ${attempt + 1} failed: ${e}`);
|
||||||
|
attempt += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(menuVisible).toBeTruthy();
|
||||||
|
// }
|
||||||
|
|
||||||
await page.getByTestId('share-menu-enable-affine-cloud-button').click();
|
await page.getByTestId('share-menu-enable-affine-cloud-button').click();
|
||||||
await page.getByTestId('confirm-enable-affine-cloud-button').click();
|
await page.getByTestId('confirm-enable-affine-cloud-button').click();
|
||||||
// wait for upload and delete local workspace
|
// wait for upload and delete local workspace
|
||||||
|
Loading…
Reference in New Issue
Block a user