Removed references to feature checks for version 2.7

This commit is contained in:
Alejandro Celaya 2022-12-23 21:06:59 +01:00
parent 815e06809a
commit 60fc351344
22 changed files with 71 additions and 168 deletions

View file

@ -4,7 +4,7 @@ import { Button, FormGroup, Input, Row } from 'reactstrap';
import { cond, isEmpty, pipe, replace, trim, T } from 'ramda';
import { parseISO } from 'date-fns';
import { DateTimeInput, DateTimeInputProps } from '../utils/dates/DateTimeInput';
import { supportsCrawlableVisits, supportsForwardQuery } from '../utils/helpers/features';
import { supportsForwardQuery } from '../utils/helpers/features';
import { SimpleCard } from '../utils/SimpleCard';
import { handleEventPreventingDefault, hasValue, OptionalString } from '../utils/utils';
import { Checkbox } from '../utils/Checkbox';
@ -113,16 +113,14 @@ export const ShortUrlForm = (
</>
);
const showCrawlableControl = supportsCrawlableVisits(selectedServer);
const showForwardQueryControl = supportsForwardQuery(selectedServer);
const showBehaviorCard = showCrawlableControl || showForwardQueryControl;
return (
<form name="shortUrlForm" className="short-url-form" onSubmit={submit}>
{isBasicMode && basicComponents}
{!isBasicMode && (
<>
<SimpleCard title="Basic options" className="mb-3">
<SimpleCard title="Main options" className="mb-3">
{basicComponents}
</SimpleCard>
@ -190,30 +188,26 @@ export const ShortUrlForm = (
)}
</SimpleCard>
</div>
{showBehaviorCard && (
<div className="col-sm-6 mb-3">
<SimpleCard title="Configure behavior">
{showCrawlableControl && (
<ShortUrlFormCheckboxGroup
infoTooltip="This short URL will be included in the robots.txt for your Shlink instance, allowing web crawlers (like Google) to index it."
checked={shortUrlData.crawlable}
onChange={(crawlable) => setShortUrlData({ ...shortUrlData, crawlable })}
>
Make it crawlable
</ShortUrlFormCheckboxGroup>
)}
{showForwardQueryControl && (
<ShortUrlFormCheckboxGroup
infoTooltip="When this short URL is visited, any query params appended to it will be forwarded to the long URL."
checked={shortUrlData.forwardQuery}
onChange={(forwardQuery) => setShortUrlData({ ...shortUrlData, forwardQuery })}
>
Forward query params on redirect
</ShortUrlFormCheckboxGroup>
)}
</SimpleCard>
</div>
)}
<div className="col-sm-6 mb-3">
<SimpleCard title="Configure behavior">
<ShortUrlFormCheckboxGroup
infoTooltip="This short URL will be included in the robots.txt for your Shlink instance, allowing web crawlers (like Google) to index it."
checked={shortUrlData.crawlable}
onChange={(crawlable) => setShortUrlData({ ...shortUrlData, crawlable })}
>
Make it crawlable
</ShortUrlFormCheckboxGroup>
{showForwardQueryControl && (
<ShortUrlFormCheckboxGroup
infoTooltip="When this short URL is visited, any query params appended to it will be forwarded to the long URL."
checked={shortUrlData.forwardQuery}
onChange={(forwardQuery) => setShortUrlData({ ...shortUrlData, forwardQuery })}
>
Forward query params on redirect
</ShortUrlFormCheckboxGroup>
)}
</SimpleCard>
</div>
</Row>
</>
)}

View file

