diff --git a/.github/workflows/enforce-dev-to-main.yml b/.github/workflows/enforce-dev-to-main.yml index 240c075..5de7ac7 100644 --- a/.github/workflows/enforce-dev-to-main.yml +++ b/.github/workflows/enforce-dev-to-main.yml @@ -1,6 +1,8 @@ name: Ensure only `dev` can merge into `main` on: - pull_request_target: + pull_request: + branches: + - main types: - opened - reopened diff --git a/.github/workflows/run-jest-tests.yml b/.github/workflows/run-jest-tests.yml index bdd3ad2..60b04a2 100644 --- a/.github/workflows/run-jest-tests.yml +++ b/.github/workflows/run-jest-tests.yml @@ -21,6 +21,6 @@ jobs: with: node-version: 18.x - run: npm install - - run: npm test + - run: npm test -- --verbose - if: ${{ failure() }} run: exit 1 diff --git a/src/utils/array.test.ts b/src/utils/array.test.ts index e068187..3cd139b 100644 --- a/src/utils/array.test.ts +++ b/src/utils/array.test.ts @@ -1,29 +1,31 @@ import { getBiggestImageUrl } from "@utils/array"; -//#region getBiggestImageUrl -describe("getBiggestImageUrl", () => { - it("should return url of image with highest width", () => { - const images: SpotifyImage[] = [ - { url: "small.jpg", width: 100, height: 100 }, - { url: "large.jpg", width: 300, height: 300 }, - { url: "medium.jpg", width: 200, height: 200 }, - ]; - expect(getBiggestImageUrl(images)).toBe("large.jpg"); - }); +describe("Array Helpers", () => { + //#region getBiggestImageUrl + describe("getBiggestImageUrl", () => { + it("should return url of image with highest width", () => { + const images: SpotifyImage[] = [ + { url: "small.jpg", width: 100, height: 100 }, + { url: "large.jpg", width: 300, height: 300 }, + { url: "medium.jpg", width: 200, height: 200 }, + ]; + expect(getBiggestImageUrl(images)).toBe("large.jpg"); + }); - it("should return first url if multiple images with same width", () => { - const images: SpotifyImage[] = [ - { url: "large-image-1.jpg", width: 300, height: 300 }, - { url: "small.jpg", width: 100, height: 100 }, - { url: "large-image-2.jpg", width: 300, height: 300 }, - ]; - expect(getBiggestImageUrl(images)).toBe("large-image-1.jpg"); - }); + it("should return first url if multiple images with same width", () => { + const images: SpotifyImage[] = [ + { url: "large-image-1.jpg", width: 300, height: 300 }, + { url: "small.jpg", width: 100, height: 100 }, + { url: "large-image-2.jpg", width: 300, height: 300 }, + ]; + expect(getBiggestImageUrl(images)).toBe("large-image-1.jpg"); + }); - it("should return empty string if no images", () => { - const images: SpotifyImage[] = []; + it("should return empty string if no images", () => { + const images: SpotifyImage[] = []; - expect(getBiggestImageUrl(images)).toBe(""); + expect(getBiggestImageUrl(images)).toBe(""); + }); }); + //#endregion }); -//#endregion diff --git a/src/utils/spotify/api.test.ts b/src/utils/spotify/api.test.ts index 5c94816..a5aa071 100644 --- a/src/utils/spotify/api.test.ts +++ b/src/utils/spotify/api.test.ts @@ -1,7 +1,6 @@ import { SpotifyService } from "@utils/spotify"; import { SpotifyApiService } from "@utils/spotify/api"; import { jest } from "@jest/globals"; -import { integrationManager, logger } from "@utils/firebot"; type DummyDataType = { foo: string; @@ -18,7 +17,7 @@ jest.mock("@utils/firebot", () => ({ chatFeedAlert: jest.fn(() => {}), })); -describe("SpotifyApiService", () => { +describe("Spotify - Api Service", () => { let spotify: SpotifyService; let api: SpotifyApiService; diff --git a/src/utils/spotify/device.test.ts b/src/utils/spotify/device.test.ts index 187a3e3..9f54029 100644 --- a/src/utils/spotify/device.test.ts +++ b/src/utils/spotify/device.test.ts @@ -1,6 +1,6 @@ import { SpotifyDeviceService } from "@utils/spotify/device"; -describe("SpotifyDeviceService", () => { +describe("Spotify - Device Service", () => { let spotifyDevice: SpotifyDeviceService; const defaults = { @@ -12,16 +12,20 @@ describe("SpotifyDeviceService", () => { spotifyDevice = new SpotifyDeviceService(); }); - it("should have default getter values", () => { - for (const [key, value] of Object.entries(defaults)) { - expect(spotifyDevice[key as keyof SpotifyDeviceService]).toBe(value); - } + describe("Getters", () => { + it("should have default getter values", () => { + for (const [key, value] of Object.entries(defaults)) { + expect(spotifyDevice[key as keyof SpotifyDeviceService]).toBe(value); + } + }); }); - it("should update device id", () => { - spotifyDevice.updateId("1234"); + describe("updateId", () => { + it("should update device id", () => { + spotifyDevice.updateId("1234"); - expect(spotifyDevice.isAvailable).toBe(true); - expect(spotifyDevice.id).toBe("1234"); + expect(spotifyDevice.isAvailable).toBe(true); + expect(spotifyDevice.id).toBe("1234"); + }); }); }); diff --git a/src/utils/spotify/index.test.ts b/src/utils/spotify/index.test.ts index cc00f96..cc05d20 100644 --- a/src/utils/spotify/index.test.ts +++ b/src/utils/spotify/index.test.ts @@ -2,7 +2,7 @@ import { SpotifyService } from "@utils/spotify"; import { jest } from "@jest/globals"; import { testSearchResponse, testTrack } from "@/testData"; -describe("SpotifyService", () => { +describe("Spotify Service", () => { let spotify: SpotifyService; beforeEach(() => { @@ -17,22 +17,24 @@ describe("SpotifyService", () => { jest.clearAllMocks(); }); - it("search returns search response", async () => { - const response = await spotify.searchAsync("testing", "track"); - - expect(response).toBe(testSearchResponse); - }); - - it("search returns expected number of tracks", async () => { - testSearchResponse.tracks.items = [ - testTrack, - testTrack, - testTrack, - testTrack, - testTrack, - ]; - const response = await spotify.searchAsync("testing", "track"); - - expect(response.tracks.items.length).toBe(5); + describe("searchAsync", () => { + it("search returns search response", async () => { + const response = await spotify.searchAsync("testing", "track"); + + expect(response).toBe(testSearchResponse); + }); + + it("search returns expected number of tracks", async () => { + testSearchResponse.tracks.items = [ + testTrack, + testTrack, + testTrack, + testTrack, + testTrack, + ]; + const response = await spotify.searchAsync("testing", "track"); + + expect(response.tracks.items.length).toBe(5); + }); }); }); diff --git a/src/utils/spotify/player/index.test.ts b/src/utils/spotify/player/index.test.ts index 62a7d8c..c448220 100644 --- a/src/utils/spotify/player/index.test.ts +++ b/src/utils/spotify/player/index.test.ts @@ -1,7 +1,7 @@ import SpotifyPlayerService from "."; import { SpotifyService } from ".."; -describe("SpotifyPlayerService", () => { +describe("Spotify - Player Service", () => { let spotify: SpotifyService; let player: SpotifyPlayerService; @@ -10,9 +10,11 @@ describe("SpotifyPlayerService", () => { player = new SpotifyPlayerService(spotify); }); - it("should have default getter values", () => { - expect(player.isPlaying).toBe(false); - expect(player.volume).toBe(-1); - expect(player.volumeWasManuallyChanged).toBe(false); + describe("Getters", () => { + it("should have default getter values", () => { + expect(player.isPlaying).toBe(false); + expect(player.volume).toBe(-1); + expect(player.volumeWasManuallyChanged).toBe(false); + }); }); }); diff --git a/src/utils/spotify/player/lyrics.test.ts b/src/utils/spotify/player/lyrics.test.ts index ea5872f..ad64d9f 100644 --- a/src/utils/spotify/player/lyrics.test.ts +++ b/src/utils/spotify/player/lyrics.test.ts @@ -2,7 +2,7 @@ import { testLyricData } from "@/testData"; import { SpotifyService } from ".."; import { SpotifyLyricsService, LyricsHelpers } from "./lyrics"; -describe("SpotifyLyricsService", () => { +describe("Spotify - Lyrics Service", () => { let spotify: SpotifyService; let lyrics: SpotifyLyricsService; @@ -30,35 +30,41 @@ describe("SpotifyLyricsService", () => { jest.clearAllMocks(); }); - it("should have default getter values", async () => { - jest - .spyOn(LyricsHelpers, "lyricsFileExistsAsync") - .mockImplementation(() => Promise.resolve(false)); + describe("Getters", () => { + it("should have default getter values", async () => { + jest + .spyOn(LyricsHelpers, "lyricsFileExistsAsync") + .mockImplementation(() => Promise.resolve(false)); - const fileExists = await lyrics.trackHasLyricsFile; - expect(fileExists).toBe(false); + const fileExists = await lyrics.trackHasLyricsFile; + expect(fileExists).toBe(false); - for (const [key, value] of Object.entries(defaults)) { - expect(lyrics[key as keyof SpotifyLyricsService]).toBe(value); - } + for (const [key, value] of Object.entries(defaults)) { + expect(lyrics[key as keyof SpotifyLyricsService]).toBe(value); + } + }); }); - it("should return true if file exists if path check resolves true", async () => { - const fileExists = await lyrics.trackHasLyricsFile; - expect(fileExists).toBe(true); - }); + describe("Helper Functions", () => { + describe("lyricsFileExistsAsync", () => { + it("should return true if file exists if path check resolves true", async () => { + const fileExists = await lyrics.trackHasLyricsFile; + expect(fileExists).toBe(true); + }); - it("should load lyrics file if file exists", async () => { - await lyrics.loadLyricsFileAsync(); + it("should load lyrics file if file exists", async () => { + await lyrics.loadLyricsFileAsync(); - const response = await lyrics.formatLines(testLyricData); + const response = await lyrics.formatLines(testLyricData); - expect(response).toEqual( - testLyricData.lyrics.lines.map((l) => ({ - ...l, - startTimeMs: Number(l.startTimeMs), - endTimeMs: Number(l.endTimeMs), - })) - ); + expect(response).toEqual( + testLyricData.lyrics.lines.map((l) => ({ + ...l, + startTimeMs: Number(l.startTimeMs), + endTimeMs: Number(l.endTimeMs), + })) + ); + }); + }); }); }); diff --git a/src/utils/spotify/player/playlist.test.ts b/src/utils/spotify/player/playlist.test.ts index 52346e4..365f7a0 100644 --- a/src/utils/spotify/player/playlist.test.ts +++ b/src/utils/spotify/player/playlist.test.ts @@ -4,7 +4,7 @@ import { SpotifyPlaylistService } from "@utils/spotify/player/playlist"; import { testPlaylist } from "@/testData"; import { getBiggestImageUrl } from "@utils/array"; -describe("SpotifyPlaylistService", () => { +describe("Spotify - Playlist Service", () => { let spotify: SpotifyService; let playlist: SpotifyPlaylistService; @@ -36,42 +36,48 @@ describe("SpotifyPlaylistService", () => { jest.spyOn(spotify.events, "trigger").mockImplementation(() => {}); }); - it("should have default getter values", () => { - for (const [key, value] of Object.entries(defaults)) { - expect(playlist[key as keyof SpotifyPlaylistService]).toBe(value); - } + describe("Getters", () => { + it("should have default getter values", () => { + for (const [key, value] of Object.entries(defaults)) { + expect(playlist[key as keyof SpotifyPlaylistService]).toBe(value); + } + }); }); - it("should fetch playlist by uri", async () => { - const response = await playlist.fetchByUriAsync(testPlaylist.uri); - expect(response).toBe(testPlaylist); + describe("fetchByUriAsync", () => { + it("should fetch playlist by uri", async () => { + const response = await playlist.fetchByUriAsync(testPlaylist.uri); + expect(response).toBe(testPlaylist); + }); }); - it("should update current playlist", async () => { - await playlist.updateByUriAsync(testPlaylist.uri); + describe("updateByUriAsync", () => { + it("should update current playlist", async () => { + await playlist.updateByUriAsync(testPlaylist.uri); - expect(playlist.isActive).toBe(true); - expect(playlist.id).toBe(testPlaylist.id); - expect(playlist.name).toBe(testPlaylist.name); - expect(playlist.description).toBe(testPlaylist.description); - expect(playlist.url).toBe(testPlaylist.external_urls.spotify); - expect(playlist.uri).toBe(testPlaylist.uri); - expect(playlist.coverImageUrl).toBe( - getBiggestImageUrl(testPlaylist.images) - ); - expect(playlist.owner).toBe(testPlaylist.owner.display_name); - expect(playlist.ownerUrl).toBe(testPlaylist.owner.external_urls.spotify); - expect(playlist.length).toBe(testPlaylist.tracks.total); - }); + expect(playlist.isActive).toBe(true); + expect(playlist.id).toBe(testPlaylist.id); + expect(playlist.name).toBe(testPlaylist.name); + expect(playlist.description).toBe(testPlaylist.description); + expect(playlist.url).toBe(testPlaylist.external_urls.spotify); + expect(playlist.uri).toBe(testPlaylist.uri); + expect(playlist.coverImageUrl).toBe( + getBiggestImageUrl(testPlaylist.images) + ); + expect(playlist.owner).toBe(testPlaylist.owner.display_name); + expect(playlist.ownerUrl).toBe(testPlaylist.owner.external_urls.spotify); + expect(playlist.length).toBe(testPlaylist.tracks.total); + }); - it("should clear playlist if null is passed through update", async () => { - // fill playlist to ensure null update actually has to do something - await playlist.updateByUriAsync(testPlaylist.uri); + it("should clear playlist if null is passed through update", async () => { + // fill playlist to ensure null update actually has to do something + await playlist.updateByUriAsync(testPlaylist.uri); - await playlist.updateByUriAsync(null); + await playlist.updateByUriAsync(null); - for (const [key, value] of Object.entries(defaults)) { - expect(playlist[key as keyof SpotifyPlaylistService]).toBe(value); - } + for (const [key, value] of Object.entries(defaults)) { + expect(playlist[key as keyof SpotifyPlaylistService]).toBe(value); + } + }); }); }); diff --git a/src/utils/spotify/player/queue.test.ts b/src/utils/spotify/player/queue.test.ts index 9c6c615..54fd0c5 100644 --- a/src/utils/spotify/player/queue.test.ts +++ b/src/utils/spotify/player/queue.test.ts @@ -3,7 +3,7 @@ import { SpotifyService } from "@utils/spotify"; import { testQueue } from "@/testData"; import { SpotifyQueueService } from "./queue"; -describe("SpotifyQueueService", () => { +describe("Spotify - Queue Service", () => { let spotify: SpotifyService; let queue: SpotifyQueueService; @@ -26,30 +26,39 @@ describe("SpotifyQueueService", () => { jest.clearAllMocks(); }); - it("should get current queue", async () => { - const response = await queue.getAsync(); + describe("getAsync", () => { + it("should get current queue", async () => { + const response = await queue.getAsync(); - expect(response.currently_playing.name).toBe( - testQueue.currently_playing.name - ); - expect(response.queue.length).toBe(testQueue.queue.length); + expect(response.currently_playing.name).toBe( + testQueue.currently_playing.name + ); + expect(response.queue.length).toBe(testQueue.queue.length); - for (let i = 0; i < testQueue.queue.length; i++) { - expect(response.queue[i].id).toBe(testQueue.queue[i].id); - } + for (let i = 0; i < testQueue.queue.length; i++) { + expect(response.queue[i].id).toBe(testQueue.queue[i].id); + } + }); }); - it("should get correct index of currently playing track", async () => { - const response = await queue.findIndexAsync( - testQueue.currently_playing.uri - ); - expect(response).toBe(0); - }); + describe("findIndexAsync", () => { + it("should get correct index of currently playing track", async () => { + const response = await queue.findIndexAsync( + testQueue.currently_playing.uri + ); + expect(response).toBe(0); + }); + + it("should get correct index of queued tracks", async () => { + for (let i = 1; i <= testQueue.queue.length; i++) { + const response = await queue.findIndexAsync(testQueue.queue[i - 1].uri); + expect(response).toBe(i); + } + }); - it("should get correct index of queued tracks", async () => { - for (let i = 1; i <= testQueue.queue.length; i++) { - const response = await queue.findIndexAsync(testQueue.queue[i - 1].uri); - expect(response).toBe(i); - } + it("should return -1 if not found", async () => { + const response = await queue.findIndexAsync("not found"); + expect(response).toBe(-1); + }); }); }); diff --git a/src/utils/spotify/player/track.test.ts b/src/utils/spotify/player/track.test.ts index fc2aaf1..75a503b 100644 --- a/src/utils/spotify/player/track.test.ts +++ b/src/utils/spotify/player/track.test.ts @@ -5,7 +5,7 @@ import { getBiggestImageUrl } from "@utils/array"; import { SpotifyTrackService } from "./track"; import { formatMsToTimecode } from "@/utils/string"; -describe("SpotifyTrackService", () => { +describe("Spotify - Track Service", () => { let spotify: SpotifyService; let track: SpotifyTrackService; diff --git a/src/utils/string.test.ts b/src/utils/string.test.ts index c882e93..8fa4199 100644 --- a/src/utils/string.test.ts +++ b/src/utils/string.test.ts @@ -1,53 +1,55 @@ import ResponseError from "@/models/responseError"; import { getErrorMessage, formatMsToTimecode } from "@/utils/string"; -//#region msToFormattedString -describe("msToFormattedString", () => { - beforeEach(() => {}); +describe("String Helpers", () => { + //#region msToFormattedString + describe("msToFormattedString", () => { + beforeEach(() => {}); - it("returns expected string value for small number", () => { - expect(formatMsToTimecode(1000)).toBe("0:01"); - }); + it("returns expected string value for small number", () => { + expect(formatMsToTimecode(1000)).toBe("0:01"); + }); - it("returns expected string with floored ms", () => { - expect(formatMsToTimecode(956)).toBe("0:00"); - expect(formatMsToTimecode(1240)).toBe("0:01"); - }); + it("returns expected string with floored ms", () => { + expect(formatMsToTimecode(956)).toBe("0:00"); + expect(formatMsToTimecode(1240)).toBe("0:01"); + }); - it("includes hours in string value when enabled", () => { - expect(formatMsToTimecode(60000, true)).toBe("0:01:00"); - }); + it("includes hours in string value when enabled", () => { + expect(formatMsToTimecode(60000, true)).toBe("0:01:00"); + }); - it("returns expected string value for large number", () => { - expect(formatMsToTimecode(3600000)).toBe("1:00:00"); - }); + it("returns expected string value for large number", () => { + expect(formatMsToTimecode(3600000)).toBe("1:00:00"); + }); - it("returns expected string value for silly number", () => { - expect(formatMsToTimecode(817000)).toBe("13:37"); + it("returns expected string value for silly number", () => { + expect(formatMsToTimecode(817000)).toBe("13:37"); + }); }); -}); -//#endregion + //#endregion -//#region getErrorMessage -describe("getErrorMessage", () => { - it("returns error message for Error", () => { - expect(getErrorMessage(new Error("test"))).toBe("test"); - }); + //#region getErrorMessage + describe("getErrorMessage", () => { + it("returns error message for Error", () => { + expect(getErrorMessage(new Error("test"))).toBe("test"); + }); - it("returns error message for ResponseError", () => { - expect(getErrorMessage(new ResponseError("test", {}))).toBe("test"); - }); + it("returns error message for ResponseError", () => { + expect(getErrorMessage(new ResponseError("test", {}))).toBe("test"); + }); - it("returns expected string value for string", () => { - expect(getErrorMessage("test")).toBe("test"); - }); + it("returns expected string value for string", () => { + expect(getErrorMessage("test")).toBe("test"); + }); - it("returns expected string value for number", () => { - expect(getErrorMessage(123)).toBe("123"); - }); + it("returns expected string value for number", () => { + expect(getErrorMessage(123)).toBe("123"); + }); - it("returns `Unhandled Exception` when no message found", () => { - expect(getErrorMessage({ someData: "test" })).toBe("Unhandled Exception"); + it("returns `Unhandled Exception` when no message found", () => { + expect(getErrorMessage({ someData: "test" })).toBe("Unhandled Exception"); + }); }); + //#endregion }); -//#endregion diff --git a/src/utils/time.test.ts b/src/utils/time.test.ts index 48ff9fb..ffb5bc5 100644 --- a/src/utils/time.test.ts +++ b/src/utils/time.test.ts @@ -8,21 +8,23 @@ jest.mock("@utils/firebot", () => ({ }, })); -describe("delay", () => { - it("resolves after ms", async () => { - const startTime = now(); - await delay(100); - expect(now() - startTime).toBeGreaterThanOrEqual(100); - }); +describe("Time Helpers", () => { + describe("delay", () => { + it("resolves after ms", async () => { + const startTime = now(); + await delay(100); + expect(now() - startTime).toBeGreaterThanOrEqual(100); + }); - it("logs warning if method took longer than expected", async () => { - const startTime = now() - 5000; + it("logs warning if method took longer than expected", async () => { + const startTime = now() - 5000; - await delay(1000, startTime); + await delay(1000, startTime); - // Check if logger.warn was called - expect(logger.warn).toHaveBeenCalledWith( - expect.stringContaining("Possible overload: method took") - ); + // Check if logger.warn was called + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining("Possible overload: method took") + ); + }); }); });