-
Notifications
You must be signed in to change notification settings - Fork 952
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Share button in zone header (#7240)
* feat: share button in zone header * Wrap share button in feature flag (#7248) * chore: wrap share button in feature flag * chore: address PR comments * refactor: extract feature flag enabled into const --------- Co-authored-by: Cadence <cadence@Cadences-MacBook-Pro.local> * fix: add cypress component test and fix css * chore: add translations & include another cy test * fix: navigator canShare * fix: share abort does not display error toast * chore: add share abort tests * fix: naming convention --------- Co-authored-by: Cadence <cadence@Cadences-MacBook-Pro.local>
- Loading branch information
Showing
10 changed files
with
374 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { ToastProvider } from '@radix-ui/react-toast'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
|
||
import { ShareButton } from './ShareButton'; | ||
|
||
const queryClient = new QueryClient(); | ||
|
||
describe('Share Button', () => { | ||
beforeEach(() => { | ||
cy.intercept('/feature-flags', { | ||
body: { 'share-button': true }, | ||
}); | ||
}); | ||
|
||
it('should display share icon for iOS', () => { | ||
cy.mount( | ||
<QueryClientProvider client={queryClient}> | ||
<ToastProvider> | ||
<ShareButton showIosIcon={true} /> | ||
</ToastProvider> | ||
</QueryClientProvider> | ||
); | ||
cy.get('[data-test-id="iosShareIcon"]').should('be.visible'); | ||
cy.get('[data-test-id="defaultShareIcon"]').should('not.exist'); | ||
}); | ||
|
||
it('should display default share icon', () => { | ||
cy.mount( | ||
<QueryClientProvider client={queryClient}> | ||
<ToastProvider> | ||
<ShareButton showIosIcon={false} /> | ||
</ToastProvider> | ||
</QueryClientProvider> | ||
); | ||
cy.get('[data-test-id="defaultShareIcon"]').should('be.visible'); | ||
cy.get('[data-test-id="iosShareIcon"]').should('not.exist'); | ||
}); | ||
|
||
it('should trigger toast on click', () => { | ||
cy.mount( | ||
<QueryClientProvider client={queryClient}> | ||
<ToastProvider> | ||
<ShareButton showIosIcon={false} /> | ||
</ToastProvider> | ||
</QueryClientProvider> | ||
); | ||
cy.get('[data-test-id="share-btn"]').should('exist'); | ||
cy.get('[data-test-id="toast"]').should('not.exist'); | ||
cy.get('[data-test-id="share-btn"]').click(); | ||
cy.get('[data-testid="toast"]').should('exist'); | ||
}); | ||
|
||
it('should close toast on click', () => { | ||
cy.mount( | ||
<QueryClientProvider client={queryClient}> | ||
<ToastProvider> | ||
<ShareButton showIosIcon={false} /> | ||
</ToastProvider> | ||
</QueryClientProvider> | ||
); | ||
cy.get('[data-test-id="share-btn"]').click(); | ||
cy.get('[data-testid="toast"]').should('be.visible'); | ||
cy.get('[data-testid="toast-dismiss"]').click(); | ||
cy.get('[data-testid="toast"]').should('not.exist'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { ToastProvider } from '@radix-ui/react-toast'; | ||
import { render, screen } from '@testing-library/react'; | ||
import { userEvent } from '@testing-library/user-event'; | ||
import { describe, expect, test } from 'vitest'; | ||
|
||
import { ShareButton } from './ShareButton'; | ||
|
||
const navMocks = vi.hoisted(() => ({ | ||
share: vi.fn(), | ||
canShare: vi.fn(), | ||
clipboard: { | ||
writeText: vi.fn(), | ||
}, | ||
})); | ||
|
||
Object.defineProperty(window.navigator, 'share', { value: navMocks.share }); | ||
Object.defineProperty(window.navigator, 'canShare', { value: navMocks.canShare }); | ||
Object.defineProperty(window.navigator, 'clipboard', { | ||
value: { | ||
writeText: navMocks.clipboard.writeText, | ||
}, | ||
}); | ||
|
||
const mocks = vi.hoisted(() => ({ | ||
isMobile: vi.fn(), | ||
isIos: vi.fn(), | ||
})); | ||
|
||
vi.mock('features/weather-layers/wind-layer/util', () => mocks); | ||
|
||
describe('ShareButton', () => { | ||
afterEach(() => { | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
test('uses navigator if on mobile and can share', async () => { | ||
navMocks.canShare.mockReturnValue(true); | ||
mocks.isMobile.mockReturnValue(true); | ||
render( | ||
<ToastProvider> | ||
<ShareButton /> | ||
</ToastProvider> | ||
); | ||
expect(window.navigator.share).not.toHaveBeenCalled(); | ||
await userEvent.click(screen.getByRole('button')); | ||
expect(window.navigator.share).toHaveBeenCalled(); | ||
}); | ||
|
||
test('does not display error toast on share abort', async () => { | ||
navMocks.canShare.mockReturnValue(true); | ||
mocks.isMobile.mockReturnValue(true); | ||
render( | ||
<ToastProvider> | ||
<ShareButton /> | ||
</ToastProvider> | ||
); | ||
expect(window.navigator.share).not.toHaveBeenCalled(); | ||
await userEvent.click(screen.getByRole('button')); | ||
expect(window.navigator.share).toHaveBeenCalled(); | ||
await userEvent.click(document.body); | ||
expect(screen.queryAllByTestId('toast')).toHaveLength(0); | ||
}); | ||
|
||
test('displays error toast on share error', async () => { | ||
navMocks.canShare.mockReturnValue(true); | ||
navMocks.share.mockRejectedValue(new Error('Error!')); | ||
mocks.isMobile.mockReturnValue(true); | ||
render( | ||
<ToastProvider> | ||
<ShareButton /> | ||
</ToastProvider> | ||
); | ||
expect(window.navigator.share).not.toHaveBeenCalled(); | ||
await userEvent.click(screen.getByRole('button')); | ||
expect(window.navigator.share).toHaveBeenCalled(); | ||
expect(screen.queryAllByTestId('toast')).toHaveLength(1); | ||
}); | ||
|
||
describe('copies to clipboard', () => { | ||
test('if not on mobile', async () => { | ||
navMocks.canShare.mockReturnValue(true); | ||
mocks.isMobile.mockReturnValue(false); | ||
render( | ||
<ToastProvider> | ||
<ShareButton /> | ||
</ToastProvider> | ||
); | ||
expect(window.navigator.clipboard.writeText).not.toHaveBeenCalled(); | ||
await userEvent.click(screen.getByRole('button')); | ||
expect(window.navigator.clipboard.writeText).toHaveBeenCalled(); | ||
expect(window.navigator.share).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('if navigator.share is not available', async () => { | ||
navMocks.canShare.mockReturnValue(false); | ||
mocks.isMobile.mockReturnValue(true); | ||
render( | ||
<ToastProvider> | ||
<ShareButton /> | ||
</ToastProvider> | ||
); | ||
expect(window.navigator.clipboard.writeText).not.toHaveBeenCalled(); | ||
await userEvent.click(screen.getByRole('button')); | ||
expect(window.navigator.clipboard.writeText).toHaveBeenCalled(); | ||
expect(window.navigator.share).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.