-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from Firebird1029/backend_tests
Add tests with 77% statement coverage
- Loading branch information
Showing
40 changed files
with
37,099 additions
and
1,165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["@babel/preset-env"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import axios from "axios"; | ||
import { getAverageAudioFeatures } from "../src/spotify"; | ||
|
||
// Mocking axios | ||
jest.mock("axios"); | ||
|
||
describe("Spotify API functions", () => { | ||
describe("getAverageAudioFeatures", () => { | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
test("calls getAudioFeatures with correct parameters", async () => { | ||
const token = "testToken"; | ||
const topSongs = { | ||
items: [ | ||
{ id: "id1", popularity: 70 }, | ||
{ id: "id2", popularity: 80 }, | ||
], | ||
}; | ||
|
||
// Spy on getAudioFeatures | ||
const getAudioFeaturesSpy = jest.spyOn(axios, "get"); | ||
|
||
// Mock the implementation of axios.get to return a resolved promise with dummy data | ||
getAudioFeaturesSpy.mockResolvedValueOnce({ | ||
data: { | ||
audio_features: [ | ||
{ | ||
acousticness: 0.5, | ||
danceability: 0.7, | ||
energy: 0.8, | ||
instrumentalness: 0.3, | ||
speechiness: 0.4, | ||
valence: 0.6, | ||
}, | ||
{ | ||
acousticness: 0.4, | ||
danceability: 0.6, | ||
energy: 0.7, | ||
instrumentalness: 0.2, | ||
speechiness: 0.5, | ||
valence: 0.8, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
await getAverageAudioFeatures(token, topSongs); | ||
|
||
// Assert that getAudioFeatures was called with the correct parameters | ||
expect(getAudioFeaturesSpy).toHaveBeenCalledWith( | ||
expect.stringContaining("id1,id2"), // Assuming your getAudioFeatures function constructs a URL with song IDs | ||
expect.objectContaining({ | ||
headers: { Authorization: `Bearer ${token}` }, | ||
}), | ||
); | ||
}); | ||
|
||
test("throws an error when unable to fetch audio features", async () => { | ||
const token = "testToken"; | ||
const topSongs = { | ||
items: [ | ||
{ id: "id1", popularity: 70 }, | ||
{ id: "id2", popularity: 80 }, | ||
], | ||
}; | ||
|
||
// Mocking the axios.get to return a rejected promise | ||
axios.get.mockRejectedValueOnce( | ||
new Error("Failed to fetch audio features"), | ||
); | ||
|
||
await expect(getAverageAudioFeatures(token, topSongs)).rejects.toThrow( | ||
"Error fetching data from Spotify API: Failed to fetch audio features", | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import axios from "axios"; | ||
import { | ||
callSpotifyApi, | ||
getUserData, | ||
getTopGenres, | ||
getAudioFeatures, | ||
getTopItems, | ||
} from "../src/spotify"; | ||
|
||
// Mocking axios | ||
jest.mock("axios"); | ||
|
||
describe("Spotify API functions", () => { | ||
describe("callSpotifyApi", () => { | ||
test("calls axios.get with correct parameters", async () => { | ||
const token = "testToken"; | ||
const endpoint = "/me"; | ||
const responseData = { data: "testData" }; | ||
axios.get.mockResolvedValue(responseData); | ||
|
||
const result = await callSpotifyApi(token, endpoint); | ||
|
||
expect(axios.get).toHaveBeenCalledWith( | ||
`https://api.spotify.com/v1${endpoint}`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}, | ||
); | ||
expect(result).toEqual(responseData.data); | ||
}); | ||
|
||
test("throws an error if token is not provided", async () => { | ||
const token = ""; | ||
const endpoint = "/me"; | ||
|
||
await expect(callSpotifyApi(token, endpoint)).rejects.toThrow( | ||
"Token not provided.", | ||
); | ||
}); | ||
|
||
test("throws an error if response is not valid", async () => { | ||
const token = "testToken"; | ||
const endpoint = "/me"; | ||
const responseData = null; | ||
axios.get.mockResolvedValue({ data: responseData }); | ||
|
||
await expect(callSpotifyApi(token, endpoint)).rejects.toThrow( | ||
"Unable to fetch data from Spotify API.", | ||
); | ||
}); | ||
|
||
test("throws an error if there is an error during API call", async () => { | ||
const token = "testToken"; | ||
const endpoint = "/me"; | ||
const errorMessage = "Failed to fetch data"; | ||
axios.get.mockRejectedValue(new Error(errorMessage)); | ||
|
||
await expect(callSpotifyApi(token, endpoint)).rejects.toThrow( | ||
`Error fetching data from Spotify API: ${errorMessage}`, | ||
); | ||
}); | ||
}); | ||
|
||
describe("getTopGenres", () => { | ||
test("correctly counts genre frequencies", () => { | ||
const topArtists = [ | ||
{ genres: ["pop", "rock"] }, | ||
{ genres: ["pop", "jazz"] }, | ||
{ genres: ["rock", "hip-hop"] }, | ||
]; | ||
|
||
const result = getTopGenres(topArtists); | ||
|
||
expect(result).toEqual({ pop: 2, rock: 2, jazz: 1, "hip-hop": 1 }); | ||
}); | ||
}); | ||
|
||
describe("getAudioFeatures", () => { | ||
test("throws an error if ids", async () => { | ||
const token = ""; | ||
await expect(getAudioFeatures(token)).rejects.toThrow( | ||
"Ids must be provided.", | ||
); | ||
}); | ||
}); | ||
|
||
describe("getUserData", () => { | ||
test("returns user data when token is provided", async () => { | ||
const token = "testToken"; | ||
const userData = { id: "user123", display_name: "Test User" }; | ||
axios.get.mockResolvedValue({ data: userData }); | ||
|
||
const result = await getUserData(token); | ||
|
||
expect(result).toEqual(userData); | ||
expect(axios.get).toHaveBeenCalledWith("https://api.spotify.com/v1/me", { | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}); | ||
}); | ||
}); | ||
|
||
describe("getTopItems", () => { | ||
test("returns top items when token is provided", async () => { | ||
const token = "testToken"; | ||
const type = "tracks"; | ||
const timeRange = "short_term"; | ||
const limit = "5"; | ||
const topItemsData = [ | ||
{ id: "track1", name: "Track 1" }, | ||
{ id: "track2", name: "Track 2" }, | ||
]; | ||
axios.get.mockResolvedValue({ data: topItemsData }); | ||
|
||
const result = await getTopItems(token, type, timeRange, limit); | ||
|
||
expect(result).toEqual(topItemsData); | ||
expect(axios.get).toHaveBeenCalledWith( | ||
`https://api.spotify.com/v1/me/top/${type}?time_range=${timeRange}&limit=${limit}`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}, | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* eslint-disable react/jsx-filename-extension */ | ||
|
||
import React from "react"; | ||
import { render, screen, fireEvent } from "@testing-library/react"; | ||
import ErrorAlert from "@/app/error/error"; | ||
|
||
describe("ErrorAlert Component Tests", () => { | ||
// Test for proper rendering with props | ||
it("renders with given title and message", () => { | ||
render(<ErrorAlert Title="Error" Message="An error has occurred" />); | ||
expect(screen.getByText("Error")).toBeInTheDocument(); | ||
expect(screen.getByText("An error has occurred")).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import axios from "axios"; | ||
import { getSpotifyData } from "../src/spotify"; // Replace with the correct path to your module | ||
|
||
jest.mock("axios"); | ||
|
||
describe("getSpotifyData", () => { | ||
const mockToken = "mockToken"; | ||
|
||
beforeEach(() => { | ||
axios.get.mockClear(); | ||
}); | ||
|
||
test("should fetch user data and return formatted user data", async () => { | ||
const getUserDataSpy = jest.spyOn(axios, "get"); | ||
getUserDataSpy.mockResolvedValueOnce({ | ||
data: {}, | ||
}); | ||
|
||
const topArtistsShortDataSpy = jest.spyOn(axios, "get"); | ||
topArtistsShortDataSpy.mockResolvedValueOnce({ | ||
data: { | ||
items: [ | ||
{ genres: ["pop", "rock"] }, | ||
{ genres: ["pop", "jazz"] }, | ||
{ genres: ["rock", "hip-hop"] }, | ||
], | ||
}, | ||
}); | ||
const topArtistsMediumDataSpy = jest.spyOn(axios, "get"); | ||
topArtistsMediumDataSpy.mockResolvedValueOnce({ | ||
data: { | ||
items: [ | ||
{ genres: ["pop", "rock"] }, | ||
{ genres: ["pop", "jazz"] }, | ||
{ genres: ["rock", "hip-hop"] }, | ||
], | ||
}, | ||
}); | ||
const topArtistsLongDataSpy = jest.spyOn(axios, "get"); | ||
topArtistsLongDataSpy.mockResolvedValueOnce({ | ||
data: { | ||
items: [ | ||
{ genres: ["pop", "rock"] }, | ||
{ genres: ["pop", "jazz"] }, | ||
{ genres: ["rock", "hip-hop"] }, | ||
], | ||
}, | ||
}); | ||
|
||
const topSongsShortDataSpy = jest.spyOn(axios, "get"); | ||
topSongsShortDataSpy.mockResolvedValueOnce({ | ||
data: {}, | ||
}); | ||
const topSongsMediumDataSpy = jest.spyOn(axios, "get"); | ||
topSongsMediumDataSpy.mockResolvedValueOnce({ | ||
data: {}, | ||
}); | ||
const topSongsLongDataSpy = jest.spyOn(axios, "get"); | ||
topSongsLongDataSpy.mockResolvedValueOnce({ | ||
data: { items: Array(50).fill(0) }, | ||
}); | ||
|
||
// Spy on getAudioFeatures | ||
const getAudioFeaturesSpy = jest.spyOn(axios, "get"); | ||
|
||
// Mock the implementation of axios.get to return a resolved promise with dummy data | ||
getAudioFeaturesSpy.mockResolvedValueOnce({ | ||
data: { | ||
audio_features: [ | ||
{ | ||
acousticness: 0.5, | ||
danceability: 0.7, | ||
energy: 0.8, | ||
instrumentalness: 0.3, | ||
speechiness: 0.4, | ||
valence: 0.6, | ||
}, | ||
{ | ||
acousticness: 0.4, | ||
danceability: 0.6, | ||
energy: 0.7, | ||
instrumentalness: 0.2, | ||
speechiness: 0.5, | ||
valence: 0.8, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
const result = await getSpotifyData(mockToken); | ||
|
||
expect(axios.get).toHaveBeenCalledTimes(8); | ||
expect(axios.get).toHaveBeenCalledWith("https://api.spotify.com/v1/me", { | ||
headers: { Authorization: `Bearer ${mockToken}` }, | ||
}); | ||
expect(axios.get).toHaveBeenCalledWith( | ||
"https://api.spotify.com/v1/me/top/artists?time_range=short_term&limit=25", | ||
{ | ||
headers: { Authorization: `Bearer ${mockToken}` }, | ||
}, | ||
); | ||
}); | ||
|
||
test("should throw an error if token is not provided", async () => { | ||
await expect(getSpotifyData()).rejects.toThrow("Token not provided."); | ||
}); | ||
}); |
Oops, something went wrong.