@remit/web-client 0.0.300 → 0.0.301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/src/auth/amplify-config.ts +2 -3
- package/src/auth/cognito-sign-in.stories.tsx +90 -0
- package/src/auth/email-sign-in.stories.tsx +128 -0
- package/src/components/onboarding/onboarding.stories.tsx +460 -0
- package/src/components/settings/AccountServices.render.test.ts +254 -0
- package/src/components/settings/AccountServices.tsx +181 -0
- package/src/components/settings/AccountServicesCard.stories.tsx +71 -0
- package/src/components/settings/AccountServicesCard.tsx +76 -0
- package/src/components/settings/accounts.stories.tsx +363 -0
- package/src/components/settings/advanced.stories.tsx +162 -0
- package/src/components/settings/appearance.stories.tsx +33 -0
- package/src/components/settings/folders.stories.tsx +89 -0
- package/src/components/settings/self-update.stories.tsx +270 -0
- package/src/components/settings/senders.stories.tsx +155 -0
- package/src/mocks/story-frame/AppStory.tsx +21 -6
- package/src/mocks/story-frame/mail-handlers.ts +69 -7
- package/src/mocks/story-frame/mail-world.ts +22 -4
- package/src/mocks/story-frame/onboarding-handlers.ts +97 -0
- package/src/mocks/story-frame/session.tsx +19 -0
- package/src/routes/settings/-accounts.test.ts +1 -0
- package/src/routes/settings/accounts.tsx +28 -20
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AccountOperationsCreateAccountResponse,
|
|
3
|
+
AccountOperationsTestConnectionResponse,
|
|
4
|
+
MicrosoftOAuthOperationsMicrosoftOAuthStartResponse,
|
|
5
|
+
RemitImapAccountSyncStatusResponse,
|
|
6
|
+
SyncOperationsGetSyncStatusResponse,
|
|
7
|
+
} from "@remit/api-http-client/types.gen.ts";
|
|
8
|
+
import { type HttpHandler, HttpResponse, http } from "msw";
|
|
9
|
+
import { makeAccount } from "@/test-support/fixtures";
|
|
10
|
+
|
|
11
|
+
const API = "/api";
|
|
12
|
+
|
|
13
|
+
export const NEW_ACCOUNT_ID = "acc-new";
|
|
14
|
+
|
|
15
|
+
export type Autoconfig = "found" | "missing" | "slow";
|
|
16
|
+
|
|
17
|
+
export interface OnboardingHandlerOptions {
|
|
18
|
+
autoconfig?: Autoconfig;
|
|
19
|
+
connection?: AccountOperationsTestConnectionResponse;
|
|
20
|
+
createFails?: boolean;
|
|
21
|
+
sync?: Omit<RemitImapAccountSyncStatusResponse, "accountId">;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const autoconfigXml = (domain: string): string => `<?xml version="1.0"?>
|
|
25
|
+
<clientConfig version="1.1">
|
|
26
|
+
<emailProvider id="${domain}">
|
|
27
|
+
<incomingServer type="imap">
|
|
28
|
+
<hostname>mail.${domain}</hostname>
|
|
29
|
+
<port>993</port>
|
|
30
|
+
<socketType>SSL</socketType>
|
|
31
|
+
</incomingServer>
|
|
32
|
+
<outgoingServer type="smtp">
|
|
33
|
+
<hostname>mail.${domain}</hostname>
|
|
34
|
+
<port>465</port>
|
|
35
|
+
<socketType>SSL</socketType>
|
|
36
|
+
</outgoingServer>
|
|
37
|
+
</emailProvider>
|
|
38
|
+
</clientConfig>`;
|
|
39
|
+
|
|
40
|
+
const pending = (): Promise<never> => new Promise<never>(() => undefined);
|
|
41
|
+
|
|
42
|
+
const autoconfigHandlers = (autoconfig: Autoconfig): HttpHandler[] => [
|
|
43
|
+
http.get("https://autoconfig.thunderbird.net/v1.1/:domain", ({ params }) => {
|
|
44
|
+
if (autoconfig === "slow") return pending();
|
|
45
|
+
if (autoconfig === "missing")
|
|
46
|
+
return new HttpResponse(null, { status: 404 });
|
|
47
|
+
return HttpResponse.text(autoconfigXml(String(params.domain)), {
|
|
48
|
+
headers: { "Content-Type": "application/xml" },
|
|
49
|
+
});
|
|
50
|
+
}),
|
|
51
|
+
http.get(
|
|
52
|
+
/^https:\/\/autoconfig\.[^/]+\/mail\/config-v1\.1\.xml$/,
|
|
53
|
+
() => new HttpResponse(null, { status: 404 }),
|
|
54
|
+
),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
export const onboardingHandlers = ({
|
|
58
|
+
autoconfig = "found",
|
|
59
|
+
connection = { imapSuccess: true, smtpSuccess: true },
|
|
60
|
+
createFails = false,
|
|
61
|
+
sync = {
|
|
62
|
+
syncPhase: "complete",
|
|
63
|
+
mailboxCountTotal: 6,
|
|
64
|
+
mailboxCountSynced: 6,
|
|
65
|
+
mailboxes: [],
|
|
66
|
+
},
|
|
67
|
+
}: OnboardingHandlerOptions = {}): HttpHandler[] => [
|
|
68
|
+
...autoconfigHandlers(autoconfig),
|
|
69
|
+
http.post(`${API}/accounts/test-connection`, () =>
|
|
70
|
+
HttpResponse.json<AccountOperationsTestConnectionResponse>(connection),
|
|
71
|
+
),
|
|
72
|
+
http.post(`${API}/accounts`, async ({ request }) => {
|
|
73
|
+
if (createFails) return HttpResponse.error();
|
|
74
|
+
const body: unknown = await request.json();
|
|
75
|
+
const email =
|
|
76
|
+
typeof body === "object" &&
|
|
77
|
+
body !== null &&
|
|
78
|
+
"email" in body &&
|
|
79
|
+
typeof body.email === "string"
|
|
80
|
+
? body.email
|
|
81
|
+
: "alice@northwind.example";
|
|
82
|
+
return HttpResponse.json<AccountOperationsCreateAccountResponse>(
|
|
83
|
+
makeAccount({ accountId: NEW_ACCOUNT_ID, email }),
|
|
84
|
+
);
|
|
85
|
+
}),
|
|
86
|
+
http.get(`${API}/accounts/${NEW_ACCOUNT_ID}/sync/status`, () =>
|
|
87
|
+
HttpResponse.json<SyncOperationsGetSyncStatusResponse>({
|
|
88
|
+
accountId: NEW_ACCOUNT_ID,
|
|
89
|
+
...sync,
|
|
90
|
+
}),
|
|
91
|
+
),
|
|
92
|
+
http.post(`${API}/accounts/oauth/microsoft/start`, () =>
|
|
93
|
+
HttpResponse.json<MicrosoftOAuthOperationsMicrosoftOAuthStartResponse>({
|
|
94
|
+
authorizationUrl: "#microsoft-sign-in",
|
|
95
|
+
}),
|
|
96
|
+
),
|
|
97
|
+
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AuthProvider, noneAuthProvider } from "@/auth/provider";
|
|
2
|
+
|
|
3
|
+
type RuntimeConfig = NonNullable<typeof globalThis.__REMIT_CONFIG__>;
|
|
4
|
+
|
|
5
|
+
export const signedInAs = (email: string): AuthProvider => ({
|
|
6
|
+
...noneAuthProvider,
|
|
7
|
+
Account: ({ children }) => (
|
|
8
|
+
<>{children({ email, signOut: () => undefined })}</>
|
|
9
|
+
),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const withRuntimeConfig =
|
|
13
|
+
(config: RuntimeConfig) => (): (() => void) => {
|
|
14
|
+
const previous = globalThis.__REMIT_CONFIG__;
|
|
15
|
+
globalThis.__REMIT_CONFIG__ = config;
|
|
16
|
+
return () => {
|
|
17
|
+
globalThis.__REMIT_CONFIG__ = previous;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -22,6 +22,7 @@ import { useEffect, useState } from "react";
|
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
import { OnboardingWizard } from "@/components/onboarding/OnboardingWizard";
|
|
24
24
|
import { AccountFormPanel } from "@/components/settings/AccountFormPanel";
|
|
25
|
+
import { AccountServices } from "@/components/settings/AccountServices";
|
|
25
26
|
import { DangerZone } from "@/components/settings/DangerZone";
|
|
26
27
|
import { ErrorState } from "@/components/ui/ErrorState";
|
|
27
28
|
import {
|
|
@@ -482,26 +483,33 @@ function AccountsSettings() {
|
|
|
482
483
|
);
|
|
483
484
|
|
|
484
485
|
return (
|
|
485
|
-
<
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
486
|
+
<div key={account.accountId} className="space-y-2">
|
|
487
|
+
<AccountHealthCard
|
|
488
|
+
label={accountLabel(account)}
|
|
489
|
+
email={account.email}
|
|
490
|
+
connector={isOAuthAccount ? "Microsoft 365" : "IMAP"}
|
|
491
|
+
syncLabel={deriveSyncLabel(account)}
|
|
492
|
+
state={deriveState(account)}
|
|
493
|
+
// What the mail server said, when it said anything. Not every
|
|
494
|
+
// refusal that fences an account is one the Reconnect button
|
|
495
|
+
// clears — "SmtpClientAuthentication is disabled" is a tenant
|
|
496
|
+
// setting — so the stored reason outranks the generic prompt.
|
|
497
|
+
errorDetail={
|
|
498
|
+
isReauth
|
|
499
|
+
? (account.lastError ?? "Re-authentication required")
|
|
500
|
+
: isMissingPassword
|
|
501
|
+
? "Imported from a config file, which carries no password. Enter one to start syncing."
|
|
502
|
+
: account.lastError
|
|
503
|
+
}
|
|
504
|
+
trailing={trailingButton}
|
|
505
|
+
/>
|
|
506
|
+
<AccountServices
|
|
507
|
+
account={account}
|
|
508
|
+
onRemoveAccount={() =>
|
|
509
|
+
setDeletingAccountId(account.accountId)
|
|
510
|
+
}
|
|
511
|
+
/>
|
|
512
|
+
</div>
|
|
505
513
|
);
|
|
506
514
|
})}
|
|
507
515
|
</div>
|