@ -8,7 +8,7 @@ import { SearchField } from '../utils/SearchField';
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
import { formatIsoDate } from '../utils/helpers/date';
import { DateRange, datesToDateRange } from '../utils/helpers/dateIntervals';
import { supportsAllTagsFiltering, supportsBotVisits } from '../utils/helpers/features';
import { supportsAllTagsFiltering } from '../utils/helpers/features';
import { SelectedServer } from '../servers/data';
import { OrderDir } from '../utils/helpers/ordering';
import { OrderingDropdown } from '../utils/OrderingDropdown';
@ -47,7 +47,6 @@ export const ShortUrlsFilteringBar = (
);
const changeTagSelection = (selectedTags: string[]) => toFirstPage({ tags: selectedTags });
const canChangeTagsMode = supportsAllTagsFiltering(selectedServer);
const botsSupported = supportsBotVisits(selectedServer);
const toggleTagsMode = pipe(
() => (tagsMode === 'any' ? 'all' : 'any'),
(mode) => toFirstPage({ tagsMode: mode }),
@ -83,7 +82,6 @@ export const ShortUrlsFilteringBar = (
</div>
<ShortUrlsFilterDropdown
className="ms-0 ms-md-2 mt-3 mt-md-0"
botsSupported={botsSupported}
selected={{ excludeBots: excludeBots ?? settings.visits?.excludeBots }}
onChange={toFirstPage}
/>

View file

@ -7,27 +7,18 @@ interface ShortUrlsFilterDropdownProps {
onChange: (filters: ShortUrlsFilter) => void;
selected?: ShortUrlsFilter;
className?: string;
botsSupported: boolean;
}
export const ShortUrlsFilterDropdown = (
{ onChange, selected = {}, className, botsSupported }: ShortUrlsFilterDropdownProps,
{ onChange, selected = {}, className }: ShortUrlsFilterDropdownProps,
) => {
if (!botsSupported) {
return null;
}
const { excludeBots = false } = selected;
const onBotsClick = () => onChange({ ...selected, excludeBots: !selected?.excludeBots });
return (
<DropdownBtn text="Filters" dropdownClassName={className} className="me-3" right minWidth={250}>
{botsSupported && (
<>
<DropdownItem header>Bots:</DropdownItem>
<DropdownItem active={excludeBots} onClick={onBotsClick}>Exclude bots visits</DropdownItem>
</>
)}
<DropdownItem header>Bots:</DropdownItem>
<DropdownItem active={excludeBots} onClick={onBotsClick}>Exclude bots visits</DropdownItem>
<DropdownItem divider />
<DropdownItem disabled={!hasValue(selected)} onClick={() => onChange({ excludeBots: false })}>

View file

@ -4,8 +4,6 @@ import { SemVerPattern, versionMatch } from './version';
const serverMatchesMinVersion = (minVersion: SemVerPattern) => (selectedServer: SelectedServer): boolean =>
isReachableServer(selectedServer) && versionMatch(selectedServer.version, { minVersion });
export const supportsBotVisits = serverMatchesMinVersion('2.7.0');
export const supportsCrawlableVisits = supportsBotVisits;
export const supportsForwardQuery = serverMatchesMinVersion('2.9.0');
export const supportsNonRestCors = supportsForwardQuery;
export const supportsDefaultDomainRedirectsEdition = serverMatchesMinVersion('2.10.0');

View file

@ -22,7 +22,6 @@ export const DomainVisits = ({ exportVisits }: ReportExporter) => boundToMercure
domainVisits,
cancelGetDomainVisits,
settings,
selectedServer,
}: DomainVisitsProps) => {
const goBack = useGoBack();
const { domain = '' } = useParams();
@ -38,7 +37,6 @@ export const DomainVisits = ({ exportVisits }: ReportExporter) => boundToMercure
visitsInfo={domainVisits}
settings={settings}
exportCsv={exportCsv}
selectedServer={selectedServer}
>
<VisitsHeader goBack={goBack} visits={domainVisits.visits} title={`"${authority}" visits`} />
</VisitsStats>

View file

@ -20,7 +20,6 @@ export const NonOrphanVisits = ({ exportVisits }: ReportExporter) => boundToMerc
nonOrphanVisits,
cancelGetNonOrphanVisits,
settings,
selectedServer,
}: NonOrphanVisitsProps) => {
const goBack = useGoBack();
const exportCsv = (visits: NormalizedVisit[]) => exportVisits('non_orphan_visits.csv', visits);
@ -34,7 +33,6 @@ export const NonOrphanVisits = ({ exportVisits }: ReportExporter) => boundToMerc
visitsInfo={nonOrphanVisits}
settings={settings}
exportCsv={exportCsv}
selectedServer={selectedServer}
>
<VisitsHeader title="Non-orphan visits" goBack={goBack} visits={nonOrphanVisits.visits} />
</VisitsStats>

View file

@ -21,7 +21,6 @@ export const OrphanVisits = ({ exportVisits }: ReportExporter) => boundToMercure
orphanVisits,
cancelGetOrphanVisits,
settings,
selectedServer,
}: OrphanVisitsProps) => {
const goBack = useGoBack();
const exportCsv = (visits: NormalizedVisit[]) => exportVisits('orphan_visits.csv', visits);
@ -36,7 +35,6 @@ export const OrphanVisits = ({ exportVisits }: ReportExporter) => boundToMercure
visitsInfo={orphanVisits}
settings={settings}
exportCsv={exportCsv}
selectedServer={selectedServer}
isOrphanVisits
>
<VisitsHeader title="Orphan visits" goBack={goBack} visits={orphanVisits.visits} />

View file

@ -30,7 +30,6 @@ export const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercu
getShortUrlDetail,
cancelGetShortUrlVisits,
settings,
selectedServer,
}: ShortUrlVisitsProps) => {
const { shortCode = '' } = useParams<{ shortCode: string }>();
const { search } = useLocation();
@ -57,7 +56,6 @@ export const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercu
visitsInfo={shortUrlVisits}
settings={settings}
exportCsv={exportCsv}
selectedServer={selectedServer}
>
<ShortUrlVisitsHeader shortUrlDetail={shortUrlDetail} shortUrlVisits={shortUrlVisits} goBack={goBack} />
</VisitsStats>

View file

@ -23,7 +23,6 @@ export const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: Repo
tagVisits,
cancelGetTagVisits,
settings,
selectedServer,
}: TagVisitsProps) => {
const goBack = useGoBack();
const { tag = '' } = useParams();
@ -38,7 +37,6 @@ export const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: Repo
visitsInfo={tagVisits}
settings={settings}
exportCsv={exportCsv}
selectedServer={selectedServer}
>
<TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={colorGenerator} />
</VisitsStats>

View file

@ -11,8 +11,6 @@ import { Message } from '../utils/Message';
import { Result } from '../utils/Result';
import { ShlinkApiError } from '../api/ShlinkApiError';
import { Settings } from '../settings/reducers/settings';
import { SelectedServer } from '../servers/data';
import { supportsBotVisits } from '../utils/helpers/features';
import { prettify } from '../utils/helpers/numbers';
import { NavPillItem, NavPills } from '../utils/NavPills';
import { ExportBtn } from '../utils/ExportBtn';
@ -33,7 +31,6 @@ export type VisitsStatsProps = PropsWithChildren<{
getVisits: (params: VisitsParams, doIntervalFallback?: boolean) => void;
visitsInfo: VisitsInfo;
settings: Settings;
selectedServer: SelectedServer;
cancelGetVisits: () => void;
exportCsv: (visits: NormalizedVisit[]) => void;
isOrphanVisits?: boolean;
@ -63,7 +60,6 @@ export const VisitsStats: FC<VisitsStatsProps> = ({
cancelGetVisits,
settings,
exportCsv,
selectedServer,
isOrphanVisits = false,
}) => {
const { visits, loading, loadingLarge, error, errorData, progress, fallbackInterval } = visitsInfo;
@ -82,7 +78,6 @@ export const VisitsStats: FC<VisitsStatsProps> = ({
);
const [highlightedVisits, setHighlightedVisits] = useState<NormalizedVisit[]>([]);
const [highlightedLabel, setHighlightedLabel] = useState<string | undefined>();
const botsSupported = supportsBotVisits(selectedServer);
const isFirstLoad = useRef(true);
const { search } = useLocation();
@ -273,7 +268,6 @@ export const VisitsStats: FC<VisitsStatsProps> = ({
selectedVisits={highlightedVisits}
setSelectedVisits={setSelectedVisits}
isOrphanVisits={isOrphanVisits}
selectedServer={selectedServer}
/>
</div>
)}
@ -306,7 +300,6 @@ export const VisitsStats: FC<VisitsStatsProps> = ({
<VisitsFilterDropdown
className="ms-0 ms-md-2 mt-3 mt-md-0"
isOrphanVisits={isOrphanVisits}
botsSupported={botsSupported}
selected={resolvedFilter}
onChange={(newVisitsFilter) => updateFiltering({ visitsFilter: newVisitsFilter })}
/>

View file

@ -8,8 +8,6 @@ import { SimplePaginator } from '../common/SimplePaginator';
import { SearchField } from '../utils/SearchField';
import { determineOrderDir, Order, sortList } from '../utils/helpers/ordering';
import { prettify } from '../utils/helpers/numbers';
import { supportsBotVisits } from '../utils/helpers/features';
import { SelectedServer } from '../servers/data';
import { Time } from '../utils/dates/Time';
import { TableOrderIcon } from '../utils/table/TableOrderIcon';
import { MediaMatcher } from '../utils/types';
@ -22,7 +20,6 @@ export interface VisitsTableProps {
setSelectedVisits: (visits: NormalizedVisit[]) => void;
matchMedia?: MediaMatcher;
isOrphanVisits?: boolean;
selectedServer: SelectedServer;
}
type OrderableFields = 'date' | 'country' | 'city' | 'browser' | 'os' | 'referer' | 'visitedUrl' | 'potentialBot';
@ -49,7 +46,6 @@ export const VisitsTable = ({
visits,
selectedVisits = [],
setSelectedVisits,
selectedServer,
matchMedia = window.matchMedia,
isOrphanVisits = false,
}: VisitsTableProps) => {
@ -64,8 +60,7 @@ export const VisitsTable = ({
const [page, setPage] = useState(1);
const end = page * PAGE_SIZE;
const start = end - PAGE_SIZE;
const supportsBots = supportsBotVisits(selectedServer);
const fullSizeColSpan = 7 + Number(supportsBots) + Number(isOrphanVisits);
const fullSizeColSpan = 8 + Number(isOrphanVisits);
const orderByColumn = (field: OrderableFields) =>
() => setOrder({ field, dir: determineOrderDir(field, order.field, order.dir) });
@ -99,12 +94,10 @@ export const VisitsTable = ({
>
<FontAwesomeIcon icon={checkIcon} className={classNames({ 'text-primary': selectedVisits.length > 0 })} />
</th>
{supportsBots && (
<th className={`${headerCellsClass} text-center`} onClick={orderByColumn('potentialBot')}>
<FontAwesomeIcon icon={botIcon} />
{renderOrderIcon('potentialBot')}
</th>
)}
<th className={`${headerCellsClass} text-center`} onClick={orderByColumn('potentialBot')}>
<FontAwesomeIcon icon={botIcon} />
{renderOrderIcon('potentialBot')}
</th>
<th className={headerCellsClass} onClick={orderByColumn('date')}>
Date
{renderOrderIcon('date')}
@ -165,18 +158,16 @@ export const VisitsTable = ({
<td className="text-center">
{isSelected && <FontAwesomeIcon icon={checkIcon} className="text-primary" />}
</td>
{supportsBots && (
<td className="text-center">
{visit.potentialBot && (
<>
<FontAwesomeIcon icon={botIcon} id={`botIcon${index}`} />
<UncontrolledTooltip placement="right" target={`botIcon${index}`}>
Potentially a visit from a bot or crawler
</UncontrolledTooltip>
</>
)}
</td>
)}
<td className="text-center">
{visit.potentialBot && (
<>
<FontAwesomeIcon icon={botIcon} id={`botIcon${index}`} />
<UncontrolledTooltip placement="right" target={`botIcon${index}`}>
Potentially a visit from a bot or crawler
</UncontrolledTooltip>
</>
)}
</td>
<td><Time date={visit.date} /></td>
<td>{visit.country}</td>
<td>{visit.city}</td>

View file

@ -8,16 +8,11 @@ interface VisitsFilterDropdownProps {
selected?: VisitsFilter;
className?: string;
isOrphanVisits: boolean;
botsSupported: boolean;
}
export const VisitsFilterDropdown = (
{ onChange, selected = {}, className, isOrphanVisits, botsSupported }: VisitsFilterDropdownProps,
{ onChange, selected = {}, className, isOrphanVisits }: VisitsFilterDropdownProps,
) => {
if (!botsSupported && !isOrphanVisits) {
return null;
}
const { orphanVisitsType, excludeBots = false } = selected;
const propsForOrphanVisitsTypeItem = (type: OrphanVisitType): DropdownItemProps => ({
active: orphanVisitsType === type,
@ -27,17 +22,12 @@ export const VisitsFilterDropdown = (
return (
<DropdownBtn text="Filters" dropdownClassName={className} className="me-3" right minWidth={250}>
{botsSupported && (
<>
<DropdownItem header>Bots:</DropdownItem>
<DropdownItem active={excludeBots} onClick={onBotsClick}>Exclude potential bots</DropdownItem>
</>
)}
{botsSupported && isOrphanVisits && <DropdownItem divider />}
<DropdownItem header>Bots:</DropdownItem>
<DropdownItem active={excludeBots} onClick={onBotsClick}>Exclude potential bots</DropdownItem>
{isOrphanVisits && (
<>
<DropdownItem divider />
<DropdownItem header>Orphan visits type:</DropdownItem>
<DropdownItem {...propsForOrphanVisitsTypeItem('base_url')}>Base URL</DropdownItem>
<DropdownItem {...propsForOrphanVisitsTypeItem('invalid_short_url')}>Invalid short URL</DropdownItem>

View file

@ -22,31 +22,31 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'ReportExporter');
bottle.decorator('ShortUrlVisits', connect(
['shortUrlVisits', 'shortUrlDetail', 'mercureInfo', 'settings', 'selectedServer'],
['shortUrlVisits', 'shortUrlDetail', 'mercureInfo', 'settings'],
['getShortUrlVisits', 'getShortUrlDetail', 'cancelGetShortUrlVisits', 'createNewVisits', 'loadMercureInfo'],
));
bottle.serviceFactory('TagVisits', TagVisits, 'ColorGenerator', 'ReportExporter');
bottle.decorator('TagVisits', connect(
['tagVisits', 'mercureInfo', 'settings', 'selectedServer'],
['tagVisits', 'mercureInfo', 'settings'],
['getTagVisits', 'cancelGetTagVisits', 'createNewVisits', 'loadMercureInfo'],
));
bottle.serviceFactory('DomainVisits', DomainVisits, 'ReportExporter');
bottle.decorator('DomainVisits', connect(
['domainVisits', 'mercureInfo', 'settings', 'selectedServer'],
['domainVisits', 'mercureInfo', 'settings'],
['getDomainVisits', 'cancelGetDomainVisits', 'createNewVisits', 'loadMercureInfo'],
));
bottle.serviceFactory('OrphanVisits', OrphanVisits, 'ReportExporter');
bottle.decorator('OrphanVisits', connect(
['orphanVisits', 'mercureInfo', 'settings', 'selectedServer'],
['orphanVisits', 'mercureInfo', 'settings'],
['getOrphanVisits', 'cancelGetOrphanVisits', 'createNewVisits', 'loadMercureInfo'],
));
bottle.serviceFactory('NonOrphanVisits', NonOrphanVisits, 'ReportExporter');
bottle.decorator('NonOrphanVisits', connect(
['nonOrphanVisits', 'mercureInfo', 'settings', 'selectedServer'],
['nonOrphanVisits', 'mercureInfo', 'settings'],
['getNonOrphanVisits', 'cancelGetNonOrphanVisits', 'createNewVisits', 'loadMercureInfo'],
));

View file

@ -1,7 +1,5 @@
import { SelectedServer } from '../../servers/data';
import { Settings } from '../../settings/reducers/settings';
export interface CommonVisitsProps {
selectedServer: SelectedServer;
settings: Settings;
}

View file

@ -64,7 +64,7 @@ describe('<ShortUrlForm />', () => {
});
it.each([
['create' as Mode, 4],
['create' as Mode, 5],
['create-basic' as Mode, 0],
])(
'renders expected amount of cards based on server capabilities and mode',

View file

@ -6,41 +6,30 @@ describe('qrCodes', () => {
[
'bar.io',
{ size: 870, format: 'svg' as QrCodeFormat, margin: 0, errorCorrection: 'L' as QrErrorCorrection },
{ errorCorrectionIsSupported: false },
'bar.io/qr-code?size=870&format=svg',
],
[
'bar.io',
{ size: 200, format: 'png' as QrCodeFormat, margin: 0, errorCorrection: 'L' as QrErrorCorrection },
{ errorCorrectionIsSupported: false },
'bar.io/qr-code?size=200&format=png',
'bar.io/qr-code?size=870&format=svg&errorCorrection=L',
],
[
'bar.io',
{ size: 200, format: 'svg' as QrCodeFormat, margin: 0, errorCorrection: 'L' as QrErrorCorrection },
{ errorCorrectionIsSupported: false },
'bar.io/qr-code?size=200&format=svg',
'bar.io/qr-code?size=200&format=svg&errorCorrection=L',
],
[
'shlink.io',
{ size: 456, format: 'png' as QrCodeFormat, margin: 10, errorCorrection: 'L' as QrErrorCorrection },
{ errorCorrectionIsSupported: false },
'shlink.io/qr-code?size=456&format=png&margin=10',
'shlink.io/qr-code?size=456&format=png&errorCorrection=L&margin=10',
],
[
'shlink.io',
{ size: 456, format: 'png' as QrCodeFormat, margin: 0, errorCorrection: 'H' as QrErrorCorrection },
{ errorCorrectionIsSupported: true },
'shlink.io/qr-code?size=456&format=png&errorCorrection=H',
],
[
'shlink.io',
{ size: 999, format: 'png' as QrCodeFormat, margin: 20, errorCorrection: 'Q' as QrErrorCorrection },
{ errorCorrectionIsSupported: true },
'shlink.io/qr-code?size=999&format=png&margin=20&errorCorrection=Q',
'shlink.io/qr-code?size=999&format=png&errorCorrection=Q&margin=20',
],
])('builds expected URL based in params', (shortUrl, options, capabilities, expectedUrl) => {
expect(buildQrCodeUrl(shortUrl, options, capabilities)).toEqual(expectedUrl);
])('builds expected URL based in params', (shortUrl, options, expectedUrl) => {
expect(buildQrCodeUrl(shortUrl, options)).toEqual(expectedUrl);
});
});
});

View file

@ -7,7 +7,6 @@ import { ReportExporter } from '../../src/common/services/ReportExporter';
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
import { DomainVisits } from '../../src/visits/reducers/domainVisits';
import { Settings } from '../../src/settings/reducers/settings';
import { SelectedServer } from '../../src/servers/data';
import { Visit } from '../../src/visits/types';
import { renderWithEvents } from '../__helpers__/setUpTest';
@ -30,7 +29,6 @@ describe('<DomainVisits />', () => {
cancelGetDomainVisits={cancelGetDomainVisits}
domainVisits={domainVisits}
settings={Mock.all<Settings>()}
selectedServer={Mock.all<SelectedServer>()}
/>
</MemoryRouter>,
);

View file

@ -7,7 +7,6 @@ import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
import { Visit } from '../../src/visits/types';
import { Settings } from '../../src/settings/reducers/settings';
import { ReportExporter } from '../../src/common/services/ReportExporter';
import { SelectedServer } from '../../src/servers/data';
import { renderWithEvents } from '../__helpers__/setUpTest';
import { VisitsInfo } from '../../src/visits/reducers/types';
@ -25,7 +24,6 @@ describe('<NonOrphanVisits />', () => {
cancelGetNonOrphanVisits={cancelGetNonOrphanVisits}
nonOrphanVisits={nonOrphanVisits}
settings={Mock.all<Settings>()}
selectedServer={Mock.all<SelectedServer>()}
/>
</MemoryRouter>,
);

View file

@ -7,7 +7,6 @@ import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
import { Visit } from '../../src/visits/types';
import { Settings } from '../../src/settings/reducers/settings';
import { ReportExporter } from '../../src/common/services/ReportExporter';
import { SelectedServer } from '../../src/servers/data';
import { renderWithEvents } from '../__helpers__/setUpTest';
import { VisitsInfo } from '../../src/visits/reducers/types';
@ -24,7 +23,6 @@ describe('<OrphanVisits />', () => {
orphanVisits={orphanVisits}
cancelGetOrphanVisits={jest.fn()}
settings={Mock.all<Settings>()}
selectedServer={Mock.all<SelectedServer>()}
/>
</MemoryRouter>,
);

View file

@ -5,7 +5,6 @@ import { createMemoryHistory } from 'history';
import { VisitsStats } from '../../src/visits/VisitsStats';
import { Visit } from '../../src/visits/types';
import { Settings } from '../../src/settings/reducers/settings';
import { ReachableServer } from '../../src/servers/data';
import { renderWithEvents } from '../__helpers__/setUpTest';
import { rangeOf } from '../../src/utils/utils';
import { VisitsInfo } from '../../src/visits/reducers/types';
@ -28,7 +27,6 @@ describe('<VisitsStats />', () => {
cancelGetVisits={() => {}}
settings={Mock.all<Settings>()}
exportCsv={exportCsv}
selectedServer={Mock.of<ReachableServer>({ version: '3.0.0' })}
/>
</Router>,
),

View file

@ -3,8 +3,6 @@ import { Mock } from 'ts-mockery';
import { VisitsTable, VisitsTableProps } from '../../src/visits/VisitsTable';
import { rangeOf } from '../../src/utils/utils';
import { NormalizedVisit } from '../../src/visits/types';
import { ReachableServer, SelectedServer } from '../../src/servers/data';
import { SemVer } from '../../src/utils/helpers/version';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<VisitsTable />', () => {
@ -13,7 +11,6 @@ describe('<VisitsTable />', () => {
const setUpFactory = (props: Partial<VisitsTableProps> = {}) => renderWithEvents(
<VisitsTable
visits={[]}
selectedServer={Mock.all<SelectedServer>()}
{...props}
matchMedia={matchMedia}
setSelectedVisits={setSelectedVisits}
@ -22,15 +19,8 @@ describe('<VisitsTable />', () => {
const setUp = (visits: NormalizedVisit[], selectedVisits: NormalizedVisit[] = []) => setUpFactory(
{ visits, selectedVisits },
);
const setUpForOrphanVisits = (isOrphanVisits: boolean, version: SemVer) => setUpFactory({
isOrphanVisits,
selectedServer: Mock.of<ReachableServer>({ printableVersion: version, version }),
});
const setUpForServerVersion = (version: SemVer) => setUpFactory({
selectedServer: Mock.of<ReachableServer>({ printableVersion: version, version }),
});
const setUpForOrphanVisits = (isOrphanVisits: boolean) => setUpFactory({ isOrphanVisits });
const setUpWithBots = () => setUpFactory({
selectedServer: Mock.of<ReachableServer>({ printableVersion: '2.7.0', version: '2.7.0' }),
visits: [
Mock.of<NormalizedVisit>({ potentialBot: false, date: '2022-05-05' }),
Mock.of<NormalizedVisit>({ potentialBot: true, date: '2022-05-05' }),
@ -39,12 +29,9 @@ describe('<VisitsTable />', () => {
afterEach(jest.resetAllMocks);
it.each([
['2.6.0' as SemVer, 6],
['2.7.0' as SemVer, 7],
])('renders expected amount of columns', (version, expectedColumns) => {
setUpForServerVersion(version);
expect(screen.getAllByRole('columnheader')).toHaveLength(expectedColumns + 1);
it('renders expected amount of columns', () => {
setUp([], []);
expect(screen.getAllByRole('columnheader')).toHaveLength(8);
});
it('shows warning when no visits are found', () => {
@ -104,17 +91,17 @@ describe('<VisitsTable />', () => {
referer: `${index}`,
country: `Country_${index}`,
})));
const getFirstColumnValue = () => screen.getAllByRole('row')[2]?.querySelectorAll('td')[2]?.textContent;
const getFirstColumnValue = () => screen.getAllByRole('row')[2]?.querySelectorAll('td')[3]?.textContent;
const clickColumn = async (index: number) => user.click(screen.getAllByRole('columnheader')[index]);
expect(getFirstColumnValue()).toContain('Country_1');
await clickColumn(1); // Date column ASC
await clickColumn(2); // Date column ASC
expect(getFirstColumnValue()).toContain('Country_9');
await clickColumn(6); // Referer column - ASC
await clickColumn(7); // Referer column - ASC
expect(getFirstColumnValue()).toContain('Country_1');
await clickColumn(6); // Referer column - DESC
await clickColumn(7); // Referer column - DESC
expect(getFirstColumnValue()).toContain('Country_9');
await clickColumn(6); // Referer column - reset
await clickColumn(7); // Referer column - reset
expect(getFirstColumnValue()).toContain('Country_1');
});
@ -139,12 +126,10 @@ describe('<VisitsTable />', () => {
});
it.each([
[true, '2.6.0' as SemVer, 8],
[false, '2.6.0' as SemVer, 7],
[true, '2.7.0' as SemVer, 9],
[false, '2.7.0' as SemVer, 8],
])('displays proper amount of columns for orphan and non-orphan visits', (isOrphanVisits, version, expectedCols) => {
setUpForOrphanVisits(isOrphanVisits, version);
[true, 9],
[false, 8],
])('displays proper amount of columns for orphan and non-orphan visits', (isOrphanVisits, expectedCols) => {
setUpForOrphanVisits(isOrphanVisits);
expect(screen.getAllByRole('columnheader')).toHaveLength(expectedCols);
});

View file

@ -5,10 +5,9 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<VisitsFilterDropdown />', () => {
const onChange = jest.fn();
const setUp = (selected: VisitsFilter = {}, isOrphanVisits = true, botsSupported = true) => renderWithEvents(
const setUp = (selected: VisitsFilter = {}, isOrphanVisits = true) => renderWithEvents(
<VisitsFilterDropdown
isOrphanVisits={isOrphanVisits}
botsSupported={botsSupported}
selected={selected}
onChange={onChange}
/>,
@ -69,9 +68,4 @@ describe('<VisitsFilterDropdown />', () => {
await user.click(screen.getAllByRole('menuitem')[index]);
expect(onChange).toHaveBeenCalledWith(expectedSelection);
});
it('does not render the component when neither orphan visits or bots filtering will be displayed', () => {
const { container } = setUp({}, false, false);
expect(container.firstChild).toBeNull();
});
});