-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Create a Service for providing video/category data #10 (Demo-rebase with @OGTor & @mblomdahl!) * #10 Update after reviews Changes: - Removed root-level package.json and package-lock.json - Removed package.json dependency on `peertube/embed-api` - Moved testData.json from root level to `OwnTube.tv/` Node project directory - Load testData.json via CommonJS import instead of HTTP request to web server From commits 4/3 to 6/3: - github actions testData fix v11 - github actions testData fix v10 - revert - test - github actions testData fix v9 - github actions testData fix v8 - github actions testData fix v7 - github actions testData fix v6 - github actions testData fix v5 - github actions testData fix v4 - github actions testData fix v3 - github actions testData fix - github actions testData fix - Changes information in testData.json - Fixes: Changed to using testData instead of test API - Create a Service for providing video/category data #10 (Rebase-demo med @OGTor och @mblomdahl!) * PR #19 contribution on service tests (OGTor/web-client#1) This PR adds test coverage for the behavior described in task #10 using Jest, which seems to be the test framework of choice for React Native (see [Testing docs here](https://reactnative.dev/docs/testing-overview#unit-tests)). @OGTor please merge this in and update your VideoService to pass all tests without test suite modifications! (Demo-rebase med @OGTor och @mblomdahl!) * Pass tests from OGTor/web-client#1 + PR comments Changes: - Updated `videoService.tsx` to pass all tests - Updated `VideoDataService.tsx` to render app landing page with videos **in** categories From squashed updates from 15/3 to 22/3: - final commit v2 - Revert "Final commit", This reverts commit 5b94307. - Final commit - test fix v3 - test fix v2 - fix for testing - Create a Service for providing video/category data #10 - final changes - changed category * Remove type Category * Prettier & remove extra testData.json * update after review 2 * changes after eslint errors * Moved VideoServiceState, Fixed thumbnail Render * Removed inline styling for eslint error
- Loading branch information
Showing
9 changed files
with
7,740 additions
and
4,213 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import { View, Text, Image, StyleSheet } from "react-native"; | ||
import VideoService from "../lib/videoServices"; | ||
import { Video } from "../types"; | ||
|
||
export interface VideoServiceState { | ||
videos: Video[]; | ||
categories: string[]; | ||
error: string | null; | ||
} | ||
const useVideoService = () => { | ||
const [state, setState] = useState<VideoServiceState>({ | ||
videos: [], | ||
categories: [], | ||
error: null, | ||
}); | ||
|
||
useEffect(() => { | ||
const videoService = new VideoService(); | ||
|
||
const fetchVideos = async () => { | ||
try { | ||
videoService.loadVideosFromJson(); | ||
const categoryLabels = videoService.getVideoCategoryLabels(); | ||
const videosWithThumbnails = videoService.completeThumbnailUrls(); | ||
setState({ | ||
videos: videosWithThumbnails, | ||
categories: categoryLabels, | ||
error: null, | ||
}); | ||
} catch (error) { | ||
console.error("Error fetching videos:", (error as Error).message); | ||
setState((prev) => ({ ...prev, error: (error as Error).message })); | ||
} | ||
}; | ||
|
||
fetchVideos(); | ||
}, []); | ||
return state; | ||
}; | ||
|
||
const VideoDataService: React.FC = () => { | ||
const { videos, categories, error } = useVideoService(); | ||
|
||
if (error) { | ||
return ( | ||
<View> | ||
<Text>Error: {error}</Text> | ||
</View> | ||
); | ||
} | ||
|
||
return ( | ||
<View> | ||
{/* Display Category Labels */} | ||
{categories.map((category) => ( | ||
<View key={category}> | ||
<Text>Category: {category}</Text> | ||
<View> | ||
{videos | ||
.filter((video) => video.category.label === category) | ||
.map((video) => ( | ||
<View key={video.id}> | ||
<Text>ID: {video.id}</Text> | ||
<Text>Name: {video.name}</Text> | ||
<Text>Category ID: {video.category.id}</Text> | ||
<Text>Category Label: {video.category.label}</Text> | ||
<Image source={{ uri: video.thumbnailUrl }} style={styles.image} /> | ||
</View> | ||
))} | ||
</View> | ||
</View> | ||
))} | ||
</View> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
image: { | ||
height: 180, | ||
width: 200, | ||
}, | ||
}); | ||
export default VideoDataService; |
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,71 @@ | ||
import VideoService from "./videoServices"; | ||
|
||
describe("VideoService", () => { | ||
it("returns a list of unique category label names from testData.json", () => { | ||
const videoService = new VideoService(); | ||
|
||
const categoryLabels = videoService.getVideoCategoryLabels(); | ||
expect(categoryLabels).toBeInstanceOf(Array); | ||
expect(categoryLabels.length).toBe(5); | ||
expect(categoryLabels).toContain("Gaming"); | ||
expect(categoryLabels).toContain("Entertainment"); | ||
expect(categoryLabels).toContain("Unknown"); | ||
expect(categoryLabels).toContain("Art"); | ||
expect(categoryLabels).toContain("Education"); | ||
}); | ||
|
||
it("returns a list with the correct number of videos from testData.json, for each label", () => { | ||
const videoService = new VideoService(); | ||
|
||
const gamingVideos = videoService.getVideosForCategory("Gaming"); | ||
expect(gamingVideos).toBeInstanceOf(Array); | ||
expect(gamingVideos.length).toBe(6); | ||
|
||
const entertainmentVideos = videoService.getVideosForCategory("Entertainment"); | ||
expect(entertainmentVideos).toBeInstanceOf(Array); | ||
expect(entertainmentVideos.length).toBe(1); | ||
|
||
const unknownVideos = videoService.getVideosForCategory("Unknown"); | ||
expect(unknownVideos).toBeInstanceOf(Array); | ||
expect(unknownVideos.length).toBe(6); | ||
|
||
const artVideos = videoService.getVideosForCategory("Art"); | ||
expect(artVideos).toBeInstanceOf(Array); | ||
expect(artVideos.length).toBe(1); | ||
|
||
const educationVideos = videoService.getVideosForCategory("Education"); | ||
expect(educationVideos).toBeInstanceOf(Array); | ||
expect(educationVideos.length).toBe(1); | ||
|
||
const undefinedLabelVideos = videoService.getVideosForCategory("Undefined, just made up from nowhere!"); | ||
expect(undefinedLabelVideos).toBeInstanceOf(Array); | ||
expect(undefinedLabelVideos.length).toBe(0); | ||
}); | ||
|
||
it("returns a total 15 videos with from testData.json, all with id, name, category, description, and thumbnailPath", () => { | ||
const videoService = new VideoService(); | ||
const allVideos = []; | ||
for (const label of videoService.getVideoCategoryLabels()) { | ||
const categoryVideos = videoService.getVideosForCategory(label); | ||
allVideos.push(...categoryVideos); | ||
} | ||
|
||
expect(allVideos.length).toBe(15); | ||
|
||
for (const video of allVideos) { | ||
expect(Number.isInteger(video.id)).toBe(true); | ||
expect(typeof video.name).toBe("string"); | ||
if (video.category.id) { | ||
expect(video.category).toMatchObject({ id: expect.any(Number), label: expect.any(String) }); | ||
} else { | ||
expect(video.category).toMatchObject({ id: null, label: expect.any(String) }); | ||
} | ||
if (video.description) { | ||
expect(typeof video.description).toBe("string"); | ||
} else { | ||
expect(video.description).toBeNull(); | ||
} | ||
expect(typeof video.thumbnailPath).toBe("string"); | ||
} | ||
}); | ||
}); |
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,38 @@ | ||
import * as testData from "../testData.json"; | ||
import { Video, Category } from "../types"; | ||
|
||
class VideoService { | ||
private videos: Video[] = []; | ||
private categories: Category[] = []; | ||
private readonly baseThumbnailUrl = "https://peertube2.cpy.re"; | ||
|
||
constructor() { | ||
this.loadVideosFromJson(); | ||
} | ||
|
||
public getVideoCategoryLabels(): string[] { | ||
return this.categories.map(({ label }) => label); | ||
} | ||
|
||
public completeThumbnailUrls(): Video[] { | ||
return this.videos.map((video) => ({ | ||
...video, | ||
thumbnailUrl: `${this.baseThumbnailUrl}${video.thumbnailPath}`, | ||
})); | ||
} | ||
|
||
public getVideosForCategory(categoryLabel: string): Video[] { | ||
return this.videos.filter((video) => video.category.label === categoryLabel); | ||
} | ||
|
||
public loadVideosFromJson(): void { | ||
const data = testData; | ||
this.videos = data.data; | ||
const uniqueCategories: Category[] = Array.from(new Set(this.videos.map((video) => video.category.label))).map( | ||
(label, index) => ({ id: index + 1, label }), | ||
); | ||
this.categories = uniqueCategories; | ||
} | ||
} | ||
|
||
export default VideoService; |
Oops, something went wrong.