-
Notifications
You must be signed in to change notification settings - Fork 0
[PB-5978]: feat(mail)/frozen account state #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
e081bd6
0b4390a
99d313d
05bbaea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { useGetStorageLimitQuery, useGetStorageUsageQuery } from '@/store/api/storage'; | ||
| import { useGetMailMeQuery } from '@/store/api/mail'; | ||
| import { getDaysUntil } from '@/utils/days-until'; | ||
|
|
||
| export const useSidenavData = () => { | ||
| const { isLoading: isLoadingPlanLimit, data: planLimit = 1 } = useGetStorageLimitQuery(); | ||
| const { isLoading: isLoadingPlanUsage, data: planUsage = 0 } = useGetStorageUsageQuery(); | ||
| const { data: mailMe } = useGetMailMeQuery(); | ||
|
|
||
| const isMailDisabled = mailMe?.status === 'suspended'; | ||
| const daysUntilDeletion = getDaysUntil(mailMe?.deletionAt); | ||
| const storagePercentage = planLimit > 0 ? Math.min((planUsage / planLimit) * 100, 100) : 0; | ||
|
|
||
| return { | ||
| mailMe, | ||
| isMailDisabled, | ||
| daysUntilDeletion, | ||
| planLimit, | ||
| planUsage, | ||
| isLoadingPlanLimit, | ||
| isLoadingPlanUsage, | ||
| storagePercentage, | ||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ import { beforeEach, afterEach, describe, expect, test, vi } from 'vitest'; | |
| import { SdkManager } from '..'; | ||
| import { MailService } from '.'; | ||
| import { getMockedMails, getMockedMailBoxes, getMockedMail } from '@/test-utils/fixtures'; | ||
| import type { SetupMailAccountPayload } from '@internxt/sdk/dist/mail/types'; | ||
| import type { MailAccountResponse, SetupMailAccountPayload } from '@internxt/sdk/dist/mail/types'; | ||
|
|
||
| describe('Mail Service', () => { | ||
| beforeEach(() => { | ||
|
|
@@ -14,6 +14,53 @@ describe('Mail Service', () => { | |
| vi.restoreAllMocks(); | ||
| }); | ||
|
|
||
| describe('Get me', () => { | ||
| test('When fetching the mail account and it is active, then the account should be returned', async () => { | ||
| const mockAccount: MailAccountResponse = { | ||
| id: 'account-1', | ||
| defaultAddress: 'jane@inxt.me', | ||
| status: 'active', | ||
| }; | ||
| const mockMailClient = { | ||
| getMailAccount: vi.fn().mockResolvedValue(mockAccount), | ||
| } as any; | ||
| vi.spyOn(SdkManager.instance, 'getMail').mockReturnValue(mockMailClient); | ||
|
|
||
| const result = await MailService.instance.getMe(); | ||
|
|
||
| expect(result).toStrictEqual(mockAccount); | ||
| expect(mockMailClient.getMailAccount).toHaveBeenCalledOnce(); | ||
| }); | ||
|
|
||
| test('When fetching the mail account and it is suspended, then suspendedAt and deletionAt should be present', async () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using technical descriptions. |
||
| const mockAccount: MailAccountResponse = { | ||
| id: 'account-1', | ||
| defaultAddress: 'jane@inxt.me', | ||
| status: 'suspended', | ||
| suspendedAt: '2026-05-01T00:00:00.000Z', | ||
| deletionAt: '2026-06-01T00:00:00.000Z', | ||
| }; | ||
| const mockMailClient = { | ||
| getMailAccount: vi.fn().mockResolvedValue(mockAccount), | ||
| } as any; | ||
| vi.spyOn(SdkManager.instance, 'getMail').mockReturnValue(mockMailClient); | ||
|
|
||
| const result = await MailService.instance.getMe(); | ||
|
|
||
| expect(result).toStrictEqual(mockAccount); | ||
| }); | ||
|
|
||
| test('When fetching the mail account fails, then an error should be thrown', async () => { | ||
| const unexpectedError = new Error('Unauthorized'); | ||
| const mockMailClient = { | ||
| getMailAccount: vi.fn().mockRejectedValue(unexpectedError), | ||
| } as any; | ||
| vi.spyOn(SdkManager.instance, 'getMail').mockReturnValue(mockMailClient); | ||
|
|
||
| await expect(MailService.instance.getMe()).rejects.toThrow(unexpectedError); | ||
| }); | ||
| }); | ||
|
|
||
| describe('Get mailboxes info', () => { | ||
| test('When fetching mailboxes, then all mailboxes should be returned', async () => { | ||
| const mockedMailboxes = getMockedMailBoxes(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import { | |
| FetchListFolderError, | ||
| FetchMailAccountKeysError, | ||
| FetchMailboxesInfoError, | ||
| FetchMailMeError, | ||
| FetchMessageError, | ||
| MAIL_NOT_SETUP_CODE, | ||
| MailNotSetupError, | ||
|
|
@@ -60,6 +61,45 @@ describe('Mail API', () => { | |
| vi.clearAllMocks(); | ||
| }); | ||
|
|
||
| describe('Get Mail Me', () => { | ||
| test('When fetching the mail account and it is active, then it should return the account data', async () => { | ||
| const mockAccount = { id: 'account-1', defaultAddress: 'jane@inxt.me', status: 'active' as const }; | ||
| vi.spyOn(MailService.instance, 'getMe').mockResolvedValue(mockAccount); | ||
| const store = createTestStore(); | ||
|
|
||
| const result = await store.dispatch(mailApi.endpoints.getMailMe.initiate()); | ||
|
|
||
| expect(result.data).toStrictEqual(mockAccount); | ||
| }); | ||
|
|
||
| test('When fetching the mail account and it is suspended, then it should return the suspended account', async () => { | ||
| const mockAccount = { | ||
| id: 'account-1', | ||
| defaultAddress: 'jane@inxt.me', | ||
| status: 'suspended' as const, | ||
| suspendedAt: '2026-05-01T00:00:00.000Z', | ||
| deletionAt: '2026-06-01T00:00:00.000Z', | ||
| }; | ||
| vi.spyOn(MailService.instance, 'getMe').mockResolvedValue(mockAccount); | ||
| const store = createTestStore(); | ||
|
|
||
| const result = await store.dispatch(mailApi.endpoints.getMailMe.initiate()); | ||
|
|
||
| expect(result.data).toStrictEqual(mockAccount); | ||
| }); | ||
|
|
||
| test('When fetching the mail account fails, then a FetchMailMeError should be returned', async () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use |
||
| vi.spyOn(MailService.instance, 'getMe').mockRejectedValue(new Error('Network error')); | ||
| const castErrorSpy = vi.spyOn(ErrorService.instance, 'castError'); | ||
| const store = createTestStore(); | ||
|
|
||
| const result = await store.dispatch(mailApi.endpoints.getMailMe.initiate()); | ||
|
|
||
| expect(castErrorSpy).toHaveBeenCalledOnce(); | ||
| expect(result.error).toBeInstanceOf(FetchMailMeError); | ||
| }); | ||
| }); | ||
|
|
||
| describe('Get Mailboxes', () => { | ||
| test('When getting the mailboxes, then it should return the list of mailboxes', async () => { | ||
| const mockedMailboxes = getMockedMailBoxes(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