diff --git a/static/app/components/codecov/datePicker/datePicker.spec.tsx b/static/app/components/codecov/datePicker/datePicker.spec.tsx new file mode 100644 index 00000000000000..c032d38ce5b6b0 --- /dev/null +++ b/static/app/components/codecov/datePicker/datePicker.spec.tsx @@ -0,0 +1,145 @@ +import {initializeOrg} from 'sentry-test/initializeOrg'; +import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; + +import {initializeUrlState} from 'sentry/actionCreators/pageFilters'; +import {DatePicker} from 'sentry/components/codecov/datePicker/datePicker'; +import OrganizationStore from 'sentry/stores/organizationStore'; +import PageFiltersStore from 'sentry/stores/pageFiltersStore'; + +const {organization, router} = initializeOrg({ + router: { + location: { + query: {}, + pathname: '/codecov/tests', + }, + params: {}, + }, +}); + +describe('DatePicker', function () { + beforeEach(() => { + PageFiltersStore.init(); + OrganizationStore.init(); + + OrganizationStore.onUpdate(organization, {replace: true}); + PageFiltersStore.onInitializeUrlState( + { + projects: [], + environments: [], + datetime: { + period: '7d', + start: null, + end: null, + utc: false, + }, + }, + new Set(['datetime']) + ); + }); + + it('can change period', async function () { + render(, {router}); + + await userEvent.click(screen.getByRole('button', {name: '7D', expanded: false})); + await userEvent.click(screen.getByRole('option', {name: 'Last 30 days'})); + + expect( + screen.getByRole('button', {name: '30D', expanded: false}) + ).toBeInTheDocument(); + expect(router.push).toHaveBeenCalledWith( + expect.objectContaining({query: {statsPeriod: '30d'}}) + ); + expect(PageFiltersStore.getState()).toEqual({ + isReady: true, + shouldPersist: true, + desyncedFilters: new Set(), + pinnedFilters: new Set(['datetime']), + selection: { + datetime: { + period: '30d', + end: null, + start: null, + utc: false, + }, + environments: [], + projects: [], + }, + }); + }); + + it('adjusts period if invalid', async function () { + PageFiltersStore.reset(); + PageFiltersStore.onInitializeUrlState( + { + projects: [], + environments: [], + datetime: { + period: '123d', + start: null, + end: null, + utc: false, + }, + }, + new Set(['datetime']) + ); + + render(, {router}); + + // Confirm selection changed to default Codecov period + const button = await screen.findByRole('button', {name: '24H', expanded: false}); + expect(button).toBeInTheDocument(); + expect(router.push).toHaveBeenCalledWith( + expect.objectContaining({query: {statsPeriod: '24h'}}) + ); + expect(PageFiltersStore.getState()).toEqual({ + isReady: true, + shouldPersist: true, + desyncedFilters: new Set(), + pinnedFilters: new Set(['datetime']), + selection: { + datetime: { + period: '24h', + end: null, + start: null, + utc: false, + }, + environments: [], + projects: [], + }, + }); + }); + + it('displays a desynced state message', async function () { + const {organization: desyncOrganization, router: desyncRouter} = initializeOrg({ + router: { + location: { + query: {statsPeriod: '7d'}, + pathname: '/codecov/test', + }, + params: {}, + }, + }); + + PageFiltersStore.reset(); + initializeUrlState({ + memberProjects: [], + nonMemberProjects: [], + organization: desyncOrganization, + queryParams: {statsPeriod: '30d'}, + router: desyncRouter, + shouldEnforceSingleProject: false, + }); + + render(, { + router: desyncRouter, + organization: desyncOrganization, + }); + + await userEvent.click(screen.getByRole('button', {name: '30D', expanded: false})); + expect(screen.getByText('Filters Updated')).toBeInTheDocument(); + expect( + screen.getByRole('button', {name: 'Restore Previous Values'}) + ).toBeInTheDocument(); + expect(screen.getByRole('button', {name: 'Got It'})).toBeInTheDocument(); + }); +}); diff --git a/static/app/components/codecov/datePicker.tsx b/static/app/components/codecov/datePicker/datePicker.tsx similarity index 85% rename from static/app/components/codecov/datePicker.tsx rename to static/app/components/codecov/datePicker/datePicker.tsx index 226701ec6e76d2..dc6f35fc9a807a 100644 --- a/static/app/components/codecov/datePicker.tsx +++ b/static/app/components/codecov/datePicker/datePicker.tsx @@ -1,14 +1,14 @@ import {useEffect} from 'react'; import {updateDateTime} from 'sentry/actionCreators/pageFilters'; -import type {DateSelectorProps} from 'sentry/components/codecov/dateSelector'; -import {DateSelector} from 'sentry/components/codecov/dateSelector'; +import type {DateSelectorProps} from 'sentry/components/codecov/datePicker/dateSelector'; +import {DateSelector} from 'sentry/components/codecov/datePicker/dateSelector'; import {DesyncedFilterMessage} from 'sentry/components/organizations/pageFilters/desyncedFilter'; import {t} from 'sentry/locale'; import usePageFilters from 'sentry/utils/usePageFilters'; import useRouter from 'sentry/utils/useRouter'; -import {isValidCodecovRelativePeriod} from './utils'; +import {isValidCodecovRelativePeriod} from '../utils'; const CODECOV_DEFAULT_RELATIVE_PERIOD = '24h'; export const CODECOV_DEFAULT_RELATIVE_PERIODS = { @@ -32,7 +32,7 @@ export function DatePicker({ const desynced = desyncedFilters.has('datetime'); const period = selection.datetime?.period; - // Adjusts to valid Codecov relative period + // Adjusts to valid Codecov relative period since Codecov only accepts a subset of dates other components accept, defined in CODECOV_DEFAULT_RELATIVE_PERIODS useEffect(() => { if (!isValidCodecovRelativePeriod(period)) { const newTimePeriod = {period: CODECOV_DEFAULT_RELATIVE_PERIOD}; diff --git a/static/app/components/codecov/datePicker/dateSelector.spec.tsx b/static/app/components/codecov/datePicker/dateSelector.spec.tsx new file mode 100644 index 00000000000000..f2a0be2fa9b87a --- /dev/null +++ b/static/app/components/codecov/datePicker/dateSelector.spec.tsx @@ -0,0 +1,17 @@ +import {render, screen} from 'sentry-test/reactTestingLibrary'; + +import {DateSelector} from 'sentry/components/codecov/datePicker/dateSelector'; + +describe('DateSelector', function () { + it('renders when given relative period', async function () { + render(); + expect(await screen.findByRole('button', {name: '7D'})).toBeInTheDocument(); + }); + + it('renders when given an invalid relative period', async function () { + render(); + expect( + await screen.findByRole('button', {name: 'Invalid Period'}) + ).toBeInTheDocument(); + }); +}); diff --git a/static/app/components/codecov/dateSelector.tsx b/static/app/components/codecov/datePicker/dateSelector.tsx similarity index 100% rename from static/app/components/codecov/dateSelector.tsx rename to static/app/components/codecov/datePicker/dateSelector.tsx diff --git a/static/app/components/codecov/utils.spec.tsx b/static/app/components/codecov/utils.spec.tsx new file mode 100644 index 00000000000000..187470d6f4bf1e --- /dev/null +++ b/static/app/components/codecov/utils.spec.tsx @@ -0,0 +1,16 @@ +import {isValidCodecovRelativePeriod} from 'sentry/components/codecov/utils'; + +describe('isValidCodecovRelativePeriod', function () { + it('returns false for null relative periods', function () { + const period = null; + expect(isValidCodecovRelativePeriod(period)).toBe(false); + }); + it('returns false for periods not belonging to the Codecov default relative periods', function () { + const period = '123d'; + expect(isValidCodecovRelativePeriod(period)).toBe(false); + }); + it('returns true for a valid relative period', function () { + const period = '7d'; + expect(isValidCodecovRelativePeriod(period)).toBe(true); + }); +}); diff --git a/static/app/components/codecov/utils.tsx b/static/app/components/codecov/utils.tsx index f6d28e18531fe2..9c82455c27c47d 100644 --- a/static/app/components/codecov/utils.tsx +++ b/static/app/components/codecov/utils.tsx @@ -1,4 +1,6 @@ -import {CODECOV_DEFAULT_RELATIVE_PERIODS} from './datePicker'; +import {CODECOV_DEFAULT_RELATIVE_PERIODS} from './datePicker/datePicker'; + +// Date Picker Utils Start /** * Determines if a period is valid for a Codecov DatePicker component. A period is invalid if @@ -15,3 +17,5 @@ export function isValidCodecovRelativePeriod(period: string | null): boolean { return true; } + +// Date Picker Utils End diff --git a/static/app/views/codecov/tests/tests.tsx b/static/app/views/codecov/tests/tests.tsx index 6d6e2e317a2d65..e104058370f27c 100644 --- a/static/app/views/codecov/tests/tests.tsx +++ b/static/app/views/codecov/tests/tests.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import {DatePicker} from 'sentry/components/codecov/datePicker'; +import {DatePicker} from 'sentry/components/codecov/datePicker/datePicker'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {space} from 'sentry/styles/space';