Skip to content

Commit

Permalink
Merge pull request #6673 from guardian/ahe/no-unchecked-index
Browse files Browse the repository at this point in the history
Remove noUncheckedIndexedAccess override and fix all cases
  • Loading branch information
andrewHEguardian authored Jan 7, 2025
2 parents d637dbc + 6eacd2c commit 126ce31
Show file tree
Hide file tree
Showing 50 changed files with 196 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const options = (optionsForMapping: Record<string, string>): JSX.Element => {
return (
<>
{Object.keys(optionsForMapping).map((key) => (
<Option value={key}>{optionsForMapping[key]}</Option>
<Option value={key}>{optionsForMapping[key] ?? ''}</Option>
))}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ function sortedOptions(optionsForSorting: Record<string, string>): JSX.Element {
<>
{Object.keys(optionsForSorting)
.sort((a, b) =>
optionsForSorting[a].localeCompare(optionsForSorting[b]),
(optionsForSorting[a] ?? '').localeCompare(
optionsForSorting[b] ?? '',
),
)
.map((key) => (
<Option value={key} key={key}>
{optionsForSorting[key]}
{optionsForSorting[key] ?? ''}
</Option>
))}
</>
Expand Down
5 changes: 5 additions & 0 deletions support-frontend/assets/components/gridImage/gridImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export default function GridImage(props: PropTypes): JSX.Element | null {
const sorted = props.srcSizes.sort(ascending);
const srcSet = gridSrcset(props.gridId, sorted, props.imgType);
const fallbackSize = sorted.find((_) => _ > MIN_IMG_WIDTH) ?? sorted[0];

if (fallbackSize === undefined) {
return null;
}

const fallbackSrc = gridUrl(props.gridId, fallbackSize, props.imgType);
return (
<img
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function PaymentMethodSelectorContainer({

useEffect(() => {
availablePaymentMethods.length === 1 &&
availablePaymentMethods[0] &&
dispatch(setPaymentMethod({ paymentMethod: availablePaymentMethods[0] }));
}, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function setPayerName(
const nameParts = payerName.trim().replace(/\s+/g, ' ').split(' ');

if (nameParts.length > 1) {
dispatch(setFirstName(nameParts[0]));
dispatch(setFirstName(nameParts[0] ?? ''));
dispatch(setLastName(nameParts.slice(1).join(' ')));
} else if (nameParts.length === 1) {
logException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ export function AddressFields({ scope, countryGroupId, ...props }: PropTypes) {

if (countryGroupId !== selectedCountryGroup) {
const pathname = window.location.pathname;
const currentInternationalisationId = pathname.split('/')[1];
const currentInternationalisationId =
pathname.split('/')[1] ?? '';
const selectedInternationalisationId =
countryGroups[selectedCountryGroup as CountryGroupId]
.supportInternationalisationId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ interface AddressSelectorProps {
function AddressSelector({ results, onAddressSelected }: AddressSelectorProps) {
function handleAddressSelected(e: React.ChangeEvent<HTMLSelectElement>) {
const resultIndex = Number.parseInt(e.currentTarget.value);
if (results[resultIndex]) {
onAddressSelected(results[resultIndex]);
const result = results[resultIndex];
if (result) {
onAddressSelected(result);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ function PaymentMethodSelector({
}: PropTypes): JSX.Element {
useEffect(() => {
availablePaymentMethods.length === 1 &&
availablePaymentMethods[0] &&
setPaymentMethod(availablePaymentMethods[0]);
}, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ export function SupportReminderCTAandPrivacy({
} & SupportReminderState): JSX.Element {
const setReminder = () => {
const choice = reminderChoices[supportReminderState.selectedChoiceIndex];

if (!choice) {
return;
}

const url = getReminderUrl(choice);

if (!isCodeOrProd()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,11 @@ export const getThankYouModuleData = (
bodyCopy: (
<>
<SubscriptionStartBodyCopy
startDateGW={formatUserDate(publicationStartDays[0])}
startDateGW={
publicationStartDays[0]
? formatUserDate(publicationStartDays[0])
: ''
}
/>
</>
),
Expand Down
20 changes: 8 additions & 12 deletions support-frontend/assets/helpers/abTests/abtest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/* eslint "@typescript-eslint/no-unnecessary-condition": "off" -- this is while we are fixing `noUncheckedIndexedAccess` errors */

// ----- Imports ----- //

import seedrandom from 'seedrandom';
import { contributionsOnlyAmountsTestName } from 'helpers/contributions';
import type { Settings } from 'helpers/globalsAndSwitches/settings';
Expand Down Expand Up @@ -427,16 +423,10 @@ function getAmountsTestVariant(

const { testName, liveTestName, seed, variants, isLive } = targetedTest;

if (!variants.length) {
return {
selectedAmountsVariant: getFallbackAmounts(countryGroupId),
};
}

const selectVariant = (
isLive: boolean,
variants: AmountsVariant[],
): AmountsVariant => {
): AmountsVariant | undefined => {
if (isLive && variants.length > 1) {
const assignmentIndex = randomNumber(mvt, seed) % variants.length;

Expand All @@ -453,9 +443,15 @@ function getAmountsTestVariant(
const amountsParticipation = buildParticipation(
targetedTest,
currentTestName,
variant.variantName,
variant?.variantName ?? '',
);

if (!variant) {
return {
selectedAmountsVariant: getFallbackAmounts(countryGroupId),
};
}

return {
selectedAmountsVariant: {
...variant,
Expand Down
12 changes: 11 additions & 1 deletion support-frontend/assets/helpers/abTests/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import type {
AmountsTest,
AmountsVariant,
SelectedAmountsVariant,
} from 'helpers/contributions';
import type { CountryGroupId } from 'helpers/internationalisation/countryGroup';

export const FALLBACK_AMOUNTS: AmountsTest[] = [
type AmountsTestWithVariants = AmountsTest & {
variants: [AmountsVariant, ...AmountsVariant[]];
};

type NonEmptyAmountsTestArray = [
AmountsTestWithVariants,
...AmountsTestWithVariants[],
];

export const FALLBACK_AMOUNTS: NonEmptyAmountsTestArray = [
{
testName: 'FALLBACK_AMOUNTS__GBPCountries',
liveTestName: '',
Expand Down
13 changes: 8 additions & 5 deletions support-frontend/assets/helpers/campaigns/campaigns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,14 @@ export function getCampaignSettings(
promoCode?: string | null,
): CampaignSettings | null {
for (const campaignId in campaigns) {
const isEligible =
isCampaignEnabled(campaignId) &&
campaigns[campaignId].isEligible(countryGroupId, promoCode);
if (isEligible || forceCampaign(campaignId)) {
return campaigns[campaignId];
const campaign = campaigns[campaignId];
if (campaign) {
const isEligible =
isCampaignEnabled(campaignId) &&
campaign.isEligible(countryGroupId, promoCode);
if (isEligible || forceCampaign(campaignId)) {
return campaign;
}
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const useHasBeenSeen = (
// Enabling debouncing ensures the target element intersects for at least
// 200ms before the callback is executed
const intersectionFn: IntersectionObserverCallback = ([entry]) => {
if (entry.isIntersecting) {
if (entry?.isIntersecting) {
setHasBeenSeen(true);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const getSpecifiedRegionAmountsFromGlobal = (
(t) =>
t.targeting.targetingType === 'Region' && t.targeting.region === target,
);
if (!testArray.length) {
if (!testArray.length || !testArray[0]) {
return {};
}
return testArray[0];
Expand Down
5 changes: 5 additions & 0 deletions support-frontend/assets/helpers/images/theGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export function gridUrl(
imgType: ImageType = 'jpg',
): string {
const gridReference = imageCatalogue[gridId];

if (!gridReference) {
return '';
}

const originalWidth = gridReference.split('_')[2];
const path = `/img/media/${imageCatalogue[gridId]}/master/${originalWidth}.${imgType}?dpr=1&s=none&width=${size}`;
const url = new URL(path, GRID_DOMAIN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class Country {
? searchUppercase
: Object.keys(states).find(
(key) =>
states[key].toUpperCase() === searchUppercase ||
states[key]?.toUpperCase() === searchUppercase ||
(searchUppercase.length === 3 && searchUppercase.startsWith(key)),
);
}
Expand Down Expand Up @@ -223,7 +223,7 @@ export class Country {

if (
path !== paths[targetCountryGroup][0] &&
!path.startsWith(paths[targetCountryGroup][1]) &&
!path.startsWith(paths[targetCountryGroup][1] ?? '') &&
countryGroupId !== targetCountryGroup
) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const addressMetaSlice = createSlice({
state.deliveryAgent.isLoading = false;
state.deliveryAgent.response = action.payload;
if (action.payload.agents?.length === 1) {
state.deliveryAgent.chosenAgent = action.payload.agents[0].agentId;
state.deliveryAgent.chosenAgent = action.payload.agents[0]?.agentId;
}
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ function getSubscriptionTypeFromURL(): SubscriptionProduct {
};
const [, match] = urlPathRegex.exec(window.location.pathname) ?? [];
if (match) {
return productsToUrlPath[match];
const product = productsToUrlPath[match];
if (product) {
return product;
}
}
return DigitalPack;
}
Expand Down
5 changes: 3 additions & 2 deletions support-frontend/assets/helpers/redux/user/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ export const userSlice = createSlice({
state.isSignedIn = action.payload;
},
setTestUserStatus(state, action: PayloadAction<Record<string, boolean>>) {
state.isTestUser = action.payload.isTestUser;
state.isPostDeploymentTestUser = action.payload.isPostDeploymentTestUser;
state.isTestUser = action.payload.isTestUser ?? false;
state.isPostDeploymentTestUser =
action.payload.isPostDeploymentTestUser ?? false;
},
setIsReturningContributor(state, action: PayloadAction<boolean>) {
state.isReturningContributor = action.payload;
Expand Down
5 changes: 3 additions & 2 deletions support-frontend/assets/helpers/storage/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export function get(name: string): string | null | undefined {
const cookies = document.cookie.split('; ');

for (let i = cookies.length - 1; i >= 0; i -= 1) {
if (cookies[i].startsWith(name)) {
return cookies[i].substr(cookies[i].indexOf('=') + 1);
const cookie = cookies[i];
if (cookie && cookie.startsWith(name)) {
return cookie.substr(cookie.indexOf('=') + 1);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ const getDeliveryDays = (
const deliveryDays = [initial];

for (let i = 1; i <= length; i += 1) {
deliveryDays.push(getNextDeliveryDay(deliveryDays[i - 1]));
const previousDay = deliveryDays[i - 1];
if (previousDay) {
deliveryDays.push(getNextDeliveryDay(previousDay));
}
}

return deliveryDays;
Expand Down
16 changes: 10 additions & 6 deletions support-frontend/assets/helpers/supporterPlus/benefitsThreshold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ export function getLowerBenefitThreshold(
): number {
const supporterPlusRatePlan =
contributionType === 'ANNUAL' ? 'Annual' : 'Monthly';
return productCatalog.SupporterPlus.ratePlans[supporterPlusRatePlan].pricing[
currencyId
];
return (
productCatalog.SupporterPlus?.ratePlans[supporterPlusRatePlan]?.pricing[
currencyId
] ?? 0
);
}

export function getLowerProductBenefitThreshold(
Expand All @@ -49,9 +51,11 @@ export function getLowerProductBenefitThreshold(
const ratePlanSupporterPlus =
contributionType === 'ANNUAL' ? 'Annual' : 'Monthly';

return productCatalog[product].ratePlans[
product === 'SupporterPlus' ? ratePlanSupporterPlus : ratePlanTier3
].pricing[currencyId];
return (
productCatalog[product]?.ratePlans[
product === 'SupporterPlus' ? ratePlanSupporterPlus : ratePlanTier3
]?.pricing[currencyId] ?? 0
);
}

// This is a function overload that means if the caller has already determined that contributionType is recurring
Expand Down
36 changes: 18 additions & 18 deletions support-frontend/assets/helpers/tracking/acquisitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function getCampaign(

return (
Object.keys(campaigns).find((campaign) =>
campaigns[campaign].includes(campaignCode),
campaigns[campaign]?.includes(campaignCode),
) ?? null
);
}
Expand Down Expand Up @@ -270,30 +270,30 @@ function getReferrerAcquisitionDataFromSessionStorage():

function getAcquisitionDataFromUtmParams():
| Record<string, string | AcquisitionABTest | AcquisitionQueryParameters>
| null
| undefined {
// Same order of fields as https://reader-revenue-lynx.s3.eu-west-1.amazonaws.com/v3.html
const utmParamNames = [
'utm_campaign',
'utm_content',
'utm_term',
'utm_source',
'utm_medium',
];
const utmParameters = Object.fromEntries(
utmParamNames.map((paramName) => [paramName, getQueryParameter(paramName)]),
);
const utmCampaign = getQueryParameter('utm_campaign');
const utmContent = getQueryParameter('utm_content');
const utmTerm = getQueryParameter('utm_term');
const utmSource = getQueryParameter('utm_source');
const utmMedium = getQueryParameter('utm_medium');

// All must be present in the URL for them to be accepted
if (utmParamNames.every((paramName) => utmParameters[paramName].length > 0)) {
if (
utmCampaign !== '' &&
utmContent !== '' &&
utmTerm !== '' &&
utmSource !== '' &&
utmMedium !== ''
) {
return {
campaignCode: utmParameters.utm_campaign,
campaignCode: utmCampaign,
abTest: {
name: utmParameters.utm_content,
variant: utmParameters.utm_term,
name: utmContent,
variant: utmTerm,
},
source: utmParameters.utm_source,
componentType: utmParameters.utm_medium,
source: utmSource,
componentType: utmMedium,
queryParameters: toAcquisitionQueryParameters(getAllQueryParams()),
};
}
Expand Down
Loading

0 comments on commit 126ce31

Please sign in to comment.