diff --git a/src/renderer/components/notifications/NotificationList.visual.test.tsx b/src/renderer/components/notifications/NotificationList.visual.test.tsx index 20d63cfc8..438bc9493 100644 --- a/src/renderer/components/notifications/NotificationList.visual.test.tsx +++ b/src/renderer/components/notifications/NotificationList.visual.test.tsx @@ -188,7 +188,7 @@ describe('notification list in a browser', () => { }); await page.getByTestId(`${kind}-mark-as-read`).first().click(); await waitFor(() => - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( true, ), ); @@ -196,7 +196,9 @@ describe('notification list in a browser', () => { await waitFor(() => expect(document.getElementById('notification-0')).toBeNull()); await scrollToStart(); await waitFor(() => expect(document.getElementById('notification-0')).not.toBeNull()); - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe(true); + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( + true, + ); expect( document .getElementById('notification-0') @@ -207,7 +209,7 @@ describe('notification list in a browser', () => { await pending; }); await waitFor(() => - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( false, ), ); @@ -245,7 +247,7 @@ describe('notification list in a browser', () => { const original = getMockedNotificationsState().notifications; await page.getByTestId(`${kind}-mark-as-read`).first().click(); await waitFor(() => - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( true, ), ); @@ -270,7 +272,7 @@ describe('notification list in a browser', () => { await scrollToStart(); await waitFor(() => expect(document.getElementById('notification-0')).not.toBeNull()); expect(scrollContainer()).toBe(scroller); - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( false, ); expect( @@ -303,8 +305,10 @@ describe('notification list in a browser', () => { }); await waitFor(() => expect(document.getElementById('new-notification')).not.toBeNull()); expect(scrollContainer()).toBe(scroller); - expect(document.getElementById('notification-0')?.classList.contains('opacity-0')).toBe(true); - expect(document.getElementById('new-notification')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('notification-0')?.hasAttribute('data-animating-exit')).toBe( + true, + ); + expect(document.getElementById('new-notification')?.hasAttribute('data-animating-exit')).toBe( false, ); await act(async () => { @@ -316,7 +320,7 @@ describe('notification list in a browser', () => { // oxlint-disable-next-line typescript/await-thenable -- Vitest types omit `expect.element`'s poll promise await expect.element(page.getByTestId('repository-mark-as-read')).toBeVisible(); expect(scrollContainer()).toBe(scroller); - expect(document.getElementById('new-notification')?.classList.contains('opacity-0')).toBe( + expect(document.getElementById('new-notification')?.hasAttribute('data-animating-exit')).toBe( false, ); }); diff --git a/src/renderer/components/notifications/NotificationRow.tsx b/src/renderer/components/notifications/NotificationRow.tsx index a235f2d3d..4eaa3925a 100644 --- a/src/renderer/components/notifications/NotificationRow.tsx +++ b/src/renderer/components/notifications/NotificationRow.tsx @@ -97,6 +97,7 @@ export function NotificationRow({ isAnimatingExit && 'translate-x-full opacity-0 transition duration-350 ease-in-out', isNotificationRead && Opacity.READ, )} + data-animating-exit={isAnimatingExit || undefined} id={notification.id} > diff --git a/src/renderer/routes/Accounts.test.tsx b/src/renderer/routes/Accounts.test.tsx index 5ff682381..9ad3857fd 100644 --- a/src/renderer/routes/Accounts.test.tsx +++ b/src/renderer/routes/Accounts.test.tsx @@ -11,8 +11,6 @@ import { import { useAccountsStore } from '../stores'; -import { IconColor } from '../types'; - import { getAlternateScopeNames, getRecommendedScopeNames, @@ -74,55 +72,41 @@ describe('renderer/routes/Accounts.tsx', () => { { name: 'recommended scopes', scopes: getRecommendedScopeNames(), - color: IconColor.GREEN, variant: 'default', }, { name: 'alternate scopes only', scopes: getAlternateScopeNames(), - color: 'text-gitify-warning', variant: 'default', }, { name: 'neither scope set', scopes: getRequiredScopeNames(), - color: null, variant: 'danger', }, { name: 'both scope sets', scopes: [...new Set([...getRecommendedScopeNames(), ...getAlternateScopeNames()])], - color: IconColor.GREEN, variant: 'default', }, ]; it.each(scopeCases)( 'preserves the icon color and button variant for $name', - async ({ scopes, color, variant }) => { + async ({ scopes, variant }) => { + const account = { ...mockPersonalAccessTokenAccount, scopes }; + await act(async () => { - renderWithProviders(, { - accounts: [{ ...mockPersonalAccessTokenAccount, scopes }], - }); + renderWithProviders(, { accounts: [account] }); }); - const button = screen.getByTestId('account-view-scopes'); - const icon = button.querySelector('svg'); + const button = screen.getByRole('button', { + name: `View scopes for ${account.user?.login}`, + }); - expect(icon).toHaveClass('octicon-shield-check'); + expect(button.querySelector('svg')).toHaveClass('octicon-shield-check'); expect(button).toHaveAttribute('data-variant', variant); expect(button).toHaveAttribute('data-size', 'small'); - expect(button).toHaveAccessibleName( - `View scopes for ${mockPersonalAccessTokenAccount.user?.login}`, - ); - if (color) { - expect(icon).toHaveClass(color); - } - for (const scopeColor of [IconColor.GREEN, 'text-gitify-warning']) { - if (scopeColor !== color) { - expect(icon).not.toHaveClass(scopeColor); - } - } }, ); @@ -135,7 +119,9 @@ describe('renderer/routes/Accounts.tsx', () => { renderWithProviders(, { accounts: [account] }); }); - const icon = screen.getByTestId('account-view-scopes').querySelector('svg'); + const icon = screen + .getByRole('button', { name: `View scopes for ${account.user?.login}` }) + .querySelector('svg'); expect(icon).toBeInTheDocument(); const updatedAccount = { @@ -149,7 +135,11 @@ describe('renderer/routes/Accounts.tsx', () => { }); expect(screen.getByText('Updated account name')).toBeInTheDocument(); - expect(screen.getByTestId('account-view-scopes').querySelector('svg')).toBe(icon); + expect( + screen + .getByRole('button', { name: `View scopes for ${account.user?.login}` }) + .querySelector('svg'), + ).toBe(icon); }, ); @@ -163,9 +153,11 @@ describe('renderer/routes/Accounts.tsx', () => { renderWithProviders(, { accounts: [account] }); }); - const button = screen.getByTestId('account-view-scopes'); + const button = screen.getByRole('button', { + name: `View scopes for ${account.user?.login}`, + }); + expect(button).toHaveAttribute('data-variant', 'danger'); - expect(button.querySelector('svg')).not.toHaveClass(IconColor.GREEN, 'text-gitify-warning'); const updatedAccount = { ...account, scopes: getRecommendedScopeNames() }; expect(getAccountUUID(updatedAccount)).toBe(getAccountUUID(account)); @@ -174,9 +166,10 @@ describe('renderer/routes/Accounts.tsx', () => { useAccountsStore.setState({ accounts: [updatedAccount] }); }); - const updatedButton = screen.getByTestId('account-view-scopes'); - expect(updatedButton.querySelector('svg')).toHaveClass(IconColor.GREEN); - expect(updatedButton.querySelector('svg')).not.toHaveClass('text-gitify-warning'); + const updatedButton = screen.getByRole('button', { + name: `View scopes for ${updatedAccount.user?.login}`, + }); + expect(updatedButton).toHaveAttribute('data-variant', 'default'); await userEvent.click(updatedButton);