From 2fbb4615f9038576cb54913c52a08f205ee97e5f Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Wed, 15 Jan 2025 11:20:18 +0000 Subject: [PATCH] Convert utility functions to TypeScript (#22658) * Convert event-tracking to TypeScript * Convert local-storage to TypeScript * Convert mapSeries to TypeScript * Convert SessionStorage to TypeScript * Convert account-upgrade to TypeScript * Convert isValidTeXFile to TypeScript * Convert date functions to TypeScript * Convert EventEmitter to TypeScript * Convert isNetworkError to TypeScript * Convert webpack-public-path to TypeScript * Convert displayNameForUser to TypeScript GitOrigin-RevId: 79c5a2d1101fcd520f3116f0f4af29d974189d94 --- .../components/settings/settings-document.tsx | 2 +- .../change-list/owner-paywall-prompt.tsx | 3 +- .../history/utils/display-name-for-user.ts | 22 +++++++++ .../utils/highlights-from-diff-response.ts | 2 +- .../ide-react/context/outline-context.tsx | 2 +- .../pdf-preview/util/pdf-caching-transport.js | 2 +- .../components/add-collaborators-upgrade.tsx | 2 +- .../access-levels-changed.tsx | 2 +- .../add-collaborators-upgrade.tsx | 2 +- .../components/editor-switch.tsx | 2 +- .../upgrade-track-changes-modal.tsx | 2 +- .../hooks/use-codemirror-scope.ts | 4 +- .../js/ide/history/util/displayNameForUser.js | 24 --------- .../{event-tracking.js => event-tracking.ts} | 44 ++++++++++++----- .../{local-storage.js => local-storage.ts} | 21 +++++--- .../web/frontend/js/infrastructure/promise.js | 16 ------ .../web/frontend/js/infrastructure/promise.ts | 13 +++++ ...{session-storage.js => session-storage.ts} | 21 +++++--- .../web/frontend/js/main/account-upgrade.js | 49 ------------------- .../web/frontend/js/main/account-upgrade.ts | 29 +++++++++++ ...valid-tex-file.js => is-valid-tex-file.ts} | 4 +- .../web/frontend/js/pages/project-list.tsx | 2 +- .../web/frontend/js/pages/sharing-updates.tsx | 2 +- .../web/frontend/js/pages/token-access.tsx | 2 +- .../web/frontend/js/pages/user/settings.jsx | 2 +- .../js/pages/user/subscription/base.js | 2 +- .../components/start-free-trial-button.tsx | 4 +- .../{EventEmitter.js => EventEmitter.ts} | 24 ++++++--- .../frontend/js/utils/{dates.js => dates.ts} | 4 +- ...{isNetworkError.js => is-network-error.ts} | 4 +- ...-public-path.js => webpack-public-path.ts} | 0 .../settings/leavers-survey-alert.stories.tsx | 2 +- .../pdf-preview/pdf-preview.spec.tsx | 2 +- .../settings/settings-document.test.tsx | 15 +++--- .../layout-dropdown-button.test.jsx | 2 +- .../utils/display-name-for-user.test.ts} | 17 ++----- .../components/current-plan-widget.test.tsx | 2 +- .../components/notifications.test.tsx | 2 +- .../components/project-list-root.test.tsx | 2 +- .../components/project-search.test.tsx | 2 +- ...e-and-download-project-pdf-button.test.tsx | 2 +- .../table/projects-action-modal.test.tsx | 2 +- .../components/leavers-survey-alert.test.tsx | 4 +- .../linking/integration-widget.test.tsx | 2 +- .../settings/components/root.test.tsx | 2 +- .../context/user-email-context.test.tsx | 2 +- .../dashboard/states/active/active.test.tsx | 2 +- .../infrastructure/local-storage.test.js | 2 +- .../shared/components/notification.test.tsx | 2 +- .../shared/hooks/use-persisted-state.test.tsx | 2 +- .../test/frontend/utils/EventEmitterTests.js | 29 ++++------- services/web/types/window.ts | 2 + 52 files changed, 203 insertions(+), 210 deletions(-) create mode 100644 services/web/frontend/js/features/history/utils/display-name-for-user.ts delete mode 100644 services/web/frontend/js/ide/history/util/displayNameForUser.js rename services/web/frontend/js/infrastructure/{event-tracking.js => event-tracking.ts} (68%) rename services/web/frontend/js/infrastructure/{local-storage.js => local-storage.ts} (62%) delete mode 100644 services/web/frontend/js/infrastructure/promise.js create mode 100644 services/web/frontend/js/infrastructure/promise.ts rename services/web/frontend/js/infrastructure/{session-storage.js => session-storage.ts} (63%) delete mode 100644 services/web/frontend/js/main/account-upgrade.js create mode 100644 services/web/frontend/js/main/account-upgrade.ts rename services/web/frontend/js/main/{is-valid-tex-file.js => is-valid-tex-file.ts} (76%) rename services/web/frontend/js/utils/{EventEmitter.js => EventEmitter.ts} (77%) rename services/web/frontend/js/utils/{dates.js => dates.ts} (58%) rename services/web/frontend/js/utils/{isNetworkError.js => is-network-error.ts} (96%) rename services/web/frontend/js/utils/{webpack-public-path.js => webpack-public-path.ts} (100%) rename services/web/test/frontend/{ide/history/util/displayNameForUserTests.js => features/history/utils/display-name-for-user.test.ts} (76%) diff --git a/services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx b/services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx index 5bff9be999..7a9e7c0c30 100644 --- a/services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx +++ b/services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import isValidTeXFile from '../../../../main/is-valid-tex-file' +import { isValidTeXFile } from '../../../../main/is-valid-tex-file' import { useEditorContext } from '../../../../shared/context/editor-context' import { useProjectSettingsContext } from '../../context/project-settings-context' import SettingsMenuSelect from './settings-menu-select' diff --git a/services/web/frontend/js/features/history/components/change-list/owner-paywall-prompt.tsx b/services/web/frontend/js/features/history/components/change-list/owner-paywall-prompt.tsx index 736940c16b..e81b58a277 100644 --- a/services/web/frontend/js/features/history/components/change-list/owner-paywall-prompt.tsx +++ b/services/web/frontend/js/features/history/components/change-list/owner-paywall-prompt.tsx @@ -3,7 +3,6 @@ import Icon from '../../../../shared/components/icon' import { useCallback, useEffect, useState } from 'react' import * as eventTracking from '../../../../infrastructure/event-tracking' import StartFreeTrialButton from '../../../../shared/components/start-free-trial-button' -import { paywallPrompt } from '../../../../main/account-upgrade' import { useFeatureFlag } from '@/shared/context/split-test-context' function FeatureItem({ text }: { text: string }) { @@ -22,7 +21,7 @@ export function OwnerPaywallPrompt() { useEffect(() => { eventTracking.send('subscription-funnel', 'editor-click-feature', 'history') - paywallPrompt('history') + eventTracking.sendMB('paywall-prompt', { 'paywall-type': 'history' }) }, []) const handleFreeTrialClick = useCallback(() => { diff --git a/services/web/frontend/js/features/history/utils/display-name-for-user.ts b/services/web/frontend/js/features/history/utils/display-name-for-user.ts new file mode 100644 index 0000000000..626e8994bd --- /dev/null +++ b/services/web/frontend/js/features/history/utils/display-name-for-user.ts @@ -0,0 +1,22 @@ +import { User } from '@/features/history/services/types/shared' +import getMeta from '@/utils/meta' +import { formatUserName } from '@/features/history/utils/history-details' + +export default function displayNameForUser( + user: + | (User & { + name?: string + }) + | null +) { + if (user == null) { + return 'Anonymous' + } + if (user.id === getMeta('ol-user').id) { + return 'you' + } + if (user.name != null) { + return user.name + } + return formatUserName(user) +} diff --git a/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts b/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts index eddc55a8cc..bdcc087ab1 100644 --- a/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts +++ b/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts @@ -1,8 +1,8 @@ -import displayNameForUser from '../../../ide/history/util/displayNameForUser' import moment from 'moment/moment' import ColorManager from '../../../ide/colors/ColorManager' import { DocDiffChunk, Highlight } from '../services/types/doc' import { TFunction } from 'i18next' +import displayNameForUser from './display-name-for-user' export function highlightsFromDiffResponse( chunks: DocDiffChunk[], diff --git a/services/web/frontend/js/features/ide-react/context/outline-context.tsx b/services/web/frontend/js/features/ide-react/context/outline-context.tsx index 4711103859..ac64033897 100644 --- a/services/web/frontend/js/features/ide-react/context/outline-context.tsx +++ b/services/web/frontend/js/features/ide-react/context/outline-context.tsx @@ -12,7 +12,7 @@ import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter' import useEventListener from '@/shared/hooks/use-event-listener' import * as eventTracking from '@/infrastructure/event-tracking' import useScopeValue from '@/shared/hooks/use-scope-value' -import isValidTeXFile from '@/main/is-valid-tex-file' +import { isValidTeXFile } from '@/main/is-valid-tex-file' import localStorage from '@/infrastructure/local-storage' import { useProjectContext } from '@/shared/context/project-context' diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js index 5fb7e66f9a..cb7433ee52 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js @@ -9,7 +9,7 @@ import { prefetchLargeEnabled, trackPdfDownloadEnabled, } from './pdf-caching-flags' -import { isNetworkError } from '@/utils/isNetworkError' +import { isNetworkError } from '@/utils/is-network-error' import { debugConsole } from '@/utils/debugging' import { PDFJS } from './pdf-js' diff --git a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.tsx b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.tsx index d34f70e4da..8e485d6d35 100644 --- a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.tsx +++ b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' import { useUserContext } from '../../../shared/context/user-context' -import { upgradePlan } from '../../../main/account-upgrade' +import { upgradePlan } from '@/main/account-upgrade' import StartFreeTrialButton from '../../../shared/components/start-free-trial-button' import Icon from '../../../shared/components/icon' import { useFeatureFlag } from '../../../shared/context/split-test-context' diff --git a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/access-levels-changed.tsx b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/access-levels-changed.tsx index 6fbf4d6bed..e0ac152a58 100644 --- a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/access-levels-changed.tsx +++ b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/access-levels-changed.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' import Notification from '@/shared/components/notification' -import { upgradePlan } from '../../../../main/account-upgrade' +import { upgradePlan } from '@/main/account-upgrade' import { useProjectContext } from '@/shared/context/project-context' import { useUserContext } from '@/shared/context/user-context' import { sendMB } from '@/infrastructure/event-tracking' diff --git a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/add-collaborators-upgrade.tsx b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/add-collaborators-upgrade.tsx index 5645192a09..6619b41a5d 100644 --- a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/add-collaborators-upgrade.tsx +++ b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/add-collaborators-upgrade.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' import Notification from '@/shared/components/notification' -import { upgradePlan } from '../../../../main/account-upgrade' +import { upgradePlan } from '@/main/account-upgrade' import { linkSharingEnforcementDate } from '../../utils/link-sharing' import { useProjectContext } from '@/shared/context/project-context' import { useUserContext } from '@/shared/context/user-context' diff --git a/services/web/frontend/js/features/source-editor/components/editor-switch.tsx b/services/web/frontend/js/features/source-editor/components/editor-switch.tsx index c8f53190d2..8df024ee99 100644 --- a/services/web/frontend/js/features/source-editor/components/editor-switch.tsx +++ b/services/web/frontend/js/features/source-editor/components/editor-switch.tsx @@ -3,7 +3,7 @@ import useScopeValue from '@/shared/hooks/use-scope-value' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import useTutorial from '@/shared/hooks/promotions/use-tutorial' import { sendMB } from '../../../infrastructure/event-tracking' -import isValidTeXFile from '../../../main/is-valid-tex-file' +import { isValidTeXFile } from '../../../main/is-valid-tex-file' import { useTranslation } from 'react-i18next' import { EditorSwitchBeginnerTooltip, diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/upgrade-track-changes-modal.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/upgrade-track-changes-modal.tsx index 4045ada811..a4b54b9e26 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/upgrade-track-changes-modal.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/upgrade-track-changes-modal.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import Icon from '../../../../shared/components/icon' import { useProjectContext } from '../../../../shared/context/project-context' import { useUserContext } from '../../../../shared/context/user-context' -import { startFreeTrial, upgradePlan } from '../../../../main/account-upgrade' +import { startFreeTrial, upgradePlan } from '@/main/account-upgrade' import { memo } from 'react' import { useFeatureFlag } from '@/shared/context/split-test-context' import OLModal, { diff --git a/services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts b/services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts index 1965724654..7d6a8e6589 100644 --- a/services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts +++ b/services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts @@ -47,7 +47,7 @@ import { setVisual } from '../extensions/visual/visual' import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path' import { useUserSettingsContext } from '@/shared/context/user-settings-context' import { setDocName } from '@/features/source-editor/extensions/doc-name' -import isValidTexFile from '@/main/is-valid-tex-file' +import { isValidTeXFile } from '@/main/is-valid-tex-file' import { captureException } from '@/infrastructure/error-reporter' import grammarlyExtensionPresent from '@/shared/utils/grammarly' import { DocumentContainer } from '@/features/ide-react/editor/document-container' @@ -288,7 +288,7 @@ function useCodeMirrorScope(view: EditorView) { const { previewByPath } = useFileTreePathContext() - const showVisual = visual && isValidTexFile(docName) + const showVisual = visual && isValidTeXFile(docName) const visualRef = useRef({ previewByPath, diff --git a/services/web/frontend/js/ide/history/util/displayNameForUser.js b/services/web/frontend/js/ide/history/util/displayNameForUser.js deleted file mode 100644 index dbdfec8f0b..0000000000 --- a/services/web/frontend/js/ide/history/util/displayNameForUser.js +++ /dev/null @@ -1,24 +0,0 @@ -import getMeta from '@/utils/meta' - -export default function displayNameForUser(user) { - if (user == null) { - return 'Anonymous' - } - if (user.id === getMeta('ol-user').id) { - return 'you' - } - if (user.name != null) { - return user.name - } - let name = [user.first_name, user.last_name] - .filter(n => n != null) - .join(' ') - .trim() - if (name === '') { - name = user.email.split('@')[0] - } - if (name == null || name === '') { - return '?' - } - return name -} diff --git a/services/web/frontend/js/infrastructure/event-tracking.js b/services/web/frontend/js/infrastructure/event-tracking.ts similarity index 68% rename from services/web/frontend/js/infrastructure/event-tracking.js rename to services/web/frontend/js/infrastructure/event-tracking.ts index 1c67b10aac..698f5df425 100644 --- a/services/web/frontend/js/infrastructure/event-tracking.js +++ b/services/web/frontend/js/infrastructure/event-tracking.ts @@ -1,25 +1,40 @@ -import sessionStorage from '../infrastructure/session-storage' +import sessionStorage from './session-storage' import getMeta from '@/utils/meta' +type Segmentation = Record< + string, + string | number | boolean | undefined | unknown | any // TODO: RecurlyError +> + const CACHE_KEY = 'mbEvents' -function alreadySent(key) { +function alreadySent(key: string) { const eventCache = sessionStorage.getItem(CACHE_KEY) || {} return !!eventCache[key] } -function markAsSent(key) { +function markAsSent(key: string) { const eventCache = sessionStorage.getItem(CACHE_KEY) || {} eventCache[key] = true sessionStorage.setItem(CACHE_KEY, eventCache) } -export function send(category, action, label, value) { +export function send( + category: string, + action: string, + label?: string, + value?: string +) { if (typeof window.ga === 'function') { window.ga('send', 'event', category, action, label, value) } } -export function sendOnce(category, action, label, value) { +export function sendOnce( + category: string, + action: string, + label: string, + value: string +) { if (alreadySent(category)) return if (typeof window.ga !== 'function') return @@ -27,7 +42,7 @@ export function sendOnce(category, action, label, value) { markAsSent(category) } -export function sendMB(key, segmentation = {}) { +export function sendMB(key: string, segmentation: Segmentation = {}) { if (!segmentation.page) { segmentation.page = window.location.pathname } @@ -40,21 +55,28 @@ export function sendMB(key, segmentation = {}) { } } -export function sendMBOnce(key, segmentation = {}) { +export function sendMBOnce(key: string, segmentation: Segmentation = {}) { if (alreadySent(key)) return sendMB(key, segmentation) markAsSent(key) } -export function sendMBSampled(key, body = {}, rate = 0.01) { +export function sendMBSampled( + key: string, + segmentation: Segmentation = {}, + rate = 0.01 +) { if (Math.random() < rate) { - sendMB(key, body) + sendMB(key, segmentation) } } const sentOncePerPageLoad = new Set() -export function sendMBOncePerPageLoad(key, segmentation = {}) { +export function sendMBOncePerPageLoad( + key: string, + segmentation: Segmentation = {} +) { if (sentOncePerPageLoad.has(key)) return sendMB(key, segmentation) sentOncePerPageLoad.add(key) @@ -66,7 +88,7 @@ export function sendMBOncePerPageLoad(key, segmentation = {}) { // @screen-sm: 768px; export const isSmallDevice = window.screen.width < 768 -function sendBeacon(key, data) { +function sendBeacon(key: string, data: Segmentation) { if (!navigator || !navigator.sendBeacon) return if (!getMeta('ol-ExposedSettings').isOverleaf) return diff --git a/services/web/frontend/js/infrastructure/local-storage.js b/services/web/frontend/js/infrastructure/local-storage.ts similarity index 62% rename from services/web/frontend/js/infrastructure/local-storage.js rename to services/web/frontend/js/infrastructure/local-storage.ts index 4ae017f82f..69738dded4 100644 --- a/services/web/frontend/js/infrastructure/local-storage.js +++ b/services/web/frontend/js/infrastructure/local-storage.ts @@ -12,7 +12,11 @@ import { debugConsole } from '@/utils/debugging' * @param {string?} key Key passed to the localStorage function (if any) * @param {any?} value Value passed to the localStorage function (if any) */ -const callSafe = function (fn, key, value) { +const callSafe = function ( + fn: (...args: any) => any, + key?: string, + value?: any +) { try { return fn(key, value) } catch (e) { @@ -21,11 +25,12 @@ const callSafe = function (fn, key, value) { } } -const getItem = function (key) { - return JSON.parse(localStorage.getItem(key)) +const getItem = function (key: string) { + const value = localStorage.getItem(key) + return value === null ? null : JSON.parse(value) } -const setItem = function (key, value) { +const setItem = function (key: string, value: any) { localStorage.setItem(key, JSON.stringify(value)) } @@ -33,15 +38,15 @@ const clear = function () { localStorage.clear() } -const removeItem = function (key) { +const removeItem = function (key: string) { return localStorage.removeItem(key) } const customLocalStorage = { - getItem: key => callSafe(getItem, key), - setItem: (key, value) => callSafe(setItem, key, value), + getItem: (key: string) => callSafe(getItem, key), + setItem: (key: string, value: any) => callSafe(setItem, key, value), clear: () => callSafe(clear), - removeItem: key => callSafe(removeItem, key), + removeItem: (key: string) => callSafe(removeItem, key), } export default customLocalStorage diff --git a/services/web/frontend/js/infrastructure/promise.js b/services/web/frontend/js/infrastructure/promise.js deleted file mode 100644 index 58a0bd67d4..0000000000 --- a/services/web/frontend/js/infrastructure/promise.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * run `fn` in serie for all values, and resolve with an array of the results - * inspired by https://stackoverflow.com/a/50506360/1314820 - * @template T the input array's item type - * @template V the `fn` function's return type - * @param {T[]} values - * @param {(item: T) => Promise} fn - * @returns {V[]} - */ -export function mapSeries(values, fn) { - return values.reduce(async (promiseChain, value) => { - const chainResults = await promiseChain - const currentResult = await fn(value) - return [...chainResults, currentResult] - }, Promise.resolve([])) -} diff --git a/services/web/frontend/js/infrastructure/promise.ts b/services/web/frontend/js/infrastructure/promise.ts new file mode 100644 index 0000000000..edbfc0114c --- /dev/null +++ b/services/web/frontend/js/infrastructure/promise.ts @@ -0,0 +1,13 @@ +/** + * run `fn` in series for all values, and resolve with an array of the results + */ +export const mapSeries = async ( + values: T[], + fn: (item: T) => Promise +) => { + const output: V[] = [] + for (const value of values) { + output.push(await fn(value)) + } + return output +} diff --git a/services/web/frontend/js/infrastructure/session-storage.js b/services/web/frontend/js/infrastructure/session-storage.ts similarity index 63% rename from services/web/frontend/js/infrastructure/session-storage.js rename to services/web/frontend/js/infrastructure/session-storage.ts index 1e2757874f..09c5dcbcee 100644 --- a/services/web/frontend/js/infrastructure/session-storage.js +++ b/services/web/frontend/js/infrastructure/session-storage.ts @@ -12,7 +12,11 @@ import { debugConsole } from '@/utils/debugging' * @param {string?} key Key passed to the sessionStorage function (if any) * @param {any?} value Value passed to the sessionStorage function (if any) */ -const callSafe = function (fn, key, value) { +const callSafe = function ( + fn: (...args: any) => any, + key?: string, + value?: any +) { try { return fn(key, value) } catch (e) { @@ -21,11 +25,12 @@ const callSafe = function (fn, key, value) { } } -const getItem = function (key) { - return JSON.parse(sessionStorage.getItem(key)) +const getItem = function (key: string) { + const value = sessionStorage.getItem(key) + return value === null ? null : JSON.parse(value) } -const setItem = function (key, value) { +const setItem = function (key: string, value: any) { sessionStorage.setItem(key, JSON.stringify(value)) } @@ -33,15 +38,15 @@ const clear = function () { sessionStorage.clear() } -const removeItem = function (key) { +const removeItem = function (key: string) { return sessionStorage.removeItem(key) } const customSessionStorage = { - getItem: key => callSafe(getItem, key), - setItem: (key, value) => callSafe(setItem, key, value), + getItem: (key: string) => callSafe(getItem, key), + setItem: (key: string, value: any) => callSafe(setItem, key, value), clear: () => callSafe(clear), - removeItem: key => callSafe(removeItem, key), + removeItem: (key: string) => callSafe(removeItem, key), } export default customSessionStorage diff --git a/services/web/frontend/js/main/account-upgrade.js b/services/web/frontend/js/main/account-upgrade.js deleted file mode 100644 index e1997a3a81..0000000000 --- a/services/web/frontend/js/main/account-upgrade.js +++ /dev/null @@ -1,49 +0,0 @@ -import * as eventTracking from '../infrastructure/event-tracking' - -function startFreeTrial(source, version, $scope, variant) { - const eventSegmentation = { 'paywall-type': source } - if (variant) { - eventSegmentation.variant = variant - } - - eventTracking.send('subscription-funnel', 'upgraded-free-trial', source) - eventTracking.sendMB('paywall-click', eventSegmentation) - - const searchParams = new URLSearchParams({ - itm_campaign: source, - }) - - if (version) { - searchParams.set('itm_content', version) - } - - if ($scope) { - $scope.startedFreeTrial = true - } - - window.open(`/user/subscription/choose-your-plan?${searchParams.toString()}`) -} - -function upgradePlan(source, $scope) { - const w = window.open() - const go = function () { - if (typeof ga === 'function') { - ga('send', 'event', 'subscription-funnel', 'upgraded-plan', source) - } - const url = '/user/subscription' - - if ($scope) { - $scope.startedFreeTrial = true - } - - w.location = url - } - - go() -} - -function paywallPrompt(source) { - eventTracking.sendMB('paywall-prompt', { 'paywall-type': source }) -} - -export { startFreeTrial, upgradePlan, paywallPrompt } diff --git a/services/web/frontend/js/main/account-upgrade.ts b/services/web/frontend/js/main/account-upgrade.ts new file mode 100644 index 0000000000..9aa2490768 --- /dev/null +++ b/services/web/frontend/js/main/account-upgrade.ts @@ -0,0 +1,29 @@ +import * as eventTracking from '../infrastructure/event-tracking' + +export function startFreeTrial(source: string, variant?: string) { + const eventSegmentation: Record = { 'paywall-type': source } + if (variant) { + eventSegmentation.variant = variant + } + + eventTracking.send('subscription-funnel', 'upgraded-free-trial', source) + eventTracking.sendMB('paywall-click', eventSegmentation) + + const searchParams = new URLSearchParams({ + itm_campaign: source, + }) + + window.open(`/user/subscription/choose-your-plan?${searchParams.toString()}`) +} + +export function upgradePlan(source: string) { + const openedWindow = window.open() + + if (typeof window.ga === 'function') { + window.ga('send', 'event', 'subscription-funnel', 'upgraded-plan', source) + } + + if (openedWindow) { + openedWindow.location = '/user/subscription' + } +} diff --git a/services/web/frontend/js/main/is-valid-tex-file.js b/services/web/frontend/js/main/is-valid-tex-file.ts similarity index 76% rename from services/web/frontend/js/main/is-valid-tex-file.js rename to services/web/frontend/js/main/is-valid-tex-file.ts index e0159d2c79..005d6f92bb 100644 --- a/services/web/frontend/js/main/is-valid-tex-file.js +++ b/services/web/frontend/js/main/is-valid-tex-file.ts @@ -1,6 +1,6 @@ import getMeta from '@/utils/meta' -function isValidTeXFile(filename) { +export const isValidTeXFile = (filename: string) => { const validTeXFileRegExp = new RegExp( `\\.(${getMeta('ol-ExposedSettings').validRootDocExtensions.join('|')})$`, 'i' @@ -8,5 +8,3 @@ function isValidTeXFile(filename) { return validTeXFileRegExp.test(filename) } - -export default isValidTeXFile diff --git a/services/web/frontend/js/pages/project-list.tsx b/services/web/frontend/js/pages/project-list.tsx index 60fcda413c..dd24bb00f9 100644 --- a/services/web/frontend/js/pages/project-list.tsx +++ b/services/web/frontend/js/pages/project-list.tsx @@ -1,5 +1,5 @@ import './../utils/meta' -import './../utils/webpack-public-path' +import '../utils/webpack-public-path' import './../infrastructure/error-reporter' import '@/i18n' import '../features/event-tracking' diff --git a/services/web/frontend/js/pages/sharing-updates.tsx b/services/web/frontend/js/pages/sharing-updates.tsx index 429bc8f57c..63219542ef 100644 --- a/services/web/frontend/js/pages/sharing-updates.tsx +++ b/services/web/frontend/js/pages/sharing-updates.tsx @@ -1,5 +1,5 @@ import './../utils/meta' -import './../utils/webpack-public-path' +import '../utils/webpack-public-path' import './../infrastructure/error-reporter' import '@/i18n' import ReactDOM from 'react-dom' diff --git a/services/web/frontend/js/pages/token-access.tsx b/services/web/frontend/js/pages/token-access.tsx index f18cd1e541..97026d93f4 100644 --- a/services/web/frontend/js/pages/token-access.tsx +++ b/services/web/frontend/js/pages/token-access.tsx @@ -1,5 +1,5 @@ import './../utils/meta' -import './../utils/webpack-public-path' +import '../utils/webpack-public-path' import './../infrastructure/error-reporter' import '@/i18n' import ReactDOM from 'react-dom' diff --git a/services/web/frontend/js/pages/user/settings.jsx b/services/web/frontend/js/pages/user/settings.jsx index b31d1c4d5c..bd55a175d9 100644 --- a/services/web/frontend/js/pages/user/settings.jsx +++ b/services/web/frontend/js/pages/user/settings.jsx @@ -1,6 +1,6 @@ import '../../marketing' import './../../utils/meta' -import './../../utils/webpack-public-path' +import '../../utils/webpack-public-path' import './../../infrastructure/error-reporter' import '@/i18n' import '../../features/settings/components/root' diff --git a/services/web/frontend/js/pages/user/subscription/base.js b/services/web/frontend/js/pages/user/subscription/base.js index 7773ac9bb2..4aa63cf159 100644 --- a/services/web/frontend/js/pages/user/subscription/base.js +++ b/services/web/frontend/js/pages/user/subscription/base.js @@ -1,5 +1,5 @@ import './../../../utils/meta' -import './../../../utils/webpack-public-path' +import '../../../utils/webpack-public-path' import './../../../infrastructure/error-reporter' import '@/i18n' import '../../../features/event-tracking' diff --git a/services/web/frontend/js/shared/components/start-free-trial-button.tsx b/services/web/frontend/js/shared/components/start-free-trial-button.tsx index 0f3c159cbf..3389ebd2af 100644 --- a/services/web/frontend/js/shared/components/start-free-trial-button.tsx +++ b/services/web/frontend/js/shared/components/start-free-trial-button.tsx @@ -1,6 +1,6 @@ import { MouseEventHandler, useCallback, useEffect } from 'react' import { useTranslation } from 'react-i18next' -import { startFreeTrial } from '../../main/account-upgrade' +import { startFreeTrial } from '@/main/account-upgrade' import * as eventTracking from '../../infrastructure/event-tracking' import OLButton from '@/features/ui/components/ol/ol-button' @@ -41,7 +41,7 @@ export default function StartFreeTrialButton({ handleClick(event) } - startFreeTrial(source, null, null, variant) + startFreeTrial(source, variant) }, [handleClick, source, variant] ) diff --git a/services/web/frontend/js/utils/EventEmitter.js b/services/web/frontend/js/utils/EventEmitter.ts similarity index 77% rename from services/web/frontend/js/utils/EventEmitter.js rename to services/web/frontend/js/utils/EventEmitter.ts index 3ed66cdc41..753cd2423b 100644 --- a/services/web/frontend/js/utils/EventEmitter.js +++ b/services/web/frontend/js/utils/EventEmitter.ts @@ -7,11 +7,19 @@ // Remove a listener for the foo event with the bar namespace: .off 'foo.bar' export default class EventEmitter { + events: Record< + string, + { + callback: (...args: any[]) => void + namespace: string + }[] + > + constructor() { this.events = {} } - on(event, callback) { + on(event: string, callback: (...args: any[]) => void) { if (!this.events) { this.events = {} } @@ -26,7 +34,7 @@ export default class EventEmitter { }) } - off(event, cb) { + off(event?: string, callback?: (...args: any[]) => void) { if (!this.events) { this.events = {} } @@ -36,8 +44,10 @@ export default class EventEmitter { if (!this.events[event]) { this.events[event] = [] } - if (cb) { - this.events[event] = this.events[event].filter(e => e.callback !== cb) + if (callback) { + this.events[event] = this.events[event].filter( + e => e.callback !== callback + ) } else if (!namespace) { // Clear all listeners for event delete this.events[event] @@ -53,7 +63,7 @@ export default class EventEmitter { } } - trigger(event, ...args) { + trigger(event: string, ...args: any[]) { if (!this.events) { this.events = {} } @@ -62,7 +72,7 @@ export default class EventEmitter { } } - emit(...args) { - this.trigger(...args) + emit(event: string, ...args: any[]) { + this.trigger(event, ...args) } } diff --git a/services/web/frontend/js/utils/dates.js b/services/web/frontend/js/utils/dates.ts similarity index 58% rename from services/web/frontend/js/utils/dates.js rename to services/web/frontend/js/utils/dates.ts index b1478da5d2..b4dd84f822 100644 --- a/services/web/frontend/js/utils/dates.js +++ b/services/web/frontend/js/utils/dates.ts @@ -1,6 +1,6 @@ import moment from 'moment' -export function formatDate(date, format) { +export function formatDate(date: moment.MomentInput, format?: string) { if (!date) return 'N/A' if (format == null) { format = 'Do MMM YYYY, h:mm a' @@ -8,6 +8,6 @@ export function formatDate(date, format) { return moment(date).format(format) } -export function fromNowDate(date) { +export function fromNowDate(date: moment.MomentInput | string) { return moment(date).fromNow() } diff --git a/services/web/frontend/js/utils/isNetworkError.js b/services/web/frontend/js/utils/is-network-error.ts similarity index 96% rename from services/web/frontend/js/utils/isNetworkError.js rename to services/web/frontend/js/utils/is-network-error.ts index cfb592436d..95d4fb2750 100644 --- a/services/web/frontend/js/utils/isNetworkError.js +++ b/services/web/frontend/js/utils/is-network-error.ts @@ -68,6 +68,6 @@ const NETWORK_ERRORS = [ '요청한 시간이 초과되었습니다.', ] -export function isNetworkError(err) { - return NETWORK_ERRORS.includes(err?.message) +export function isNetworkError(err?: Error) { + return err && NETWORK_ERRORS.includes(err.message) } diff --git a/services/web/frontend/js/utils/webpack-public-path.js b/services/web/frontend/js/utils/webpack-public-path.ts similarity index 100% rename from services/web/frontend/js/utils/webpack-public-path.js rename to services/web/frontend/js/utils/webpack-public-path.ts diff --git a/services/web/frontend/stories/settings/leavers-survey-alert.stories.tsx b/services/web/frontend/stories/settings/leavers-survey-alert.stories.tsx index 6a1662e35c..075061ab12 100644 --- a/services/web/frontend/stories/settings/leavers-survey-alert.stories.tsx +++ b/services/web/frontend/stories/settings/leavers-survey-alert.stories.tsx @@ -1,7 +1,7 @@ import EmailsSection from '../../js/features/settings/components/emails-section' import { UserEmailsProvider } from '../../js/features/settings/context/user-email-context' import { LeaversSurveyAlert } from '../../js/features/settings/components/leavers-survey-alert' -import localStorage from '../../js/infrastructure/local-storage' +import localStorage from '@/infrastructure/local-storage' import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher' export const SurveyAlert = () => { diff --git a/services/web/test/frontend/components/pdf-preview/pdf-preview.spec.tsx b/services/web/test/frontend/components/pdf-preview/pdf-preview.spec.tsx index 1f46407f6e..8f61cfc9bf 100644 --- a/services/web/test/frontend/components/pdf-preview/pdf-preview.spec.tsx +++ b/services/web/test/frontend/components/pdf-preview/pdf-preview.spec.tsx @@ -1,5 +1,5 @@ import '../../helpers/bootstrap-3' -import localStorage from '../../../../frontend/js/infrastructure/local-storage' +import localStorage from '@/infrastructure/local-storage' import PdfPreview from '../../../../frontend/js/features/pdf-preview/components/pdf-preview' import { EditorProviders } from '../../helpers/editor-providers' import { mockScope } from './scope' diff --git a/services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx b/services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx index 6d3c147cc1..c46e3a6497 100644 --- a/services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx +++ b/services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx @@ -1,17 +1,13 @@ import { screen, within } from '@testing-library/dom' import { expect } from 'chai' -import sinon from 'sinon' import fetchMock from 'fetch-mock' import SettingsDocument from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-document' -import * as isValidTeXFileModule from '../../../../../../frontend/js/main/is-valid-tex-file' import { Folder } from '../../../../../../types/folder' import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context' import { render } from '@testing-library/react' import { EditorProviders } from '../../../../helpers/editor-providers' describe('', function () { - let isValidTeXFileStub: sinon.SinonStub - const rootFolder: Folder = { _id: 'root-folder-id', name: 'rootFolder', @@ -25,15 +21,18 @@ describe('', function () { folders: [], } + let originalSettings: typeof window.metaAttributesCache + beforeEach(function () { - isValidTeXFileStub = sinon - .stub(isValidTeXFileModule, 'default') - .returns(true) + originalSettings = window.metaAttributesCache.get('ol-ExposedSettings') + window.metaAttributesCache.set('ol-ExposedSettings', { + validRootDocExtensions: ['tex'], + }) }) afterEach(function () { fetchMock.reset() - isValidTeXFileStub.restore() + window.metaAttributesCache.set('ol-ExposedSettings', originalSettings) }) it('shows correct menu', async function () { diff --git a/services/web/test/frontend/features/editor-navigation-toolbar/components/layout-dropdown-button.test.jsx b/services/web/test/frontend/features/editor-navigation-toolbar/components/layout-dropdown-button.test.jsx index c0331ba80c..648c62feb5 100644 --- a/services/web/test/frontend/features/editor-navigation-toolbar/components/layout-dropdown-button.test.jsx +++ b/services/web/test/frontend/features/editor-navigation-toolbar/components/layout-dropdown-button.test.jsx @@ -4,7 +4,7 @@ import { expect } from 'chai' import { fireEvent, screen } from '@testing-library/react' import LayoutDropdownButton from '../../../../../frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button' import { renderWithEditorContext } from '../../../helpers/render-with-context' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' describe('', function () { let openStub diff --git a/services/web/test/frontend/ide/history/util/displayNameForUserTests.js b/services/web/test/frontend/features/history/utils/display-name-for-user.test.ts similarity index 76% rename from services/web/test/frontend/ide/history/util/displayNameForUserTests.js rename to services/web/test/frontend/features/history/utils/display-name-for-user.test.ts index 7edd9e72e6..07d454a5ed 100644 --- a/services/web/test/frontend/ide/history/util/displayNameForUserTests.js +++ b/services/web/test/frontend/features/history/utils/display-name-for-user.test.ts @@ -1,19 +1,8 @@ -/* eslint-disable - no-return-assign, -*/ -// TODO: This file was created by bulk-decaffeinate. -// Fix any style issues and re-enable lint. -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ import { expect } from 'chai' +import displayNameForUser from '@/features/history/utils/display-name-for-user' -import displayNameForUser from '../../../../../frontend/js/ide/history/util/displayNameForUser' - -export default describe('displayNameForUser', function () { - const currentUsersId = 42 +describe('displayNameForUser', function () { + const currentUsersId = 'user-a' beforeEach(function () { window.metaAttributesCache.set('ol-user', { id: currentUsersId }) }) diff --git a/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx b/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx index ed6877ee07..faca302f05 100644 --- a/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx +++ b/services/web/test/frontend/features/project-list/components/current-plan-widget.test.tsx @@ -7,7 +7,7 @@ import { IndividualPlanSubscription, } from '../../../../../types/project/dashboard/subscription' import { DeepReadonly } from '../../../../../types/utils' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import CurrentPlanWidget from '../../../../../frontend/js/features/project-list/components/current-plan-widget/current-plan-widget' describe('', function () { diff --git a/services/web/test/frontend/features/project-list/components/notifications.test.tsx b/services/web/test/frontend/features/project-list/components/notifications.test.tsx index 3ecb7b6750..679e00815e 100644 --- a/services/web/test/frontend/features/project-list/components/notifications.test.tsx +++ b/services/web/test/frontend/features/project-list/components/notifications.test.tsx @@ -36,7 +36,7 @@ import { DeepPartial } from '../../../../../types/utils' import { Project } from '../../../../../types/project/dashboard/api' import GroupsAndEnterpriseBanner from '../../../../../frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner' import GroupSsoSetupSuccess from '../../../../../frontend/js/features/project-list/components/notifications/groups/group-sso-setup-success' -import localStorage from '../../../../../frontend/js/infrastructure/local-storage' +import localStorage from '@/infrastructure/local-storage' import * as useLocationModule from '../../../../../frontend/js/shared/hooks/use-location' import { commonsSubscription, diff --git a/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx b/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx index 2c5e3f6dc7..a2567319bd 100644 --- a/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx +++ b/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx @@ -4,7 +4,7 @@ import fetchMock from 'fetch-mock' import sinon from 'sinon' import ProjectListRoot from '../../../../../frontend/js/features/project-list/components/project-list-root' import { renderWithProjectListContext } from '../helpers/render-with-context' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import { projectsData, owner, diff --git a/services/web/test/frontend/features/project-list/components/project-search.test.tsx b/services/web/test/frontend/features/project-list/components/project-search.test.tsx index a8b5879535..f8c482740b 100644 --- a/services/web/test/frontend/features/project-list/components/project-search.test.tsx +++ b/services/web/test/frontend/features/project-list/components/project-search.test.tsx @@ -2,7 +2,7 @@ import sinon from 'sinon' import { render, screen, fireEvent } from '@testing-library/react' import { expect } from 'chai' import SearchForm from '../../../../../frontend/js/features/project-list/components/search-form' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import fetchMock from 'fetch-mock' import { Filter } from '../../../../../frontend/js/features/project-list/context/project-list-context' import { Tag } from '../../../../../app/src/Features/Tags/types' diff --git a/services/web/test/frontend/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button.test.tsx b/services/web/test/frontend/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button.test.tsx index 978faf510f..2479d9d3ab 100644 --- a/services/web/test/frontend/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button.test.tsx +++ b/services/web/test/frontend/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button.test.tsx @@ -5,7 +5,7 @@ import { projectsData } from '../../../../fixtures/projects-data' import * as useLocationModule from '../../../../../../../../frontend/js/shared/hooks/use-location' import { CompileAndDownloadProjectPDFButtonTooltip } from '../../../../../../../../frontend/js/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button' import fetchMock from 'fetch-mock' -import * as eventTracking from '../../../../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' describe('', function () { let assignStub: sinon.SinonStub diff --git a/services/web/test/frontend/features/project-list/components/table/projects-action-modal.test.tsx b/services/web/test/frontend/features/project-list/components/table/projects-action-modal.test.tsx index 8476f64580..66b350eaab 100644 --- a/services/web/test/frontend/features/project-list/components/table/projects-action-modal.test.tsx +++ b/services/web/test/frontend/features/project-list/components/table/projects-action-modal.test.tsx @@ -7,7 +7,7 @@ import { resetProjectListContextFetch, renderWithProjectListContext, } from '../../helpers/render-with-context' -import * as eventTracking from '../../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' describe('', function () { const actionHandler = sinon.stub().resolves({}) diff --git a/services/web/test/frontend/features/settings/components/leavers-survey-alert.test.tsx b/services/web/test/frontend/features/settings/components/leavers-survey-alert.test.tsx index 570c3019ab..2ffa2e5051 100644 --- a/services/web/test/frontend/features/settings/components/leavers-survey-alert.test.tsx +++ b/services/web/test/frontend/features/settings/components/leavers-survey-alert.test.tsx @@ -3,8 +3,8 @@ import sinon from 'sinon' import { fireEvent, screen, render } from '@testing-library/react' import { UserEmailsProvider } from '../../../../../frontend/js/features/settings/context/user-email-context' import { LeaversSurveyAlert } from '../../../../../frontend/js/features/settings/components/leavers-survey-alert' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' -import localStorage from '../../../../../frontend/js/infrastructure/local-storage' +import * as eventTracking from '@/infrastructure/event-tracking' +import localStorage from '@/infrastructure/local-storage' import fetchMock from 'fetch-mock' function renderWithProvider() { diff --git a/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx index 5fd7180036..168421e6c7 100644 --- a/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx +++ b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx @@ -2,7 +2,7 @@ import { expect } from 'chai' import sinon from 'sinon' import { screen, fireEvent, render, waitFor } from '@testing-library/react' import { IntegrationLinkingWidget } from '../../../../../../frontend/js/features/settings/components/linking/integration-widget' -import * as eventTracking from '../../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' describe('', function () { const defaultProps = { diff --git a/services/web/test/frontend/features/settings/components/root.test.tsx b/services/web/test/frontend/features/settings/components/root.test.tsx index d15c3c22bd..ea4de26aa1 100644 --- a/services/web/test/frontend/features/settings/components/root.test.tsx +++ b/services/web/test/frontend/features/settings/components/root.test.tsx @@ -1,7 +1,7 @@ import { expect } from 'chai' import sinon from 'sinon' import { screen, render, waitFor } from '@testing-library/react' -import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import SettingsPageRoot from '../../../../../frontend/js/features/settings/components/root' import getMeta from '@/utils/meta' diff --git a/services/web/test/frontend/features/settings/context/user-email-context.test.tsx b/services/web/test/frontend/features/settings/context/user-email-context.test.tsx index bf0b69c208..ba814d6ebf 100644 --- a/services/web/test/frontend/features/settings/context/user-email-context.test.tsx +++ b/services/web/test/frontend/features/settings/context/user-email-context.test.tsx @@ -14,7 +14,7 @@ import { fakeUsersData, unconfirmedCommonsUserData, } from '../fixtures/test-user-email-data' -import localStorage from '../../../../../frontend/js/infrastructure/local-storage' +import localStorage from '@/infrastructure/local-storage' const renderUserEmailsContext = () => renderHook(() => useUserEmailsContext(), { diff --git a/services/web/test/frontend/features/subscription/components/dashboard/states/active/active.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/states/active/active.test.tsx index aad32212ca..df8192030f 100644 --- a/services/web/test/frontend/features/subscription/components/dashboard/states/active/active.test.tsx +++ b/services/web/test/frontend/features/subscription/components/dashboard/states/active/active.test.tsx @@ -1,6 +1,6 @@ import { expect } from 'chai' import { fireEvent, screen, waitFor } from '@testing-library/react' -import * as eventTracking from '../../../../../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import { RecurlySubscription } from '../../../../../../../../types/subscription/dashboard/subscription' import { annualActiveSubscription, diff --git a/services/web/test/frontend/infrastructure/local-storage.test.js b/services/web/test/frontend/infrastructure/local-storage.test.js index c8a35337b3..e6b07cccce 100644 --- a/services/web/test/frontend/infrastructure/local-storage.test.js +++ b/services/web/test/frontend/infrastructure/local-storage.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import sinon from 'sinon' -import customLocalStorage from '../../../frontend/js/infrastructure/local-storage' +import customLocalStorage from '@/infrastructure/local-storage' import { debugConsole } from '@/utils/debugging' describe('localStorage', function () { diff --git a/services/web/test/frontend/shared/components/notification.test.tsx b/services/web/test/frontend/shared/components/notification.test.tsx index a4b421efc6..fbe5c04fc2 100644 --- a/services/web/test/frontend/shared/components/notification.test.tsx +++ b/services/web/test/frontend/shared/components/notification.test.tsx @@ -1,7 +1,7 @@ import { expect } from 'chai' import { screen, render } from '@testing-library/react' import Notification from '../../../../frontend/js/shared/components/notification' -import * as eventTracking from '../../../../frontend/js/infrastructure/event-tracking' +import * as eventTracking from '@/infrastructure/event-tracking' import sinon from 'sinon' describe('', function () { diff --git a/services/web/test/frontend/shared/hooks/use-persisted-state.test.tsx b/services/web/test/frontend/shared/hooks/use-persisted-state.test.tsx index 90dc4cde07..5b670698e3 100644 --- a/services/web/test/frontend/shared/hooks/use-persisted-state.test.tsx +++ b/services/web/test/frontend/shared/hooks/use-persisted-state.test.tsx @@ -3,7 +3,7 @@ import { expect } from 'chai' import { useEffect } from 'react' import { render, screen } from '@testing-library/react' import usePersistedState from '../../../../frontend/js/shared/hooks/use-persisted-state' -import localStorage from '../../../../frontend/js/infrastructure/local-storage' +import localStorage from '@/infrastructure/local-storage' describe('usePersistedState', function () { beforeEach(function () { diff --git a/services/web/test/frontend/utils/EventEmitterTests.js b/services/web/test/frontend/utils/EventEmitterTests.js index 68ad71eed2..6f4f4858dc 100644 --- a/services/web/test/frontend/utils/EventEmitterTests.js +++ b/services/web/test/frontend/utils/EventEmitterTests.js @@ -1,22 +1,11 @@ -/* eslint-disable - max-len, - no-return-assign, -*/ -// TODO: This file was created by bulk-decaffeinate. -// Fix any style issues and re-enable lint. -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ import { expect } from 'chai' import sinon from 'sinon' -import EventEmitter from '../../../frontend/js/utils/EventEmitter' +import EventEmitter from '@/utils/EventEmitter' -export default describe('EventEmitter', function () { +describe('EventEmitter', function () { beforeEach(function () { - return (this.eventEmitter = new EventEmitter()) + this.eventEmitter = new EventEmitter() }) it('calls listeners', function () { @@ -28,7 +17,7 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') expect(cb1).to.have.been.called - return expect(cb2).to.not.have.been.called + expect(cb2).to.not.have.been.called }) it('calls multiple listeners', function () { @@ -40,7 +29,7 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') expect(cb1).to.have.been.called - return expect(cb2).to.have.been.called + expect(cb2).to.have.been.called }) it('calls listeners with namespace', function () { @@ -52,7 +41,7 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') expect(cb1).to.have.been.called - return expect(cb2).to.have.been.called + expect(cb2).to.have.been.called }) it('removes listeners', function () { @@ -62,7 +51,7 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') - return expect(cb).to.not.have.been.called + expect(cb).to.not.have.been.called }) it('removes namespaced listeners', function () { @@ -72,7 +61,7 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') - return expect(cb).to.not.have.been.called + expect(cb).to.not.have.been.called }) it('does not remove unnamespaced listeners if off called with namespace', function () { @@ -85,6 +74,6 @@ export default describe('EventEmitter', function () { this.eventEmitter.trigger('foo') expect(cb1).to.have.been.called - return expect(cb2).to.not.have.been.called + expect(cb2).to.not.have.been.called }) }) diff --git a/services/web/types/window.ts b/services/web/types/window.ts index 84213774d6..4096958005 100644 --- a/services/web/types/window.ts +++ b/services/web/types/window.ts @@ -37,5 +37,7 @@ declare global { store: ScopeValueStore } } + ga?: (...args: any) => void + gtag?: (...args: any) => void } }