diff --git a/.eslintrc.js b/.eslintrc.js index 4c527d3ab..710ccb1ac 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -37,5 +37,6 @@ module.exports = { max: 3, }, ], + 'testing-library/no-node-access': ['error', { allowContainerFirstChild: true }], }, }; diff --git a/package.json b/package.json index cce450335..156f93dc6 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,8 @@ "turbo": "^1.7.4", "typescript": "^4.7.4", "video.js": "^8.0.3", - "vitest": "^0.29.3" + "vitest": "^0.29.3", + "vitest-fetch-mock": "^0.2.2" }, "resolutions": { "@types/react": "17.0.2", diff --git a/setupVitest.ts b/setupVitest.ts new file mode 100644 index 000000000..6d1c12953 --- /dev/null +++ b/setupVitest.ts @@ -0,0 +1,8 @@ +//setupVitest.js or similar file +import createFetchMock from 'vitest-fetch-mock'; +import { vi } from 'vitest'; + +const fetchMocker = createFetchMock(vi); + +// sets globalThis.fetch and globalThis.fetchMock to our mocked version +fetchMocker.enableMocks(); diff --git a/src/components/AppAvatar.test.tsx b/src/components/AppAvatar.test.tsx index b5cb29eaf..014043d6f 100644 --- a/src/components/AppAvatar.test.tsx +++ b/src/components/AppAvatar.test.tsx @@ -2,15 +2,51 @@ import { render } from '@testing-library/react'; import { describe, expect, it } from 'vitest'; import { AppAvatar } from './AppAvatar'; -describe(AppAvatar.name, () => { - it.concurrent('display placeholder when no url', () => { +describe('AppAvatar', () => { + it('display placeholder when no url', () => { const { container } = render(); - expect(container.firstElementChild).not.toBeNull(); - expect(container.firstElementChild!.className).contain('mantine-Avatar-root'); + expect(container.firstChild).toMatchInlineSnapshot(` +
+
+ + + +
+
+ `); + }); - const svgElement = container.querySelector('svg'); - expect(svgElement).not.toBeNull(); - expect(svgElement?.getAttribute('fill')).not.toBeNull(); + it('display placeholder when valid url', () => { + const { container } = render( + + ); + + expect(container.firstChild).toMatchInlineSnapshot(` +
+ +
+ `); }); }); diff --git a/src/tools/server/getServerSideTranslations.ts b/src/tools/server/getServerSideTranslations.ts index aa782cd7a..88fa1b6e3 100644 --- a/src/tools/server/getServerSideTranslations.ts +++ b/src/tools/server/getServerSideTranslations.ts @@ -9,7 +9,7 @@ export const getServerSideTranslations = async ( res?: ServerResponse, ) => { if (!req || !res) { - return await serverSideTranslations( + return serverSideTranslations( requestLocale ?? 'en', namespaces ); @@ -17,7 +17,7 @@ export const getServerSideTranslations = async ( const configLocale = getCookie('config-locale', { req, res }); - return await serverSideTranslations( + return serverSideTranslations( (configLocale ?? requestLocale ?? 'en') as string, namespaces ); diff --git a/src/tools/server/sdk/plex/plexClient.test.ts b/src/tools/server/sdk/plex/plexClient.test.ts new file mode 100644 index 000000000..557767022 --- /dev/null +++ b/src/tools/server/sdk/plex/plexClient.test.ts @@ -0,0 +1,73 @@ +import { describe, expect, it } from 'vitest'; +import 'vitest-fetch-mock'; +import { PlexClient } from './plexClient'; + +const mockResponse = ` + +`; + +describe('Plex SDK', () => { + it('abc', async () => { + // arrange + const client = new PlexClient('https://plex', 'MY_TOKEN'); + + fetchMock.mockResponseOnce(mockResponse); + + // act + const response = await client.getSessions(); + + // assert + expect(fetchMock.requests().length).toBe(1); + expect(fetchMock.requests()[0].url).toBe('https://plex/status/sessions?X-Plex-Token=MY_TOKEN'); + expect(response).not.toBeNull(); + expect(response.length).toBe(1); + expect(response[0].id).toBe('2894294r2jf2038fj3098jgf3gt'); + expect(response[0].username).toBe('example_usr'); + expect(response[0].userProfilePicture).toBe('https://google.com'); + expect(response[0].sessionName).toBe('Plex Web (Chrome)'); + expect(response[0].currentlyPlaying).toMatchObject({ + name: 'A long title', + type: 'movie', + metadata: { + video: { + bitrate: '20231', + height: '1080', + videoCodec: 'h264', + videoFrameRate: '24p', + width: '1920', + }, + audio: { audioChannels: '2', audioCodec: 'aac' }, + transcoding: { + audioChannels: '2', + audioCodec: 'aac', + audioDecision: 'transcode', + container: 'mp4', + context: 'streaming', + duration: '100', + error: false, + height: '1080', + sourceAudioCodec: 'dca', + sourceVideoCodec: 'h264', + timeStamp: '1679349635.2791338', + transcodeHwRequested: false, + videoCodec: 'h264', + videoDecision: 'copy', + width: '1920', + }, + }, + }); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 8f02bb21c..84963283d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,6 +12,9 @@ export default defineConfig({ reporter: ['html'], all: true, exclude: ['.next/', '.yarn/', 'data/'] - } + }, + setupFiles: [ + "./setupVitest.ts" + ] }, }); diff --git a/yarn.lock b/yarn.lock index 1c4215b7d..9af9f32dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3145,6 +3145,15 @@ __metadata: languageName: node linkType: hard +"cross-fetch@npm:^3.0.6": + version: 3.1.5 + resolution: "cross-fetch@npm:3.1.5" + dependencies: + node-fetch: 2.6.7 + checksum: f6b8c6ee3ef993ace6277fd789c71b6acf1b504fd5f5c7128df4ef2f125a429e29cd62dc8c127523f04a5f2fa4771ed80e3f3d9695617f441425045f505cf3bb + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -4932,6 +4941,7 @@ __metadata: uuid: ^8.3.2 video.js: ^8.0.3 vitest: ^0.29.3 + vitest-fetch-mock: ^0.2.2 xml-js: ^1.6.11 yarn: ^1.22.19 zustand: ^4.1.4 @@ -6273,6 +6283,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:2.6.7": + version: 2.6.7 + resolution: "node-fetch@npm:2.6.7" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b + languageName: node + linkType: hard + "node-gyp@npm:latest": version: 9.3.1 resolution: "node-gyp@npm:9.3.1" @@ -7868,6 +7892,13 @@ __metadata: languageName: node linkType: hard +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 + languageName: node + linkType: hard + "tsconfig-paths@npm:^3.14.1": version: 3.14.1 resolution: "tsconfig-paths@npm:3.14.1" @@ -8304,6 +8335,17 @@ __metadata: languageName: node linkType: hard +"vitest-fetch-mock@npm:^0.2.2": + version: 0.2.2 + resolution: "vitest-fetch-mock@npm:0.2.2" + dependencies: + cross-fetch: ^3.0.6 + peerDependencies: + vitest: ">=0.16.0" + checksum: fa160f301171cd45dbf7d782880b6b6063fc74b9dd1965ef9206545e812ca8696e6be76662afbac822c6bf850fbb66cf8fb066af646e0e159f5a87ab25c97a02 + languageName: node + linkType: hard + "vitest@npm:^0.29.3": version: 0.29.3 resolution: "vitest@npm:0.29.3" @@ -8378,6 +8420,13 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c + languageName: node + linkType: hard + "webidl-conversions@npm:^7.0.0": version: 7.0.0 resolution: "webidl-conversions@npm:7.0.0" @@ -8430,6 +8479,16 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: ~0.0.3 + webidl-conversions: ^3.0.0 + checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + languageName: node + linkType: hard + "which-boxed-primitive@npm:^1.0.2": version: 1.0.2 resolution: "which-boxed-primitive@npm:1.0.2"