diff --git a/frontend/__tests__/unit/components/AnchorTitle.test.tsx b/frontend/__tests__/unit/components/AnchorTitle.test.tsx index 102f43f5bc..c328495d12 100644 --- a/frontend/__tests__/unit/components/AnchorTitle.test.tsx +++ b/frontend/__tests__/unit/components/AnchorTitle.test.tsx @@ -72,7 +72,7 @@ const setupAnimationFrameForHash = (cb: (time: number) => void) => { describe('AnchorTitle Component', () => { afterEach(() => { jest.restoreAllMocks() - window.history.replaceState(null, '', window.location.pathname) + globalThis.history.replaceState(null, '', globalThis.location.pathname) }) describe('Basic Rendering', () => { @@ -157,10 +157,10 @@ describe('AnchorTitle Component', () => { let mockRequestAnimationFrame: jest.SpyInstance const setupMocks = () => { - mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() - mockPushState = jest.spyOn(window.history, 'pushState').mockImplementation() + mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() + mockPushState = jest.spyOn(globalThis.history, 'pushState').mockImplementation() mockRequestAnimationFrame = jest - .spyOn(window, 'requestAnimationFrame') + .spyOn(globalThis, 'requestAnimationFrame') .mockImplementation(setupMockAnimationFrame) mockGetBoundingClientRect = jest.fn(createMockBoundingClientRect) @@ -232,9 +232,9 @@ describe('AnchorTitle Component', () => { let mockRequestAnimationFrame: jest.SpyInstance const setupUseEffectMocks = () => { - mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() mockRequestAnimationFrame = jest - .spyOn(window, 'requestAnimationFrame') + .spyOn(globalThis, 'requestAnimationFrame') .mockImplementation(setupAnimationFrameForUseEffect) const mockElement = createMockElementForUseEffect() @@ -253,7 +253,7 @@ describe('AnchorTitle Component', () => { afterEach(cleanupUseEffectMocks) it('scrolls to element on mount when hash matches', async () => { - window.location.hash = '#test-scroll' + globalThis.location.hash = '#test-scroll' render() @@ -267,7 +267,7 @@ describe('AnchorTitle Component', () => { }) it('does not scroll when hash does not match', () => { - window.location.hash = '#different-hash' + globalThis.location.hash = '#different-hash' render() @@ -276,10 +276,10 @@ describe('AnchorTitle Component', () => { it('handles popstate events correctly', async () => { render() - window.location.hash = '#popstate-test' + globalThis.location.hash = '#popstate-test' const popstateEvent = new PopStateEvent('popstate') - fireEvent(window, popstateEvent) + fireEvent(globalThis as unknown as Window, popstateEvent) await waitFor(() => { expect(mockRequestAnimationFrame).toHaveBeenCalled() @@ -288,7 +288,7 @@ describe('AnchorTitle Component', () => { }) it('removes popstate event listener on unmount', () => { - const mockRemoveEventListener = jest.spyOn(window, 'removeEventListener') + const mockRemoveEventListener = jest.spyOn(globalThis, 'removeEventListener') const { unmount } = render() unmount() @@ -347,7 +347,7 @@ describe('AnchorTitle Component', () => { const mockGetElementById = jest .spyOn(document, 'getElementById') .mockReturnValue(mockElement as unknown as HTMLElement) - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() render() const link = screen.getByRole('link') @@ -381,8 +381,8 @@ describe('AnchorTitle Component', () => { }) it('maintains focus management on interaction', () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() - const mockPushState = jest.spyOn(window.history, 'pushState').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() + const mockPushState = jest.spyOn(globalThis.history, 'pushState').mockImplementation() render() @@ -418,8 +418,8 @@ describe('AnchorTitle Component', () => { }) it('handles rapid successive clicks', () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() - const mockPushState = jest.spyOn(window.history, 'pushState').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() + const mockPushState = jest.spyOn(globalThis.history, 'pushState').mockImplementation() render() const link = screen.getByRole('link') @@ -450,10 +450,10 @@ describe('AnchorTitle Component', () => { describe('Browser API Interactions', () => { it('handles window.pageYOffset correctly', () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() const originalPageYOffset = window.pageYOffset - Object.defineProperty(window, 'pageYOffset', { + Object.defineProperty(globalThis, 'pageYOffset', { value: 500, configurable: true, }) @@ -473,7 +473,7 @@ describe('AnchorTitle Component', () => { behavior: 'smooth', }) - Object.defineProperty(window, 'pageYOffset', { + Object.defineProperty(globalThis, 'pageYOffset', { value: originalPageYOffset, configurable: true, }) @@ -483,17 +483,17 @@ describe('AnchorTitle Component', () => { }) it('handles hash changes in the URL correctly', async () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() const mockRequestAnimationFrame = jest - .spyOn(window, 'requestAnimationFrame') + .spyOn(globalThis, 'requestAnimationFrame') .mockImplementation(setupAnimationFrameForHash) - window.location.hash = '' + globalThis.location.hash = '' render() - window.location.hash = '#hash-test' + globalThis.location.hash = '#hash-test' const popstateEvent = new PopStateEvent('popstate') - fireEvent(window, popstateEvent) + fireEvent(globalThis as unknown as Window, popstateEvent) await waitFor(() => { expect(mockScrollTo).toHaveBeenCalled() @@ -506,7 +506,7 @@ describe('AnchorTitle Component', () => { describe('Performance and Optimization', () => { it('uses useCallback for scrollToElement function', () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() const { rerender } = render() const link1 = screen.getByRole('link') @@ -523,8 +523,8 @@ describe('AnchorTitle Component', () => { }) it('cleans up event listeners properly', () => { - const mockAddEventListener = jest.spyOn(window, 'addEventListener') - const mockRemoveEventListener = jest.spyOn(window, 'removeEventListener') + const mockAddEventListener = jest.spyOn(globalThis, 'addEventListener') + const mockRemoveEventListener = jest.spyOn(globalThis, 'removeEventListener') const { unmount } = render() @@ -541,7 +541,7 @@ describe('AnchorTitle Component', () => { describe('State Changes and Internal Logic', () => { it('recalculates scroll position when element dimensions change', () => { - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() const offsetHeights = { current: 30 } const mockElement = { @@ -570,8 +570,8 @@ describe('AnchorTitle Component', () => { }) it('handles component rerender with different IDs', () => { - const mockAddEventListener = jest.spyOn(window, 'addEventListener') - const mockRemoveEventListener = jest.spyOn(window, 'removeEventListener') + const mockAddEventListener = jest.spyOn(globalThis, 'addEventListener') + const mockRemoveEventListener = jest.spyOn(globalThis, 'removeEventListener') const { rerender } = render() const originalAddCalls = mockAddEventListener.mock.calls.length @@ -657,8 +657,8 @@ describe('AnchorTitle Component', () => { .replace(/(^-{1,10}|-{1,10}$)/g, '') ) - const mockScrollTo = jest.spyOn(window, 'scrollTo').mockImplementation() - const mockPushState = jest.spyOn(window.history, 'pushState').mockImplementation() + const mockScrollTo = jest.spyOn(globalThis, 'scrollTo').mockImplementation() + const mockPushState = jest.spyOn(globalThis.history, 'pushState').mockImplementation() render() diff --git a/frontend/__tests__/unit/components/AnimatedCounter.test.tsx b/frontend/__tests__/unit/components/AnimatedCounter.test.tsx index e2ffc56ff9..1f1a1e421f 100644 --- a/frontend/__tests__/unit/components/AnimatedCounter.test.tsx +++ b/frontend/__tests__/unit/components/AnimatedCounter.test.tsx @@ -173,7 +173,7 @@ describe('AnimatedCounter', () => { describe('Animation behavior', () => { it('calls requestAnimationFrame during animation', () => { - const requestAnimationFrameSpy = jest.spyOn(window, 'requestAnimationFrame') + const requestAnimationFrameSpy = jest.spyOn(globalThis, 'requestAnimationFrame') render() expect(requestAnimationFrameSpy).toHaveBeenCalled() diff --git a/frontend/__tests__/unit/components/MultiSearch.test.tsx b/frontend/__tests__/unit/components/MultiSearch.test.tsx index e5df9beebd..7d02fe1f41 100644 --- a/frontend/__tests__/unit/components/MultiSearch.test.tsx +++ b/frontend/__tests__/unit/components/MultiSearch.test.tsx @@ -39,7 +39,7 @@ jest.mock('@fortawesome/react-fontawesome', () => ({ // Mock window.open globally const mockWindowOpen = jest.fn() -Object.defineProperty(window, 'open', { +Object.defineProperty(globalThis, 'open', { value: mockWindowOpen, writable: true, }) diff --git a/frontend/__tests__/unit/components/ScrollToTop.test.tsx b/frontend/__tests__/unit/components/ScrollToTop.test.tsx index 5f271eff26..ed1001db84 100644 --- a/frontend/__tests__/unit/components/ScrollToTop.test.tsx +++ b/frontend/__tests__/unit/components/ScrollToTop.test.tsx @@ -3,9 +3,9 @@ import ScrollToTop from 'components/ScrollToTop' describe('ScrollToTop component test', () => { beforeEach(() => { - window.scrollTo = jest.fn() - Object.defineProperty(window, 'scrollY', { value: 0, writable: true }) - Object.defineProperty(window, 'innerHeight', { value: 1000, writable: true }) + globalThis.scrollTo = jest.fn() + Object.defineProperty(globalThis, 'scrollY', { value: 0, writable: true }) + Object.defineProperty(globalThis, 'innerHeight', { value: 1000, writable: true }) }) afterEach(() => { @@ -24,8 +24,8 @@ describe('ScrollToTop component test', () => { const { getByLabelText } = render() const button = getByLabelText(/scroll to top/i) - Object.defineProperty(window, 'scrollY', { value: 400, writable: true }) - window.dispatchEvent(new Event('scroll')) + Object.defineProperty(globalThis, 'scrollY', { value: 400, writable: true }) + globalThis.dispatchEvent(new Event('scroll')) await waitFor(() => { expect(button).toHaveClass('opacity-100') @@ -33,18 +33,18 @@ describe('ScrollToTop component test', () => { }) }) - test('Clicking the button should call window.scrollTo with smooth behavior', async () => { + test('Clicking the button should call globalThis.scrollTo with smooth behavior', async () => { const { getByLabelText } = render() const button = getByLabelText(/scroll to top/i) - Object.defineProperty(window, 'scrollY', { value: 400, writable: true }) - window.dispatchEvent(new Event('scroll')) + Object.defineProperty(globalThis, 'scrollY', { value: 400, writable: true }) + globalThis.dispatchEvent(new Event('scroll')) await waitFor(() => { expect(button).toHaveClass('opacity-100') }) fireEvent.click(button) - expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' }) + expect(globalThis.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' }) }) }) diff --git a/frontend/__tests__/unit/components/Search.test.tsx b/frontend/__tests__/unit/components/Search.test.tsx index b03ef8e352..91c2e81995 100644 --- a/frontend/__tests__/unit/components/Search.test.tsx +++ b/frontend/__tests__/unit/components/Search.test.tsx @@ -185,7 +185,7 @@ describe('SearchBar Component', () => { expect(sendGTMEvent).toHaveBeenCalledWith({ event: 'search', - path: window.location.pathname, + path: globalThis.location.pathname, value: 'test', }) }) @@ -203,7 +203,7 @@ describe('SearchBar Component', () => { expect(mockOnSearch).toHaveBeenCalledWith('new query') expect(sendGTMEvent).toHaveBeenCalledWith({ event: 'search', - path: window.location.pathname, + path: globalThis.location.pathname, value: 'new query', }) @@ -214,7 +214,7 @@ describe('SearchBar Component', () => { expect(mockOnSearch).toHaveBeenCalledWith('change query') expect(sendGTMEvent).toHaveBeenCalledWith({ event: 'search', - path: window.location.pathname, + path: globalThis.location.pathname, value: 'change query', }) }) diff --git a/frontend/__tests__/unit/pages/Header.test.tsx b/frontend/__tests__/unit/pages/Header.test.tsx index f0a111df17..e12116319b 100644 --- a/frontend/__tests__/unit/pages/Header.test.tsx +++ b/frontend/__tests__/unit/pages/Header.test.tsx @@ -190,7 +190,7 @@ describe('Header Component', () => { beforeEach(() => { mockUsePathname.mockReturnValue('/') // Mock window.innerWidth - Object.defineProperty(window, 'innerWidth', { + Object.defineProperty(globalThis, 'innerWidth', { writable: true, configurable: true, value: 1024, @@ -487,7 +487,7 @@ describe('Header Component', () => { // Simulate resize event await act(async () => { - window.dispatchEvent(new Event('resize')) + globalThis.dispatchEvent(new Event('resize')) }) // Test passes if no errors are thrown @@ -685,7 +685,7 @@ describe('Header Component', () => { it('shows mobile menu button for mobile screens', () => { // Set window width to simulate mobile - Object.defineProperty(window, 'innerWidth', { + Object.defineProperty(globalThis, 'innerWidth', { writable: true, configurable: true, value: 400, diff --git a/frontend/jest.setup.ts b/frontend/jest.setup.ts index 19fa975c68..799e5d54e3 100644 --- a/frontend/jest.setup.ts +++ b/frontend/jest.setup.ts @@ -2,13 +2,13 @@ import '@testing-library/jest-dom' import React from 'react' import 'core-js/actual/structured-clone' -global.React = React +globalThis.React = React // Add fetch polyfill for jsdom test environment // Node.js 18+ has native fetch, but jsdom doesn't include it -if (typeof global.fetch === 'undefined') { +if (typeof globalThis.fetch === 'undefined') { // Use a simple mock fetch for testing - global.fetch = jest.fn().mockResolvedValue({ + globalThis.fetch = jest.fn().mockResolvedValue({ ok: true, status: 200, statusText: 'OK', @@ -50,24 +50,24 @@ jest.mock('next-auth/react', () => { } }) -if (!global.structuredClone) { - global.structuredClone = (val) => JSON.parse(JSON.stringify(val)) +if (!globalThis.structuredClone) { + globalThis.structuredClone = (val) => JSON.parse(JSON.stringify(val)) } beforeAll(() => { - if (typeof window !== 'undefined') { - jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => { + if (typeof globalThis !== 'undefined') { + jest.spyOn(globalThis, 'requestAnimationFrame').mockImplementation((cb) => { return setTimeout(cb, 0) }) - Object.defineProperty(window, 'runAnimationFrameCallbacks', { + Object.defineProperty(globalThis, 'runAnimationFrameCallbacks', { value: () => {}, configurable: true, writable: true, }) } - global.ResizeObserver = class { + globalThis.ResizeObserver = class { disconnect() {} observe() {} unobserve() {} @@ -79,7 +79,7 @@ beforeEach(() => { throw new Error(`Console error: ${args.join(' ')}`) }) - jest.spyOn(global.console, 'warn').mockImplementation((message) => { + jest.spyOn(globalThis.console, 'warn').mockImplementation((message) => { if ( typeof message === 'string' && message.includes('[@zag-js/dismissable] node is `null` or `undefined`') @@ -88,7 +88,7 @@ beforeEach(() => { } }) - Object.defineProperty(window, 'matchMedia', { + Object.defineProperty(globalThis, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((query) => ({ matches: false, @@ -102,6 +102,6 @@ beforeEach(() => { })), }) - global.runAnimationFrameCallbacks = jest.fn() - global.removeAnimationFrameCallbacks = jest.fn() + globalThis.runAnimationFrameCallbacks = jest.fn() + globalThis.removeAnimationFrameCallbacks = jest.fn() }) diff --git a/frontend/src/app/mentorship/programs/[programKey]/page.tsx b/frontend/src/app/mentorship/programs/[programKey]/page.tsx index cf23164bb2..4adf2c0961 100644 --- a/frontend/src/app/mentorship/programs/[programKey]/page.tsx +++ b/frontend/src/app/mentorship/programs/[programKey]/page.tsx @@ -43,7 +43,7 @@ const ProgramDetailsPage = () => { const params = new URLSearchParams(searchParams.toString()) params.delete('refresh') const cleaned = params.toString() - router.replace(cleaned ? `?${cleaned}` : window.location.pathname, { scroll: false }) + router.replace(cleaned ? `?${cleaned}` : globalThis.location.pathname, { scroll: false }) } } diff --git a/frontend/src/app/my/mentorship/page.tsx b/frontend/src/app/my/mentorship/page.tsx index b95f6b5466..3de19c9c32 100644 --- a/frontend/src/app/my/mentorship/page.tsx +++ b/frontend/src/app/my/mentorship/page.tsx @@ -43,8 +43,8 @@ const MyMentorshipPage: React.FC = () => { const params = new URLSearchParams() if (searchQuery) params.set('q', searchQuery) if (page > 1) params.set('page', String(page)) - const nextUrl = params.toString() ? `?${params}` : window.location.pathname - if (window.location.search !== `?${params}`) { + const nextUrl = params.toString() ? `?${params}` : globalThis.location.pathname + if (globalThis.location.search !== `?${params}`) { router.push(nextUrl, { scroll: false }) } }, [searchQuery, page, router]) @@ -118,7 +118,7 @@ const MyMentorshipPage: React.FC = () => { currentPage={page} onPageChange={(p) => { setPage(p) - window.scrollTo({ top: 0, behavior: 'smooth' }) + globalThis.scrollTo({ top: 0, behavior: 'smooth' }) }} onSearch={(q) => { setSearchQuery(q) diff --git a/frontend/src/app/my/mentorship/programs/[programKey]/page.tsx b/frontend/src/app/my/mentorship/programs/[programKey]/page.tsx index c386ef1b44..0cec3c40ec 100644 --- a/frontend/src/app/my/mentorship/programs/[programKey]/page.tsx +++ b/frontend/src/app/my/mentorship/programs/[programKey]/page.tsx @@ -101,7 +101,7 @@ const ProgramDetailsPage = () => { const params = new URLSearchParams(searchParams.toString()) params.delete('refresh') const cleaned = params.toString() - router.replace(cleaned ? `?${cleaned}` : window.location.pathname, { scroll: false }) + router.replace(cleaned ? `?${cleaned}` : globalThis.location.pathname, { scroll: false }) } } diff --git a/frontend/src/components/AnchorTitle.tsx b/frontend/src/components/AnchorTitle.tsx index 7557d9114e..667b01d17c 100644 --- a/frontend/src/components/AnchorTitle.tsx +++ b/frontend/src/components/AnchorTitle.tsx @@ -23,7 +23,7 @@ const AnchorTitle: React.FC = ({ title }) => { } useEffect(() => { - const hash = window.location.hash.replace('#', '') + const hash = globalThis.location.hash.replace('#', '') if (hash === id) { requestAnimationFrame(() => scrollToElement()) } @@ -31,13 +31,13 @@ const AnchorTitle: React.FC = ({ title }) => { useEffect(() => { const handlePopState = () => { - const hash = window.location.hash.replace('#', '') + const hash = globalThis.location.hash.replace('#', '') if (hash === id) { requestAnimationFrame(() => scrollToElement()) } } - window.addEventListener('popstate', handlePopState) - return () => window.removeEventListener('popstate', handlePopState) + globalThis.addEventListener('popstate', handlePopState) + return () => globalThis.removeEventListener('popstate', handlePopState) }, [id, scrollToElement]) return ( diff --git a/frontend/src/components/CardDetailsPage.tsx b/frontend/src/components/CardDetailsPage.tsx index 1fde4c4490..ca2055cebb 100644 --- a/frontend/src/components/CardDetailsPage.tsx +++ b/frontend/src/components/CardDetailsPage.tsx @@ -91,7 +91,7 @@ const DetailsCard = ({ type="button" className="flex items-center justify-center gap-2 rounded-md border border-[#0D6EFD] bg-transparent px-2 py-2 text-nowrap text-[#0D6EFD] transition-all hover:bg-[#0D6EFD] hover:text-white dark:border-sky-600 dark:text-sky-600 dark:hover:bg-sky-100" onClick={() => { - router.push(`${window.location.pathname}/edit`) + router.push(`${globalThis.location.pathname}/edit`) }} > Edit Module diff --git a/frontend/src/components/ChapterMap.tsx b/frontend/src/components/ChapterMap.tsx index 36c360aca5..ee145c1017 100644 --- a/frontend/src/components/ChapterMap.tsx +++ b/frontend/src/components/ChapterMap.tsx @@ -71,7 +71,7 @@ const ChapterMap = ({ popupContent.className = 'popup-content' popupContent.textContent = chapter.name popupContent.addEventListener('click', () => { - window.location.href = `/chapters/${chapter.key}` + globalThis.location.href = `/chapters/${chapter.key}` }) popup.setContent(popupContent) marker.bindPopup(popup) diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index 689eb6af90..d653ac4514 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -26,7 +26,7 @@ export default function Header({ isGitHubAuthEnabled }: { readonly isGitHubAuthE useEffect(() => { const handleResize = () => { - if (window.innerWidth >= desktopViewMinWidth) { + if (globalThis.innerWidth >= desktopViewMinWidth) { setMobileMenuOpen(false) } } @@ -45,12 +45,12 @@ export default function Header({ isGitHubAuthEnabled }: { readonly isGitHubAuthE } } - window.addEventListener('resize', handleResize) - window.addEventListener('click', handleOutsideClick) + globalThis.addEventListener('resize', handleResize) + globalThis.addEventListener('click', handleOutsideClick) return () => { - window.removeEventListener('resize', handleResize) - window.removeEventListener('click', handleOutsideClick) + globalThis.removeEventListener('resize', handleResize) + globalThis.removeEventListener('click', handleOutsideClick) } }, [mobileMenuOpen]) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index d5f8cdb594..479e9ec136 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -70,7 +70,7 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { const ModuleItem = ({ details }: { details: Module }) => { const router = useRouter() const handleClick = () => { - router.push(`${window.location.pathname}/modules/${details.key}`) + router.push(`${globalThis.location.pathname}/modules/${details.key}`) } return ( diff --git a/frontend/src/components/MultiSearch.tsx b/frontend/src/components/MultiSearch.tsx index e675021203..4643ae98e3 100644 --- a/frontend/src/components/MultiSearch.tsx +++ b/frontend/src/components/MultiSearch.tsx @@ -48,7 +48,7 @@ const MultiSearchBar: React.FC = ({ if (query && query.trim() !== '') { sendGAEvent({ event: 'homepageSearch', - path: window.location.pathname, + path: globalThis.location.pathname, value: query, }) } @@ -100,7 +100,7 @@ const MultiSearchBar: React.FC = ({ router.push(`/chapters/${suggestion.key}`) break case 'events': - window.open((suggestion as Event).url, '_blank') + globalThis.open((suggestion as Event).url, '_blank') break case 'organizations': // Use type guard to safely access login property diff --git a/frontend/src/components/ProgramActions.tsx b/frontend/src/components/ProgramActions.tsx index 93f4e380e9..039dae5240 100644 --- a/frontend/src/components/ProgramActions.tsx +++ b/frontend/src/components/ProgramActions.tsx @@ -22,10 +22,10 @@ const ProgramActions: React.FC = ({ status, setStatus }) => const handleAction = (actionKey: string) => { switch (actionKey) { case 'edit Program': - router.push(`${window.location.pathname}/edit`) + router.push(`${globalThis.location.pathname}/edit`) break case 'create_module': - router.push(`${window.location.pathname}/modules/create`) + router.push(`${globalThis.location.pathname}/modules/create`) break case 'publish': setStatus(ProgramStatusEnum.Published) diff --git a/frontend/src/components/Search.tsx b/frontend/src/components/Search.tsx index 93f9743637..3e4f6c856a 100644 --- a/frontend/src/components/Search.tsx +++ b/frontend/src/components/Search.tsx @@ -40,7 +40,7 @@ const SearchBar: React.FC = ({ if (query && query.trim() !== '') { sendGTMEvent({ event: 'search', - path: window.location.pathname, + path: globalThis.location.pathname, value: query, }) } diff --git a/frontend/src/components/SingleModuleCard.tsx b/frontend/src/components/SingleModuleCard.tsx index 2b7d3f1435..ced93ecc44 100644 --- a/frontend/src/components/SingleModuleCard.tsx +++ b/frontend/src/components/SingleModuleCard.tsx @@ -37,17 +37,17 @@ const SingleModuleCard: React.FC = ({ const handleView = () => { setDropdownOpen(false) - router.push(`${window.location.pathname}/modules/${module.key}`) + router.push(`${globalThis.location.pathname}/modules/${module.key}`) } const handleEdit = () => { setDropdownOpen(false) - router.push(`${window.location.pathname}/modules/${module.key}/edit`) + router.push(`${globalThis.location.pathname}/modules/${module.key}/edit`) } const handleCreate = () => { setDropdownOpen(false) - router.push(`${window.location.pathname}/modules/create`) + router.push(`${globalThis.location.pathname}/modules/create`) } const moduleDetails = [ @@ -73,7 +73,7 @@ const SingleModuleCard: React.FC = ({
{ useEffect(() => { // check whether the browser supports matchMedia API - if (typeof window.matchMedia !== 'function') return + if (typeof globalThis.matchMedia !== 'function') return - const mediaQuery = window.matchMedia(`(max-width: ${desktopViewMinWidth - 1}px)`) + const mediaQuery = globalThis.matchMedia(`(max-width: ${desktopViewMinWidth - 1}px)`) const handleChange = (e: MediaQueryListEvent | MediaQueryList) => { setIsMobile(e.matches) diff --git a/frontend/src/server/fetchMetricsPDF.ts b/frontend/src/server/fetchMetricsPDF.ts index 8cd3ee97d7..8b1a91cf7d 100644 --- a/frontend/src/server/fetchMetricsPDF.ts +++ b/frontend/src/server/fetchMetricsPDF.ts @@ -21,14 +21,14 @@ export const fetchMetricsPDF = async (path: string, fileName: string): Promise