Skip to content

Commit 880962d

Browse files
test(medium): Fix component test errors and suppress console noise (#9444)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: arii <342438+arii@users.noreply.github.com>
1 parent 325e0da commit 880962d

10 files changed

Lines changed: 130 additions & 50 deletions

File tree

tests/unit/app/api/internal/token-delivery/route.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { NextRequest } from 'next/server'
77
import { SPOTIFY_DEFAULT_TOKEN_EXPIRY_S } from '@/constants/spotify'
88

99
// Mock logger
10-
jest.mock('@/utils/logger.server', () => ({
10+
jest.mock('@/utils/logger', () => ({
1111
__esModule: true,
1212
default: {
1313
info: jest.fn(),
@@ -36,10 +36,18 @@ describe('POST /api/internal/token-delivery', () => {
3636
})
3737

3838
beforeEach(() => {
39+
jest.spyOn(console, 'info').mockImplementation(() => {})
40+
jest.spyOn(console, 'warn').mockImplementation(() => {})
41+
jest.spyOn(console, 'error').mockImplementation(() => {})
42+
3943
jest.clearAllMocks()
4044
global.spotifyService = mockSpotifyService
4145
})
4246

47+
afterEach(() => {
48+
jest.restoreAllMocks()
49+
})
50+
4351
it('should return 401 if secret header is missing or invalid', async () => {
4452
const req = new NextRequest(
4553
'http://localhost/api/internal/token-delivery',

tests/unit/app/api/spotify/access-token/route.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ jest.mock('next-auth/next', () => ({
1414
const mockedGetServerSession = getServerSession as jest.Mock
1515

1616
describe('API Route: /api/spotify/access-token', () => {
17+
beforeEach(() => {
18+
jest.spyOn(console, 'error').mockImplementation(() => {})
19+
jest.spyOn(console, 'info').mockImplementation(() => {})
20+
})
21+
1722
afterEach(() => {
23+
jest.restoreAllMocks()
1824
jest.clearAllMocks()
1925
})
2026

tests/unit/app/api/spotify/devices/route.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ describe('API Route: /api/spotify/devices', () => {
3333
let tokenManagerInstance: { getValidAccessToken: jest.Mock }
3434

3535
beforeEach(() => {
36+
jest.spyOn(console, 'error').mockImplementation(() => {})
37+
jest.spyOn(console, 'info').mockImplementation(() => {})
38+
3639
jest.clearAllMocks()
3740
// Set up a new mock instance for each test
3841
MockedSpotifyTokenManager.mockClear()
@@ -44,6 +47,11 @@ describe('API Route: /api/spotify/devices', () => {
4447
MockedSpotifyTokenManager.mockImplementation(() => tokenManagerInstance)
4548
})
4649

50+
afterEach(() => {
51+
jest.restoreAllMocks()
52+
jest.clearAllMocks()
53+
})
54+
4755
it('should return 401 if no user session and no system token is available', async () => {
4856
mockedGetServerSession.mockResolvedValue(null)
4957
tokenManagerInstance.getValidAccessToken.mockResolvedValue(null)

tests/unit/app/api/spotify/playlists/route.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@ jest.mock('@spotify/web-api-ts-sdk', () => {
5252
const mockedGetServerSession = getServerSession as jest.Mock
5353

5454
describe('API Route: /api/spotify/playlists', () => {
55+
beforeEach(() => {
56+
jest.spyOn(console, 'error').mockImplementation(() => {})
57+
jest.spyOn(console, 'warn').mockImplementation(() => {})
58+
})
59+
5560
afterEach(() => {
61+
jest.restoreAllMocks()
5662
jest.clearAllMocks()
5763
})
5864

tests/unit/components/GoogleDocViewer.test.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,16 @@ describe('GoogleDocViewer', () => {
4848
})
4949

5050
it('renders nothing if embedUrl is invalid', () => {
51-
const { container } = render(
52-
<GoogleDocViewer title="Test Doc" embedUrl="invalid-url" />
53-
)
54-
expect(container).toBeEmptyDOMElement()
51+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
52+
try {
53+
const { container } = render(
54+
<GoogleDocViewer title="Test Doc" embedUrl="invalid-url" />
55+
)
56+
expect(container).toBeEmptyDOMElement()
57+
expect(errorSpy).toHaveBeenCalledWith('Invalid URL:', 'invalid-url')
58+
} finally {
59+
errorSpy.mockRestore()
60+
}
5561
})
5662

5763
it('renders nothing if embedUrl is empty', () => {

tests/unit/components/SpotifyDisplay.test.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,13 @@ describe('SpotifyDisplay', () => {
165165
})
166166
expect(loginButton).toBeInTheDocument()
167167

168-
// Simulate user click
169-
await userEvent.click(loginButton)
168+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
169+
try {
170+
// Simulate user click
171+
await userEvent.click(loginButton)
172+
} finally {
173+
logSpy.mockRestore()
174+
}
170175

171176
// Assert that signIn was called correctly
172177
expect(mockedSignIn).toHaveBeenCalledTimes(1)

tests/unit/hooks/useBluetoothHRM.race.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ jest.mock('js-cookie', () => ({
3030
}))
3131

3232
describe('useBluetoothHRM Race Conditions', () => {
33+
let infoSpy: jest.SpyInstance
34+
let warnSpy: jest.SpyInstance
35+
36+
beforeAll(() => {
37+
infoSpy = jest.spyOn(console, 'info').mockImplementation(() => {})
38+
warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
39+
})
40+
41+
afterAll(() => {
42+
infoSpy.mockRestore()
43+
warnSpy.mockRestore()
44+
})
45+
3346
const originalNavigator = global.navigator
3447
let mockRequestDevice: jest.Mock
3548
let mockGattConnect: jest.Mock

tests/unit/hooks/usePersistentStorage.test.ts

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -115,40 +115,50 @@ describe('usePersistentStorage', () => {
115115
})
116116

117117
it('should not fallback to cookies when localStorage is available but write fails', () => {
118-
// Mock localStorage: setItem works for the test key (so checkLocalStorage passes)
119-
// but fails for the data key.
120-
Object.defineProperty(window, 'localStorage', {
121-
value: {
122-
setItem: jest.fn((key, _value) => {
123-
if (key === '__hrm_test__') {
124-
return // Success for check
125-
}
126-
throw new Error('QuotaExceeded')
127-
}),
128-
getItem: jest.fn(),
129-
removeItem: jest.fn(),
130-
clear: jest.fn(),
131-
},
132-
writable: true,
133-
configurable: true,
134-
})
135-
136-
const { result } = renderHook(() =>
137-
usePersistentStorage(TEST_KEY, INITIAL_VALUE, {
138-
enableCookieFallback: true,
118+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
119+
120+
try {
121+
// Mock localStorage: setItem works for the test key (so checkLocalStorage passes)
122+
// but fails for the data key.
123+
Object.defineProperty(window, 'localStorage', {
124+
value: {
125+
setItem: jest.fn((key, _value) => {
126+
if (key === '__hrm_test__') {
127+
return // Success for check
128+
}
129+
throw new Error('QuotaExceeded')
130+
}),
131+
getItem: jest.fn(),
132+
removeItem: jest.fn(),
133+
clear: jest.fn(),
134+
},
135+
writable: true,
136+
configurable: true,
139137
})
140-
)
141138

142-
act(() => {
143-
const [, setValue] = result.current
144-
setValue(UPDATED_VALUE)
145-
})
139+
const { result } = renderHook(() =>
140+
usePersistentStorage(TEST_KEY, INITIAL_VALUE, {
141+
enableCookieFallback: true,
142+
})
143+
)
146144

147-
expect(window.localStorage.setItem).toHaveBeenCalledWith(
148-
TEST_KEY,
149-
JSON.stringify(UPDATED_VALUE)
150-
)
151-
expect(Cookies.set).not.toHaveBeenCalled()
145+
act(() => {
146+
const [, setValue] = result.current
147+
setValue(UPDATED_VALUE)
148+
})
149+
150+
expect(window.localStorage.setItem).toHaveBeenCalledWith(
151+
TEST_KEY,
152+
JSON.stringify(UPDATED_VALUE)
153+
)
154+
expect(Cookies.set).not.toHaveBeenCalled()
155+
expect(consoleSpy).toHaveBeenCalledWith(
156+
'LocalStorage write failed:',
157+
expect.any(Error)
158+
)
159+
} finally {
160+
consoleSpy.mockRestore()
161+
}
152162
})
153163

154164
it('should load initial value from localStorage if present', () => {

tests/unit/hooks/useSpotifyWebPlayback.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,20 @@ describe('useSpotifyWebPlayback', () => {
5252
let mockAddError: jest.Mock
5353

5454
beforeEach(() => {
55+
jest.spyOn(console, 'log').mockImplementation(() => {})
56+
jest.spyOn(console, 'error').mockImplementation(() => {})
57+
5558
jest.clearAllMocks()
5659
mockAddError = jest.fn()
5760
mockUseError.mockReturnValue({ addError: mockAddError })
5861
mockUseSpotifyAuth.mockReturnValue({ status: 'authenticated' })
5962
})
6063

64+
afterEach(() => {
65+
jest.restoreAllMocks()
66+
jest.clearAllMocks()
67+
})
68+
6169
it('should initialize the SDK and connect the player on mount', async () => {
6270
mockFetchWithRetry.mockResolvedValue({
6371
ok: true,

tests/unit/lib/env.test.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,17 @@ describe('Environment Variables', () => {
4646
})
4747

4848
it('should throw an error for invalid environment variables', async () => {
49-
process.env.NODE_ENV = 'test'
50-
process.env.NEXTAUTH_URL = 'invalid-url'
51-
process.env.NEXTAUTH_SECRET = 'secret'
52-
process.env.SPOTIFY_CLIENT_ID = 'id'
53-
process.env.SPOTIFY_CLIENT_SECRET = 'secret'
54-
await expect(import('../../../lib/env')).rejects.toThrow(z.ZodError)
49+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
50+
try {
51+
process.env.NODE_ENV = 'test'
52+
process.env.NEXTAUTH_URL = 'invalid-url'
53+
process.env.NEXTAUTH_SECRET = 'secret'
54+
process.env.SPOTIFY_CLIENT_ID = 'id'
55+
process.env.SPOTIFY_CLIENT_SECRET = 'secret'
56+
await expect(import('../../../lib/env')).rejects.toThrow(z.ZodError)
57+
} finally {
58+
errorSpy.mockRestore()
59+
}
5560
})
5661

5762
it('should derive SPOTIFY_CALLBACK_URL from NEXTAUTH_URL if not provided', async () => {
@@ -67,11 +72,16 @@ describe('Environment Variables', () => {
6772
})
6873

6974
it('should throw an error if Spotify credentials are provided but callback URL cannot be determined', async () => {
70-
process.env.NODE_ENV = 'test'
71-
process.env.NEXTAUTH_SECRET = 'secret'
72-
process.env.SPOTIFY_CLIENT_ID = 'id'
73-
process.env.SPOTIFY_CLIENT_SECRET = 'secret'
74-
delete process.env.NEXTAUTH_URL
75-
await expect(import('../../../lib/env')).rejects.toThrow(z.ZodError)
75+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
76+
try {
77+
process.env.NODE_ENV = 'test'
78+
process.env.NEXTAUTH_SECRET = 'secret'
79+
process.env.SPOTIFY_CLIENT_ID = 'id'
80+
process.env.SPOTIFY_CLIENT_SECRET = 'secret'
81+
delete process.env.NEXTAUTH_URL
82+
await expect(import('../../../lib/env')).rejects.toThrow(z.ZodError)
83+
} finally {
84+
errorSpy.mockRestore()
85+
}
7686
})
7787
})

0 commit comments

Comments
 (0)