From 0f9ab4a57054cc5658618f3a1fae2c9c2b622087 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 20 May 2024 14:02:07 +0200 Subject: [PATCH 1/8] wip --- .eslintrc.js | 1 - .github/actions/javascript/bumpVersion/bumpVersion.ts | 2 +- .../javascript/getGraphiteString/getGraphiteString.ts | 2 +- .../javascript/getPreviousVersion/getPreviousVersion.ts | 2 +- .github/scripts/detectRedirectCycle.ts | 2 +- desktop/contextBridge.ts | 2 +- desktop/main.ts | 4 ++-- src/components/Attachments/AttachmentCarousel/index.tsx | 2 +- src/components/OfflineWithFeedback.tsx | 2 +- src/libs/EmojiUtils.ts | 2 +- src/libs/Environment/betaChecker/index.android.ts | 2 +- .../LocalNotification/BrowserNotifications.ts | 2 +- src/pages/home/report/ContextMenu/ContextMenuActions.tsx | 2 +- .../ComposerWithSuggestions/ComposerWithSuggestions.tsx | 9 +++++++-- src/pages/home/report/ReportActionsList.tsx | 4 ++-- 15 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1f23ae22ca7e..eb50d1fcc5f3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -100,7 +100,6 @@ module.exports = { __DEV__: 'readonly', }, rules: { - '@typescript-eslint/no-unsafe-argument': 'off', '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', diff --git a/.github/actions/javascript/bumpVersion/bumpVersion.ts b/.github/actions/javascript/bumpVersion/bumpVersion.ts index ed4828367cf2..f9215f36a844 100644 --- a/.github/actions/javascript/bumpVersion/bumpVersion.ts +++ b/.github/actions/javascript/bumpVersion/bumpVersion.ts @@ -47,7 +47,7 @@ if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } -const {version: previousVersion} = JSON.parse(fs.readFileSync('./package.json').toString()); +const {version: previousVersion}: {version: string} = JSON.parse(fs.readFileSync('./package.json').toString()); const newVersion = versionUpdater.incrementVersion(previousVersion, semanticVersionLevel); console.log(`Previous version: ${previousVersion}`, `New version: ${newVersion}`); diff --git a/.github/actions/javascript/getGraphiteString/getGraphiteString.ts b/.github/actions/javascript/getGraphiteString/getGraphiteString.ts index 57a941105f90..c486fdbd39f3 100644 --- a/.github/actions/javascript/getGraphiteString/getGraphiteString.ts +++ b/.github/actions/javascript/getGraphiteString/getGraphiteString.ts @@ -28,7 +28,7 @@ const run = () => { // Extract timestamp, Graphite accepts timestamp in seconds if (current.metadata?.creationDate) { - timestamp = Math.floor(new Date(current.metadata.creationDate).getTime() / 1000); + timestamp = Math.floor(new Date(current.metadata.creationDate as string).getTime() / 1000); } if (current.name && current.meanDuration && current.meanCount && timestamp) { diff --git a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts index dc1e99d1e3b8..e725e302eee1 100644 --- a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts +++ b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts @@ -7,6 +7,6 @@ if (!semverLevel || !Object.values(versionUpdater.SEMANTIC_VERSION_LEVEL core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); } -const {version: currentVersion} = JSON.parse(readFileSync('./package.json', 'utf8')); +const {version: currentVersion}: {version: string} = JSON.parse(readFileSync('./package.json', 'utf8')); const previousVersion = versionUpdater.getPreviousVersion(currentVersion, semverLevel); core.setOutput('PREVIOUS_VERSION', previousVersion); diff --git a/.github/scripts/detectRedirectCycle.ts b/.github/scripts/detectRedirectCycle.ts index 5aa0d1daf342..6da0ecba158c 100644 --- a/.github/scripts/detectRedirectCycle.ts +++ b/.github/scripts/detectRedirectCycle.ts @@ -52,7 +52,7 @@ function detectCycle(): boolean { fs.createReadStream(`${process.cwd()}/docs/redirects.csv`) .pipe(parser) - .on('data', (row) => { + .on('data', (row: [string, string]) => { // Create a directed graph of sourceURL -> targetURL addEdge(row[0], row[1]); }) diff --git a/desktop/contextBridge.ts b/desktop/contextBridge.ts index 487e528a7485..61ede178da2d 100644 --- a/desktop/contextBridge.ts +++ b/desktop/contextBridge.ts @@ -67,7 +67,7 @@ contextBridge.exposeInMainWorld('electron', { } // Deliberately strip event as it includes `sender` - ipcRenderer.on(channel, (event, ...args) => func(...args)); + ipcRenderer.on(channel, (event, ...args: unknown[]) => func(...args)); }, /** Remove listeners for a single channel from the main process and sent to the renderer process. */ diff --git a/desktop/main.ts b/desktop/main.ts index b40557464ec1..64587f42bf56 100644 --- a/desktop/main.ts +++ b/desktop/main.ts @@ -581,7 +581,7 @@ const mainWindow = (): Promise => { app.hide(); } - ipcMain.on(ELECTRON_EVENTS.LOCALE_UPDATED, (event, updatedLocale) => { + ipcMain.on(ELECTRON_EVENTS.LOCALE_UPDATED, (event, updatedLocale: Locale) => { Menu.setApplicationMenu(Menu.buildFromTemplate(localizeMenuItems(initialMenuTemplate, updatedLocale))); disposeContextMenu(); disposeContextMenu = createContextMenu(updatedLocale); @@ -601,7 +601,7 @@ const mainWindow = (): Promise => { // Listen to badge updater event emitted by the render process // and update the app badge count (MacOS only) - ipcMain.on(ELECTRON_EVENTS.REQUEST_UPDATE_BADGE_COUNT, (event, totalCount) => { + ipcMain.on(ELECTRON_EVENTS.REQUEST_UPDATE_BADGE_COUNT, (event, totalCount?: number) => { if (totalCount === -1) { // The electron docs say you should be able to update this and pass no parameters to set the badge // to a single red dot, but in practice it resulted in an error "TypeError: Insufficient number of diff --git a/src/components/Attachments/AttachmentCarousel/index.tsx b/src/components/Attachments/AttachmentCarousel/index.tsx index 3a7e0f19c4cd..3b873d437e95 100644 --- a/src/components/Attachments/AttachmentCarousel/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/index.tsx @@ -98,7 +98,7 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, } if (onNavigate) { - onNavigate(entry.item); + onNavigate(entry.item as Attachment); } }, [isFullScreenRef, onNavigate], diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx index ba9ce9858d03..d96f11a46240 100644 --- a/src/components/OfflineWithFeedback.tsx +++ b/src/components/OfflineWithFeedback.tsx @@ -116,7 +116,7 @@ function OfflineWithFeedback({ }; if (child.props.children) { - props.children = applyStrikeThrough(child.props.children); + props.children = applyStrikeThrough(child.props.children as React.ReactNode); } return React.cloneElement(child, props); diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 3b189dbb084f..fc84bb7261f6 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -411,7 +411,7 @@ function suggestEmojis(text: string, lang: Locale, limit: number = CONST.AUTO_CO } matching.push({code: node.metaData.code, name: node.name, types: node.metaData.types}); } - const suggestions = node.metaData.suggestions; + const suggestions: Emoji[] | undefined = node.metaData.suggestions; if (!suggestions) { return; } diff --git a/src/libs/Environment/betaChecker/index.android.ts b/src/libs/Environment/betaChecker/index.android.ts index 4b912e0daaa5..da65ae1b7383 100644 --- a/src/libs/Environment/betaChecker/index.android.ts +++ b/src/libs/Environment/betaChecker/index.android.ts @@ -22,7 +22,7 @@ function isBetaBuild(): IsBetaBuild { fetch(CONST.GITHUB_RELEASE_URL) .then((res) => res.json()) .then((json) => { - const productionVersion = json.tag_name; + const productionVersion: string | semver.SemVer = json.tag_name; if (!productionVersion) { AppUpdate.setIsAppInBeta(false); resolve(false); diff --git a/src/libs/Notification/LocalNotification/BrowserNotifications.ts b/src/libs/Notification/LocalNotification/BrowserNotifications.ts index ee6d00ee2208..18fd8256a5ec 100644 --- a/src/libs/Notification/LocalNotification/BrowserNotifications.ts +++ b/src/libs/Notification/LocalNotification/BrowserNotifications.ts @@ -153,7 +153,7 @@ export default { */ clearNotifications(shouldClearNotification: (notificationData: LocalNotificationData) => boolean) { Object.values(notificationCache) - .filter((notification) => shouldClearNotification(notification.data)) + .filter((notification) => shouldClearNotification(notification.data as LocalNotificationData)) .forEach((notification) => notification.close()); }, }; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 105eadffd436..fe415b137fe6 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -366,7 +366,7 @@ const ContextMenuActions: ContextMenuAction[] = [ Clipboard.setString(Localize.translateLocal('iou.unheldExpense')); } else if (content) { setClipboardMessage( - content.replace(/()(.*?)(<\/mention-user>)/gi, (match, openTag, innerContent, closeTag): string => { + content.replace(/()(.*?)(<\/mention-user>)/gi, (match, openTag: string, innerContent: string, closeTag: string): string => { const modifiedContent = Str.removeSMSDomain(innerContent) || ''; return openTag + modifiedContent + closeTag || ''; }), diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 29b25828d24b..0b585de8f059 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -177,6 +177,11 @@ type ComposerWithSuggestionsProps = ComposerWithSuggestionsOnyxProps & policyID: string; }; +type SwitchToCurrentReportProps = { + preexistingReportID: string; + callback: () => void; +}; + const {RNTextInputReset} = NativeModules; const isIOSNative = getPlatform() === CONST.PLATFORM.IOS; @@ -336,7 +341,7 @@ function ComposerWithSuggestions( const debouncedSaveReportComment = useMemo( () => - lodashDebounce((selectedReportID, newComment) => { + lodashDebounce((selectedReportID: string, newComment: string | null) => { Report.saveReportDraftComment(selectedReportID, newComment); isCommentPendingSaved.current = false; }, 1000), @@ -344,7 +349,7 @@ function ComposerWithSuggestions( ); useEffect(() => { - const switchToCurrentReport = DeviceEventEmitter.addListener(`switchToPreExistingReport_${reportID}`, ({preexistingReportID, callback}) => { + const switchToCurrentReport = DeviceEventEmitter.addListener(`switchToPreExistingReport_${reportID}`, ({preexistingReportID, callback}: SwitchToCurrentReportProps) => { if (!commentRef.current) { callback(); return; diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index d8aed24e3b13..bdc0b80375fa 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -303,12 +303,12 @@ function ReportActionsList({ setCurrentUnreadMarker(null); }; - const unreadActionSubscription = DeviceEventEmitter.addListener(`unreadAction_${report.reportID}`, (newLastReadTime) => { + const unreadActionSubscription = DeviceEventEmitter.addListener(`unreadAction_${report.reportID}`, (newLastReadTime: string) => { resetUnreadMarker(newLastReadTime); setMessageManuallyMarkedUnread(new Date().getTime()); }); - const readNewestActionSubscription = DeviceEventEmitter.addListener(`readNewestAction_${report.reportID}`, (newLastReadTime) => { + const readNewestActionSubscription = DeviceEventEmitter.addListener(`readNewestAction_${report.reportID}`, (newLastReadTime: string) => { resetUnreadMarker(newLastReadTime); setMessageManuallyMarkedUnread(0); }); From 2681751b8aafba2152980c924df846f47181998d Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 20 May 2024 18:18:30 +0200 Subject: [PATCH 2/8] wip 2 --- .../actions/javascript/bumpVersion/bumpVersion.ts | 9 +++++++-- src/components/AttachmentPicker/index.native.tsx | 8 +++++++- .../Attachments/AttachmentCarousel/index.tsx | 5 +++-- src/components/Onfido/BaseOnfidoWeb.tsx | 7 ++++++- src/components/Onfido/index.native.tsx | 9 +++++++-- .../SignInButtons/AppleSignIn/index.android.tsx | 2 +- src/libs/EmojiUtils.ts | 12 +++++++----- src/libs/Localize/index.ts | 2 +- src/libs/Pusher/pusher.ts | 2 +- src/libs/actions/Device/index.ts | 10 +++++++++- tests/e2e/server/index.ts | 8 +++++++- tests/ui/UnreadIndicatorsTest.tsx | 2 +- tests/unit/MiddlewareTest.ts | 8 ++++---- tests/unit/markPullRequestsAsDeployedTest.ts | 6 +++--- tests/utils/TestHelper.ts | 4 ++-- workflow_tests/utils/ExtendedAct.ts | 4 ++-- workflow_tests/utils/preGenerateTest.ts | 2 +- 17 files changed, 69 insertions(+), 31 deletions(-) diff --git a/.github/actions/javascript/bumpVersion/bumpVersion.ts b/.github/actions/javascript/bumpVersion/bumpVersion.ts index f9215f36a844..85955ea81ff4 100644 --- a/.github/actions/javascript/bumpVersion/bumpVersion.ts +++ b/.github/actions/javascript/bumpVersion/bumpVersion.ts @@ -1,6 +1,7 @@ import * as core from '@actions/core'; import {exec as originalExec} from 'child_process'; import fs from 'fs'; +import type {PackageJson} from 'type-fest'; import {promisify} from 'util'; import {generateAndroidVersionCode, updateAndroidVersion, updateiOSVersion} from '@github/libs/nativeVersionUpdater'; import * as versionUpdater from '@github/libs/versionUpdater'; @@ -47,8 +48,12 @@ if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } -const {version: previousVersion}: {version: string} = JSON.parse(fs.readFileSync('./package.json').toString()); -const newVersion = versionUpdater.incrementVersion(previousVersion, semanticVersionLevel); +const {version: previousVersion}: PackageJson = JSON.parse(fs.readFileSync('./package.json').toString()); +if (!previousVersion) { + core.setFailed('Error: Could not read package.json'); +} + +const newVersion = versionUpdater.incrementVersion(previousVersion ?? '', semanticVersionLevel); console.log(`Previous version: ${previousVersion}`, `New version: ${newVersion}`); updateNativeVersions(newVersion); diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index ad4cf023c096..822a5650e758 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -248,7 +248,13 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s completeAttachmentSelection.current(result); }) .catch((error) => { - showGeneralAlert(error.message); + let errorMessage; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = String(error.message); + } + showGeneralAlert(errorMessage); throw error; }); }, diff --git a/src/components/Attachments/AttachmentCarousel/index.tsx b/src/components/Attachments/AttachmentCarousel/index.tsx index 3b873d437e95..42536ae208ae 100644 --- a/src/components/Attachments/AttachmentCarousel/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/index.tsx @@ -92,13 +92,14 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, return; } + const item: Attachment = entry.item; if (entry.index !== null) { setPage(entry.index); - setActiveSource(entry.item.source); + setActiveSource(item.source); } if (onNavigate) { - onNavigate(entry.item as Attachment); + onNavigate(item); } }, [isFullScreenRef, onNavigate], diff --git a/src/components/Onfido/BaseOnfidoWeb.tsx b/src/components/Onfido/BaseOnfidoWeb.tsx index fefe2ab0a6d1..af9b99efda33 100644 --- a/src/components/Onfido/BaseOnfidoWeb.tsx +++ b/src/components/Onfido/BaseOnfidoWeb.tsx @@ -93,8 +93,13 @@ function initializeOnfido({sdkToken, onSuccess, onError, onUserExit, preferredLo onSuccess(data); }, onError: (error) => { + let errorMessage; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = CONST.ERROR.UNKNOWN_ERROR; + } const errorType = error.type; - const errorMessage = error.message ?? CONST.ERROR.UNKNOWN_ERROR; Log.hmmm('Onfido error', {errorType, errorMessage}); if (errorType === CONST.WALLET.ERROR.ONFIDO_USER_CONSENT_DENIED) { onUserExit(); diff --git a/src/components/Onfido/index.native.tsx b/src/components/Onfido/index.native.tsx index a7e7a277fff9..f1f590b46786 100644 --- a/src/components/Onfido/index.native.tsx +++ b/src/components/Onfido/index.native.tsx @@ -30,14 +30,19 @@ function Onfido({sdkToken, onUserExit, onSuccess, onError}: OnfidoProps) { }) .then(onSuccess) .catch((error) => { - const errorMessage = error.message ?? CONST.ERROR.UNKNOWN_ERROR; + let errorMessage: string; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = CONST.ERROR.UNKNOWN_ERROR; + } const errorType = error.type; Log.hmmm('Onfido error on native', {errorType, errorMessage}); // If the user cancels the Onfido flow we won't log this error as it's normal. In the React Native SDK the user exiting the flow will trigger this error which we can use as // our "user exited the flow" callback. On web, this event has it's own callback passed as a config so we don't need to bother with this there. - if ([CONST.ONFIDO.ERROR.USER_CANCELLED, CONST.ONFIDO.ERROR.USER_TAPPED_BACK, CONST.ONFIDO.ERROR.USER_EXITED].includes(errorMessage)) { + if (([CONST.ONFIDO.ERROR.USER_CANCELLED, CONST.ONFIDO.ERROR.USER_TAPPED_BACK, CONST.ONFIDO.ERROR.USER_EXITED] as string[]).includes(errorMessage)) { onUserExit(); return; } diff --git a/src/components/SignInButtons/AppleSignIn/index.android.tsx b/src/components/SignInButtons/AppleSignIn/index.android.tsx index cfd1c48ee8b5..81d360d9f072 100644 --- a/src/components/SignInButtons/AppleSignIn/index.android.tsx +++ b/src/components/SignInButtons/AppleSignIn/index.android.tsx @@ -38,7 +38,7 @@ function AppleSignIn() { appleSignInRequest() .then((token) => Session.beginAppleSignIn(token)) .catch((e) => { - if (e.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { + if (e instanceof Error && e.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { return null; } Log.alert('[Apple Sign In] Apple authentication failed', e); diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index fc84bb7261f6..0be7e76a0aa9 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -10,6 +10,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx'; import type {ReportActionReaction, UsersReactions} from '@src/types/onyx/ReportActionReactions'; import type IconAsset from '@src/types/utils/IconAsset'; +import type EmojiTrie from './EmojiTrie'; +import type {SupportedLanguage} from './EmojiTrie'; type HeaderIndice = {code: string; index: number; icon: IconAsset}; type EmojiSpacer = {code: string; spacer: boolean}; @@ -312,9 +314,9 @@ function getAddedEmojis(currentEmojis: Emoji[], formerEmojis: Emoji[]): Emoji[] */ function replaceEmojis(text: string, preferredSkinTone: OnyxEntry = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { // emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it - const emojisTrie = require('./EmojiTrie').default; + const emojisTrie: typeof EmojiTrie = require('./EmojiTrie').default; - const trie = emojisTrie[lang]; + const trie = emojisTrie[lang as SupportedLanguage]; if (!trie) { return {text, emojis: []}; } @@ -390,9 +392,9 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone: OnyxEntry = TranslationFlatObject[TKey] extends */ const translationCache = new Map, Map>( Object.values(CONST.LOCALES).reduce((cache, locale) => { - cache.push([locale, new Map()]); + cache.push([locale, new Map()]); return cache; }, [] as Array<[ValueOf, Map]>), ); diff --git a/src/libs/Pusher/pusher.ts b/src/libs/Pusher/pusher.ts index 48c5e5c1409f..cdce408d8d43 100644 --- a/src/libs/Pusher/pusher.ts +++ b/src/libs/Pusher/pusher.ts @@ -198,7 +198,7 @@ function bindEventToChannel(channel: Channel // packet. if (chunkedEvent.receivedFinal && chunkedEvent.chunks.length === Object.keys(chunkedEvent.chunks).length) { try { - eventCallback(JSON.parse(chunkedEvent.chunks.join(''))); + eventCallback(JSON.parse(chunkedEvent.chunks.join('')) as EventData); } catch (err) { Log.alert('[Pusher] Unable to parse chunked JSON response from Pusher', { error: err, diff --git a/src/libs/actions/Device/index.ts b/src/libs/actions/Device/index.ts index e7c19d20e4fe..5309f67ea91a 100644 --- a/src/libs/actions/Device/index.ts +++ b/src/libs/actions/Device/index.ts @@ -43,7 +43,15 @@ function setDeviceID() { Log.info('Got new deviceID', false, uniqueID); Onyx.set(ONYXKEYS.DEVICE_ID, uniqueID); }) - .catch((err) => Log.info('Found existing deviceID', false, err.message)); + .catch((err) => { + let errorMessage; + if (err instanceof Error) { + errorMessage = err.message; + } else { + errorMessage = String(err.message); + } + Log.info('Found existing deviceID', false, errorMessage); + }); } /** diff --git a/tests/e2e/server/index.ts b/tests/e2e/server/index.ts index 51b73447bab4..0854c5d29db9 100644 --- a/tests/e2e/server/index.ts +++ b/tests/e2e/server/index.ts @@ -154,7 +154,13 @@ const createServerInstance = (): ServerInstance => { res.end('Error executing command'); }) .catch((error) => { - Logger.error('Error executing command', error); + let errorString; + if (error instanceof Error) { + errorString = error.toString(); + } else { + errorString = String(error); + } + Logger.error('Error executing command', errorString); res.statusCode = 500; res.end('Error executing command'); }); diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index e5c7e0359eed..5f8fa228d191 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -77,7 +77,7 @@ const createAddListenerMock = (): ListenerMock => { transitionEndListeners.forEach((transitionEndListener) => transitionEndListener()); }; - const addListener: jest.Mock = jest.fn().mockImplementation((listener, callback) => { + const addListener: jest.Mock = jest.fn().mockImplementation((listener, callback: () => void) => { if (listener === 'transitionEnd') { transitionEndListeners.push(callback); } diff --git a/tests/unit/MiddlewareTest.ts b/tests/unit/MiddlewareTest.ts index cc4bf7d0df6b..6954b22b2706 100644 --- a/tests/unit/MiddlewareTest.ts +++ b/tests/unit/MiddlewareTest.ts @@ -49,9 +49,9 @@ describe('Middleware', () => { expect(global.fetch).toHaveBeenCalledTimes(2); expect(global.fetch).toHaveBeenLastCalledWith('https://www.expensify.com.dev/api/AddComment?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body, {reportID: '1234', reportActionID: '5678'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body as TestHelper.FormData, {reportID: '1234', reportActionID: '5678'}); expect(global.fetch).toHaveBeenNthCalledWith(1, 'https://www.expensify.com.dev/api/OpenReport?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body, {reportID: '1234'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body as TestHelper.FormData, {reportID: '1234'}); }); test('Request with preexistingReportID', async () => { @@ -93,9 +93,9 @@ describe('Middleware', () => { expect(global.fetch).toHaveBeenCalledTimes(2); expect(global.fetch).toHaveBeenLastCalledWith('https://www.expensify.com.dev/api/AddComment?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body, {reportID: '5555', reportActionID: '5678'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body as TestHelper.FormData, {reportID: '5555', reportActionID: '5678'}); expect(global.fetch).toHaveBeenNthCalledWith(1, 'https://www.expensify.com.dev/api/OpenReport?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body, {reportID: '1234'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body as TestHelper.FormData, {reportID: '1234'}); }); }); }); diff --git a/tests/unit/markPullRequestsAsDeployedTest.ts b/tests/unit/markPullRequestsAsDeployedTest.ts index d533435273d4..24a6733d1244 100644 --- a/tests/unit/markPullRequestsAsDeployedTest.ts +++ b/tests/unit/markPullRequestsAsDeployedTest.ts @@ -196,7 +196,7 @@ platform | result }); it('comments on pull requests correctly for a standard production deploy', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'IS_PRODUCTION_DEPLOY') { return true; } @@ -226,7 +226,7 @@ platform | result }); it('comments on pull requests correctly for a cherry pick', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'PR_LIST') { return JSON.stringify([3]); } @@ -281,7 +281,7 @@ platform | result }); it('comments on pull requests correctly when one platform fails', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'ANDROID') { return 'skipped'; } diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index bd107ba6ed56..11befebea340 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -230,7 +230,7 @@ const createAddListenerMock = () => { transitionEndListeners.forEach((transitionEndListener) => transitionEndListener()); }; - const addListener = jest.fn().mockImplementation((listener, callback) => { + const addListener = jest.fn().mockImplementation((listener, callback: Listener) => { if (listener === 'transitionEnd') { transitionEndListeners.push(callback); } @@ -242,5 +242,5 @@ const createAddListenerMock = () => { return {triggerTransitionEnd, addListener}; }; -export type {MockFetch}; +export type {MockFetch, FormData}; export {assertFormDataMatchesObject, buildPersonalDetails, buildTestReportComment, createAddListenerMock, getGlobalFetchMock, setPersonalDetails, signInWithTestUser, signOutTestUser}; diff --git a/workflow_tests/utils/ExtendedAct.ts b/workflow_tests/utils/ExtendedAct.ts index b0f4d7e159e4..e2bb12ec8e01 100644 --- a/workflow_tests/utils/ExtendedAct.ts +++ b/workflow_tests/utils/ExtendedAct.ts @@ -42,14 +42,14 @@ class ExtendedAct extends Act { if (opts.workflowFile) { workflowFiles = [path.basename(opts.workflowFile)]; } else if (this['workflowFile'] !== this['cwd']) { - workflowFiles = [path.basename(this['workflowFile'])]; + workflowFiles = [path.basename(this['workflowFile'] as string)]; } else { const availableWorkflows = await this.list(undefined, opts.cwd, opts.workflowFile); workflowFiles = availableWorkflows.filter(filter).map((workflow: Workflow) => workflow.workflowFile); } return workflowFiles.map((workflowFile) => { - const jobMocker = new JobMocker(workflowFile, opts.cwd ?? this['cwd']); + const jobMocker = new JobMocker(workflowFile, opts.cwd ?? (this['cwd'] as string)); return jobMocker.mock(opts.mockJobs); }); } diff --git a/workflow_tests/utils/preGenerateTest.ts b/workflow_tests/utils/preGenerateTest.ts index 25bdb8f00ae3..b1fd99b72794 100644 --- a/workflow_tests/utils/preGenerateTest.ts +++ b/workflow_tests/utils/preGenerateTest.ts @@ -275,7 +275,7 @@ checkIfMocksFileExists(workflowTestMocksDirectory, workflowTestMocksFileName); const workflowTestAssertionsFileName = `${workflowName}Assertions.ts`; checkIfAssertionsFileExists(workflowTestAssertionsDirectory, workflowTestAssertionsFileName); -const workflow = yaml.parse(fs.readFileSync(workflowFilePath, 'utf8')); +const workflow: YamlWorkflow = yaml.parse(fs.readFileSync(workflowFilePath, 'utf8')); const workflowJobs = parseWorkflowFile(workflow); const mockFileContent = getMockFileContent(workflowName, workflowJobs); From 9f96e0c723a489af9c87f5f99633e3ec08050a4e Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 20 May 2024 18:45:06 +0200 Subject: [PATCH 3/8] define step --- workflow_tests/utils/preGenerateTest.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/workflow_tests/utils/preGenerateTest.ts b/workflow_tests/utils/preGenerateTest.ts index b1fd99b72794..1e7e7bb04184 100644 --- a/workflow_tests/utils/preGenerateTest.ts +++ b/workflow_tests/utils/preGenerateTest.ts @@ -7,6 +7,8 @@ import {exit} from 'process'; import yaml from 'yaml'; import type {YamlMockJob, YamlWorkflow} from './JobMocker'; +type Step = {name: string; with?: string; envs?: string[]; inputs?: string[]}; + const workflowsDirectory = path.resolve(__dirname, '..', '..', '.github', 'workflows'); const workflowTestsDirectory = path.resolve(__dirname, '..'); const workflowTestMocksDirectory = path.join(workflowTestsDirectory, 'mocks'); @@ -199,7 +201,7 @@ const parseWorkflowFile = (workflow: YamlWorkflow) => { workflowJobs[jobId] = { steps: [], }; - job.steps.forEach((step) => { + job.steps.forEach((step: Step) => { const workflowStep = { name: step.name, inputs: Object.keys(step.with ?? {}), @@ -243,7 +245,7 @@ const getAssertionsFileContent = (jobs: Record): string => Object.entries(jobs).forEach(([jobId, job]) => { let stepAssertionsContent = ''; - job.steps.forEach((step) => { + job.steps.forEach((step: Step) => { stepAssertionsContent += stepAssertionTemplate(step.name, jobId.toUpperCase(), step.name, step.inputs, step.envs); }); const jobAssertionName = `assert${jobId.charAt(0).toUpperCase() + jobId.slice(1)}JobExecuted`; From d96b21743efe9ff10b2eda35d74099bc1612f90c Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 21 May 2024 14:47:09 +0200 Subject: [PATCH 4/8] another portion of types --- .../javascript/bumpVersion/bumpVersion.ts | 2 +- .../checkDeployBlockers.ts | 2 +- .../getPreviousVersion/getPreviousVersion.ts | 9 +++++++-- .../reviewerChecklist/reviewerChecklist.ts | 2 +- .../AttachmentPicker/index.native.tsx | 2 +- src/components/Composer/index.tsx | 2 +- src/components/Icon/__mocks__/Expensicons.ts | 5 ++++- .../SignInButtons/AppleSignIn/index.ios.tsx | 7 ++++--- src/libs/Pusher/pusher.ts | 10 +++++++--- tests/ui/UnreadIndicatorsTest.tsx | 6 +++++- tests/utils/collections/reportActions.ts | 19 +++++++++---------- 11 files changed, 41 insertions(+), 25 deletions(-) diff --git a/.github/actions/javascript/bumpVersion/bumpVersion.ts b/.github/actions/javascript/bumpVersion/bumpVersion.ts index 85955ea81ff4..eba79c7c9edb 100644 --- a/.github/actions/javascript/bumpVersion/bumpVersion.ts +++ b/.github/actions/javascript/bumpVersion/bumpVersion.ts @@ -20,7 +20,7 @@ function updateNativeVersions(version: string) { .then(() => { console.log('Successfully updated Android!'); }) - .catch((err) => { + .catch((err: string | Error) => { console.error('Error updating Android'); core.setFailed(err); }); diff --git a/.github/actions/javascript/checkDeployBlockers/checkDeployBlockers.ts b/.github/actions/javascript/checkDeployBlockers/checkDeployBlockers.ts index bf94b136ce43..d51d68796070 100644 --- a/.github/actions/javascript/checkDeployBlockers/checkDeployBlockers.ts +++ b/.github/actions/javascript/checkDeployBlockers/checkDeployBlockers.ts @@ -60,7 +60,7 @@ const run = function (): Promise { core.setOutput('HAS_DEPLOY_BLOCKERS', false); } }) - .catch((error) => { + .catch((error: string | Error) => { console.error('A problem occurred while trying to communicate with the GitHub API', error); core.setFailed(error); }); diff --git a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts index e725e302eee1..262b603124fa 100644 --- a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts +++ b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts @@ -1,5 +1,6 @@ import * as core from '@actions/core'; import {readFileSync} from 'fs'; +import type {PackageJson} from 'type-fest'; import * as versionUpdater from '@github/libs/versionUpdater'; const semverLevel = core.getInput('SEMVER_LEVEL', {required: true}); @@ -7,6 +8,10 @@ if (!semverLevel || !Object.values(versionUpdater.SEMANTIC_VERSION_LEVEL core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); } -const {version: currentVersion}: {version: string} = JSON.parse(readFileSync('./package.json', 'utf8')); -const previousVersion = versionUpdater.getPreviousVersion(currentVersion, semverLevel); +const {version: currentVersion}: PackageJson = JSON.parse(readFileSync('./package.json', 'utf8')); +if (!currentVersion) { + core.setFailed('Error: Could not read package.json'); +} + +const previousVersion = versionUpdater.getPreviousVersion(currentVersion ?? '', semverLevel); core.setOutput('PREVIOUS_VERSION', previousVersion); diff --git a/.github/actions/javascript/reviewerChecklist/reviewerChecklist.ts b/.github/actions/javascript/reviewerChecklist/reviewerChecklist.ts index aabc6b33086a..f57ef6c36a04 100644 --- a/.github/actions/javascript/reviewerChecklist/reviewerChecklist.ts +++ b/.github/actions/javascript/reviewerChecklist/reviewerChecklist.ts @@ -90,7 +90,7 @@ function checkIssueForCompletedChecklist(numberOfChecklistItems: number) { getNumberOfItemsFromReviewerChecklist() .then(checkIssueForCompletedChecklist) - .catch((err) => { + .catch((err: string | Error) => { console.error(err); core.setFailed(err); }); diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index 822a5650e758..d865ca044779 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -171,7 +171,7 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s */ const showDocumentPicker = useCallback( (): Promise => - RNDocumentPicker.pick(getDocumentPickerOptions(type)).catch((error) => { + RNDocumentPicker.pick(getDocumentPickerOptions(type)).catch((error: TypeError) => { if (RNDocumentPicker.isCancel(error)) { return; } diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index f7bf277050a2..bead38512780 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -123,7 +123,7 @@ function Composer( if (shouldCalculateCaretPosition && isRendered) { // we do flushSync to make sure that the valueBeforeCaret is updated before we calculate the caret position to receive a proper position otherwise we will calculate position for the previous state flushSync(() => { - setValueBeforeCaret(webEvent.target.value.slice(0, webEvent.nativeEvent.selection.start)); + setValueBeforeCaret((webEvent.target as HTMLInputElement).value.slice(0, webEvent.nativeEvent.selection.start)); setCaretContent(getNextChars(value ?? '', webEvent.nativeEvent.selection.start)); }); const selectionValue = { diff --git a/src/components/Icon/__mocks__/Expensicons.ts b/src/components/Icon/__mocks__/Expensicons.ts index 78ad86210bf0..e268b109f0a5 100644 --- a/src/components/Icon/__mocks__/Expensicons.ts +++ b/src/components/Icon/__mocks__/Expensicons.ts @@ -1,4 +1,7 @@ -const Expensicons = jest.requireActual('../Expensicons'); +// eslint-disable-next-line import/no-import-module-exports +import type {SvgProps} from 'react-native-svg'; + +const Expensicons = jest.requireActual>>('../Expensicons'); module.exports = Object.keys(Expensicons).reduce((prev, curr) => { // We set the name of the anonymous mock function here so we can dynamically build the list of mocks and access the diff --git a/src/components/SignInButtons/AppleSignIn/index.ios.tsx b/src/components/SignInButtons/AppleSignIn/index.ios.tsx index 3fb1179d0365..4df8375edad8 100644 --- a/src/components/SignInButtons/AppleSignIn/index.ios.tsx +++ b/src/components/SignInButtons/AppleSignIn/index.ios.tsx @@ -1,4 +1,5 @@ import appleAuth from '@invertase/react-native-apple-authentication'; +import type {AppleError} from '@invertase/react-native-apple-authentication'; import React from 'react'; import IconButton from '@components/SignInButtons/IconButton'; import Log from '@libs/Log'; @@ -35,11 +36,11 @@ function AppleSignIn() { const handleSignIn = () => { appleSignInRequest() .then((token) => Session.beginAppleSignIn(token)) - .catch((e) => { - if (e.code === appleAuth.Error.CANCELED) { + .catch((error: {code: AppleError}) => { + if (error.code === appleAuth.Error.CANCELED) { return null; } - Log.alert('[Apple Sign In] Apple authentication failed', e); + Log.alert('[Apple Sign In] Apple authentication failed', error); }); }; return ( diff --git a/src/libs/Pusher/pusher.ts b/src/libs/Pusher/pusher.ts index cdce408d8d43..d4e17846d412 100644 --- a/src/libs/Pusher/pusher.ts +++ b/src/libs/Pusher/pusher.ts @@ -36,7 +36,9 @@ type PusherEventMap = { [TYPE.USER_IS_LEAVING_ROOM]: UserIsLeavingRoomEvent; }; -type EventData = EventName extends keyof PusherEventMap ? PusherEventMap[EventName] : OnyxUpdatesFromServer; +type EventData = {chunk?: string; id?: string; index?: number; final?: boolean} & (EventName extends keyof PusherEventMap + ? PusherEventMap[EventName] + : OnyxUpdatesFromServer); type EventCallbackError = {type: ValueOf; data: {code: number}}; @@ -164,7 +166,7 @@ function bindEventToChannel(channel: Channel return; } - let data; + let data: EventData; try { data = isObject(eventData) ? eventData : JSON.parse(eventData); } catch (err) { @@ -187,7 +189,9 @@ function bindEventToChannel(channel: Channel // Add it to the rolling list. const chunkedEvent = chunkedDataEvents[data.id]; - chunkedEvent.chunks[data.index] = data.chunk; + if (data.index !== undefined) { + chunkedEvent.chunks[data.index] = data.chunk; + } // If this is the last packet, mark that we've hit the end. if (data.final) { diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index 5f8fa228d191..0f13062b2e94 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -5,6 +5,7 @@ import {addSeconds, format, subMinutes, subSeconds} from 'date-fns'; import {utcToZonedTime} from 'date-fns-tz'; import React from 'react'; import {AppState, DeviceEventEmitter, Linking} from 'react-native'; +import type {ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type Animated from 'react-native-reanimated'; @@ -157,7 +158,10 @@ function scrollUpToRevealNewMessagesBadge() { function isNewMessagesBadgeVisible(): boolean { const hintText = Localize.translateLocal('accessibilityHints.scrollToNewestMessages'); const badge = screen.queryByAccessibilityHint(hintText); - return Math.round(badge?.props.style.transform[0].translateY) === -40; + const badgeProps = badge?.props as {style: ViewStyle}; + const transformStyle = badgeProps.style.transform?.[0] as {translateY: number}; + + return Math.round(transformStyle.translateY) === -40; } function navigateToSidebar(): Promise { diff --git a/tests/utils/collections/reportActions.ts b/tests/utils/collections/reportActions.ts index 65cbb3ba966e..111062f0c63e 100644 --- a/tests/utils/collections/reportActions.ts +++ b/tests/utils/collections/reportActions.ts @@ -2,17 +2,16 @@ import {rand, randAggregation, randBoolean, randWord} from '@ngneat/falso'; import {format} from 'date-fns'; import CONST from '@src/CONST'; import type {ReportAction} from '@src/types/onyx'; +import type {ActionName} from '@src/types/onyx/OriginalMessage'; +import type DeepRecord from '@src/types/utils/DeepRecord'; -type ActionType = keyof typeof CONST.REPORT.ACTIONS.TYPE; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const flattenActionNamesValues = (actionNames: any) => { - let result = [] as ActionType[]; - Object.keys(actionNames).forEach((key) => { - if (typeof actionNames[key] === 'object') { - result = result.concat(flattenActionNamesValues(actionNames[key])); +const flattenActionNamesValues = (actionNames: DeepRecord) => { + let result: ActionName[] = []; + Object.values(actionNames).forEach((value) => { + if (typeof value === 'object') { + result = result.concat(flattenActionNamesValues(value)); } else { - result.push(actionNames[key]); + result.push(value); } }); return result; @@ -81,4 +80,4 @@ export default function createRandomReportAction(index: number): ReportAction { }; } -export {getRandomDate}; +export {getRandomDate, flattenActionNamesValues}; From 9ef0e19b2ac03d7bed487107ab349bb40cd9f454 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 21 May 2024 15:10:13 +0200 Subject: [PATCH 5/8] use better types for errors --- src/components/AttachmentPicker/index.native.tsx | 10 ++-------- src/components/Onfido/BaseOnfidoWeb.tsx | 10 +++------- src/components/Onfido/index.native.tsx | 10 +++------- .../SignInButtons/AppleSignIn/index.android.tsx | 6 +++--- src/libs/actions/Device/index.ts | 10 +--------- tests/e2e/server/index.ts | 10 ++-------- tests/utils/collections/reportActions.ts | 2 +- 7 files changed, 15 insertions(+), 43 deletions(-) diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index d865ca044779..98d03d78e469 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -247,14 +247,8 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s .then((result) => { completeAttachmentSelection.current(result); }) - .catch((error) => { - let errorMessage; - if (error instanceof Error) { - errorMessage = error.message; - } else { - errorMessage = String(error.message); - } - showGeneralAlert(errorMessage); + .catch((error: Error) => { + showGeneralAlert(error.message); throw error; }); }, diff --git a/src/components/Onfido/BaseOnfidoWeb.tsx b/src/components/Onfido/BaseOnfidoWeb.tsx index af9b99efda33..94124180bea3 100644 --- a/src/components/Onfido/BaseOnfidoWeb.tsx +++ b/src/components/Onfido/BaseOnfidoWeb.tsx @@ -1,4 +1,5 @@ import {Onfido as OnfidoSDK} from 'onfido-sdk-ui'; +import type {ErrorType} from 'onfido-sdk-ui/types/Types'; import React, {forwardRef, useEffect} from 'react'; import type {ForwardedRef} from 'react'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; @@ -92,14 +93,9 @@ function initializeOnfido({sdkToken, onSuccess, onError, onUserExit, preferredLo } onSuccess(data); }, - onError: (error) => { - let errorMessage; - if (error instanceof Error) { - errorMessage = error.message; - } else { - errorMessage = CONST.ERROR.UNKNOWN_ERROR; - } + onError: (error: ErrorType) => { const errorType = error.type; + const errorMessage: string = error.message ?? CONST.ERROR.UNKNOWN_ERROR; Log.hmmm('Onfido error', {errorType, errorMessage}); if (errorType === CONST.WALLET.ERROR.ONFIDO_USER_CONSENT_DENIED) { onUserExit(); diff --git a/src/components/Onfido/index.native.tsx b/src/components/Onfido/index.native.tsx index f1f590b46786..10badbcec414 100644 --- a/src/components/Onfido/index.native.tsx +++ b/src/components/Onfido/index.native.tsx @@ -1,4 +1,5 @@ import {OnfidoCaptureType, OnfidoCountryCode, OnfidoDocumentType, Onfido as OnfidoSDK, OnfidoTheme} from '@onfido/react-native-sdk'; +import type {ErrorType} from 'onfido-sdk-ui/types/Types'; import React, {useEffect} from 'react'; import {Alert, Linking} from 'react-native'; import {checkMultiple, PERMISSIONS, RESULTS} from 'react-native-permissions'; @@ -29,13 +30,8 @@ function Onfido({sdkToken, onUserExit, onSuccess, onError}: OnfidoProps) { }, }) .then(onSuccess) - .catch((error) => { - let errorMessage: string; - if (error instanceof Error) { - errorMessage = error.message; - } else { - errorMessage = CONST.ERROR.UNKNOWN_ERROR; - } + .catch((error: ErrorType) => { + const errorMessage: string = error.message ?? CONST.ERROR.UNKNOWN_ERROR; const errorType = error.type; Log.hmmm('Onfido error on native', {errorType, errorMessage}); diff --git a/src/components/SignInButtons/AppleSignIn/index.android.tsx b/src/components/SignInButtons/AppleSignIn/index.android.tsx index 81d360d9f072..a56377940480 100644 --- a/src/components/SignInButtons/AppleSignIn/index.android.tsx +++ b/src/components/SignInButtons/AppleSignIn/index.android.tsx @@ -37,11 +37,11 @@ function AppleSignIn() { const handleSignIn = () => { appleSignInRequest() .then((token) => Session.beginAppleSignIn(token)) - .catch((e) => { - if (e instanceof Error && e.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { + .catch((error) => { + if (error instanceof Error && error.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { return null; } - Log.alert('[Apple Sign In] Apple authentication failed', e); + Log.alert('[Apple Sign In] Apple authentication failed', error); }); }; return ( diff --git a/src/libs/actions/Device/index.ts b/src/libs/actions/Device/index.ts index 5309f67ea91a..ed700c06a97f 100644 --- a/src/libs/actions/Device/index.ts +++ b/src/libs/actions/Device/index.ts @@ -43,15 +43,7 @@ function setDeviceID() { Log.info('Got new deviceID', false, uniqueID); Onyx.set(ONYXKEYS.DEVICE_ID, uniqueID); }) - .catch((err) => { - let errorMessage; - if (err instanceof Error) { - errorMessage = err.message; - } else { - errorMessage = String(err.message); - } - Log.info('Found existing deviceID', false, errorMessage); - }); + .catch((error: Error) => Log.info('Found existing deviceID', false, error.message)); } /** diff --git a/tests/e2e/server/index.ts b/tests/e2e/server/index.ts index 0854c5d29db9..52e50fefc0ae 100644 --- a/tests/e2e/server/index.ts +++ b/tests/e2e/server/index.ts @@ -153,14 +153,8 @@ const createServerInstance = (): ServerInstance => { res.statusCode = 500; res.end('Error executing command'); }) - .catch((error) => { - let errorString; - if (error instanceof Error) { - errorString = error.toString(); - } else { - errorString = String(error); - } - Logger.error('Error executing command', errorString); + .catch((error: string) => { + Logger.error('Error executing command', error); res.statusCode = 500; res.end('Error executing command'); }); diff --git a/tests/utils/collections/reportActions.ts b/tests/utils/collections/reportActions.ts index 111062f0c63e..152358cedb49 100644 --- a/tests/utils/collections/reportActions.ts +++ b/tests/utils/collections/reportActions.ts @@ -80,4 +80,4 @@ export default function createRandomReportAction(index: number): ReportAction { }; } -export {getRandomDate, flattenActionNamesValues}; +export {getRandomDate}; From f926b0d958036499472b2c5bc0f9d31d97c37df7 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 21 May 2024 15:35:19 +0200 Subject: [PATCH 6/8] finish typing --- .../BaseProfilingToolMenu.tsx | 2 +- .../AppleSignIn/index.android.tsx | 4 ++-- src/libs/Middleware/Logging.ts | 21 +++++++++++-------- .../PushNotification/index.native.ts | 2 +- .../step/IOURequestStepScan/index.native.tsx | 6 +++--- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/components/ProfilingToolMenu/BaseProfilingToolMenu.tsx b/src/components/ProfilingToolMenu/BaseProfilingToolMenu.tsx index ff34db881a35..6ab1761fda62 100644 --- a/src/components/ProfilingToolMenu/BaseProfilingToolMenu.tsx +++ b/src/components/ProfilingToolMenu/BaseProfilingToolMenu.tsx @@ -115,7 +115,7 @@ function BaseProfilingToolMenu({isProfilingInProgress = false, pathToBeUsed, dis .then(() => { Log.hmmm('[ProfilingToolMenu] file copied successfully'); }) - .catch((error) => { + .catch((error: Record) => { Log.hmmm('[ProfilingToolMenu] error copying file: ', error); }); diff --git a/src/components/SignInButtons/AppleSignIn/index.android.tsx b/src/components/SignInButtons/AppleSignIn/index.android.tsx index a56377940480..ec669590d029 100644 --- a/src/components/SignInButtons/AppleSignIn/index.android.tsx +++ b/src/components/SignInButtons/AppleSignIn/index.android.tsx @@ -37,8 +37,8 @@ function AppleSignIn() { const handleSignIn = () => { appleSignInRequest() .then((token) => Session.beginAppleSignIn(token)) - .catch((error) => { - if (error instanceof Error && error.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { + .catch((error: Record) => { + if (error.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { return null; } Log.alert('[Apple Sign In] Apple authentication failed', error); diff --git a/src/libs/Middleware/Logging.ts b/src/libs/Middleware/Logging.ts index 19d767c8a4b1..58031c24722e 100644 --- a/src/libs/Middleware/Logging.ts +++ b/src/libs/Middleware/Logging.ts @@ -1,4 +1,5 @@ import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; +import type HttpsError from '@libs/Errors/HttpsError'; import Log from '@libs/Log'; import CONST from '@src/CONST'; import type Request from '@src/types/onyx/Request'; @@ -42,7 +43,7 @@ const Logging: Middleware = (response, request) => { logRequestDetails(`Finished API request in ${Date.now() - startTime}ms`, request, data); return data; }) - .catch((error) => { + .catch((error: HttpsError) => { const logParams: Record = { message: error.message, status: error.status, @@ -64,18 +65,20 @@ const Logging: Middleware = (response, request) => { // incorrect url, bad cors headers returned by the server, DNS lookup failure etc. Log.hmmm('[Network] API request error: Failed to fetch', logParams); } else if ( - [ - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST, - CONST.ERROR.NETWORK_REQUEST_FAILED, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_RUSSIAN, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SWEDISH, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SPANISH, - ].includes(error.message) + ( + [ + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST, + CONST.ERROR.NETWORK_REQUEST_FAILED, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_RUSSIAN, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SWEDISH, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SPANISH, + ] as string[] + ).includes(error.message) ) { // These errors seem to happen for native devices with interrupted connections. Often we will see logs about Pusher disconnecting together with these. // This type of error may also indicate a problem with SSL certs. Log.hmmm('[Network] API request error: Connection interruption likely', logParams); - } else if ([CONST.ERROR.FIREFOX_DOCUMENT_LOAD_ABORTED, CONST.ERROR.SAFARI_DOCUMENT_LOAD_ABORTED].includes(error.message)) { + } else if (([CONST.ERROR.FIREFOX_DOCUMENT_LOAD_ABORTED, CONST.ERROR.SAFARI_DOCUMENT_LOAD_ABORTED] as string[]).includes(error.message)) { // This message can be observed page load is interrupted (closed or navigated away). Log.hmmm('[Network] API request error: User likely navigated away from or closed browser', logParams); } else if (error.message === CONST.ERROR.IOS_LOAD_FAILED) { diff --git a/src/libs/Notification/PushNotification/index.native.ts b/src/libs/Notification/PushNotification/index.native.ts index 426f03c6d408..34699f0610e1 100644 --- a/src/libs/Notification/PushNotification/index.native.ts +++ b/src/libs/Notification/PushNotification/index.native.ts @@ -130,7 +130,7 @@ const register: Register = (notificationID) => { // Refresh notification opt-in status NVP for the new user. refreshNotificationOptInStatus(); }) - .catch((error) => { + .catch((error: Record) => { Log.warn('[PushNotification] Failed to register for push notifications! Reason: ', error); }); }; diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index c022a079df65..b844aa29f670 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -105,11 +105,11 @@ function IOURequestStepScan({ return; } - camera.current.focus(point).catch((ex) => { - if (ex.message === '[unknown/unknown] Cancelled by another startFocusAndMetering()') { + camera.current.focus(point).catch((error: Record) => { + if (error.message === '[unknown/unknown] Cancelled by another startFocusAndMetering()') { return; } - Log.warn('Error focusing camera', ex); + Log.warn('Error focusing camera', error); }); }; From c7237ccc6437564ed2b08015a2cb746ad0549e12 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 21 May 2024 16:15:11 +0200 Subject: [PATCH 7/8] review comments --- .../AttachmentPicker/index.native.tsx | 2 +- src/components/OfflineWithFeedback.tsx | 8 +++++--- src/libs/Middleware/Logging.ts | 18 ++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index 98d03d78e469..218a255d34d3 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -171,7 +171,7 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s */ const showDocumentPicker = useCallback( (): Promise => - RNDocumentPicker.pick(getDocumentPickerOptions(type)).catch((error: TypeError) => { + RNDocumentPicker.pick(getDocumentPickerOptions(type)).catch((error: Error) => { if (RNDocumentPicker.isCancel(error)) { return; } diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx index d96f11a46240..1ff3ee2ed737 100644 --- a/src/components/OfflineWithFeedback.tsx +++ b/src/components/OfflineWithFeedback.tsx @@ -9,6 +9,7 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import type {MaybePhraseKey} from '@libs/Localize'; import mapChildrenFlat from '@libs/mapChildrenFlat'; import shouldRenderOffscreen from '@libs/shouldRenderOffscreen'; +import type {AllStyles} from '@styles/utils/types'; import CONST from '@src/CONST'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {ReceiptError, ReceiptErrors} from '@src/types/onyx/Transaction'; @@ -111,12 +112,13 @@ function OfflineWithFeedback({ return child; } + const childProps: {children: React.ReactNode | undefined; style: AllStyles} = child.props; const props: StrikethroughProps = { - style: StyleUtils.combineStyles(child.props.style, styles.offlineFeedback.deleted, styles.userSelectNone), + style: StyleUtils.combineStyles(childProps.style, styles.offlineFeedback.deleted, styles.userSelectNone), }; - if (child.props.children) { - props.children = applyStrikeThrough(child.props.children as React.ReactNode); + if (childProps.children) { + props.children = applyStrikeThrough(childProps.children); } return React.cloneElement(child, props); diff --git a/src/libs/Middleware/Logging.ts b/src/libs/Middleware/Logging.ts index 58031c24722e..f10e8d2f5120 100644 --- a/src/libs/Middleware/Logging.ts +++ b/src/libs/Middleware/Logging.ts @@ -65,20 +65,18 @@ const Logging: Middleware = (response, request) => { // incorrect url, bad cors headers returned by the server, DNS lookup failure etc. Log.hmmm('[Network] API request error: Failed to fetch', logParams); } else if ( - ( - [ - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST, - CONST.ERROR.NETWORK_REQUEST_FAILED, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_RUSSIAN, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SWEDISH, - CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SPANISH, - ] as string[] - ).includes(error.message) + [ + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST, + CONST.ERROR.NETWORK_REQUEST_FAILED, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_RUSSIAN, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SWEDISH, + CONST.ERROR.IOS_NETWORK_CONNECTION_LOST_SPANISH, + ].some((message) => message === error.message) ) { // These errors seem to happen for native devices with interrupted connections. Often we will see logs about Pusher disconnecting together with these. // This type of error may also indicate a problem with SSL certs. Log.hmmm('[Network] API request error: Connection interruption likely', logParams); - } else if (([CONST.ERROR.FIREFOX_DOCUMENT_LOAD_ABORTED, CONST.ERROR.SAFARI_DOCUMENT_LOAD_ABORTED] as string[]).includes(error.message)) { + } else if ([CONST.ERROR.FIREFOX_DOCUMENT_LOAD_ABORTED, CONST.ERROR.SAFARI_DOCUMENT_LOAD_ABORTED].some((message) => message === error.message)) { // This message can be observed page load is interrupted (closed or navigated away). Log.hmmm('[Network] API request error: User likely navigated away from or closed browser', logParams); } else if (error.message === CONST.ERROR.IOS_LOAD_FAILED) { From c8ca386cf32419453dcaee013d53b72e2a3249d4 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 21 May 2024 16:19:35 +0200 Subject: [PATCH 8/8] rebuild gh actions --- .github/actions/javascript/bumpVersion/index.js | 5 ++++- .github/actions/javascript/getPreviousVersion/index.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/actions/javascript/bumpVersion/index.js b/.github/actions/javascript/bumpVersion/index.js index d4a085fc9ddf..e1a5cf13a8d9 100644 --- a/.github/actions/javascript/bumpVersion/index.js +++ b/.github/actions/javascript/bumpVersion/index.js @@ -3478,7 +3478,10 @@ if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } const { version: previousVersion } = JSON.parse(fs_1.default.readFileSync('./package.json').toString()); -const newVersion = versionUpdater.incrementVersion(previousVersion, semanticVersionLevel); +if (!previousVersion) { + core.setFailed('Error: Could not read package.json'); +} +const newVersion = versionUpdater.incrementVersion(previousVersion ?? '', semanticVersionLevel); console.log(`Previous version: ${previousVersion}`, `New version: ${newVersion}`); updateNativeVersions(newVersion); console.log(`Setting npm version to ${newVersion}`); diff --git a/.github/actions/javascript/getPreviousVersion/index.js b/.github/actions/javascript/getPreviousVersion/index.js index f372f0fdaf99..8eac2f62f03e 100644 --- a/.github/actions/javascript/getPreviousVersion/index.js +++ b/.github/actions/javascript/getPreviousVersion/index.js @@ -2728,7 +2728,10 @@ if (!semverLevel || !Object.values(versionUpdater.SEMANTIC_VERSION_LEVELS).inclu core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); } const { version: currentVersion } = JSON.parse((0, fs_1.readFileSync)('./package.json', 'utf8')); -const previousVersion = versionUpdater.getPreviousVersion(currentVersion, semverLevel); +if (!currentVersion) { + core.setFailed('Error: Could not read package.json'); +} +const previousVersion = versionUpdater.getPreviousVersion(currentVersion ?? '', semverLevel); core.setOutput('PREVIOUS_VERSION', previousVersion);