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"