added testing framework vitest and docs in a readme.md

main
jeremy 2024-10-07 21:07:59 -05:00
parent d3634f3e35
commit 423166adc8
7 changed files with 433 additions and 1391 deletions

View File

@ -1,3 +1,52 @@
# youtube-api # YouTube API Interface
This is a simple app for a code challenge to interface with the YouTube API. A simple app for interacting with the YouTube API.
## Description
This project provides a basic interface for searching and displaying YouTube videos. It uses the YouTube API to fetch video data and displays the results in a grid.
## Tools used
- vite with the vanilla js template
- lit
## Features
- Search for videos by keyword
- Sort search results by relevance, date, or rating
- Display video thumbnails, titles, and descriptions
- Link to YouTube video pages
- Pagination for large result sets
## Dependencies
This project uses the following dependencies:
- `axios` for making API requests
- `dotenv` for environment variable management
- `lit` for building the UI component
- `twind` for styling
## Setup
1. Clone the repository: `git clone https://gitea.jeremyhayes.me/Cybernomad/youtube-api.git`
2. Install dependencies: `npm install` or if you prefer `npm i`
3. Create a `.env` file with your YouTube API key: `API_KEY=YOUR_API_KEY_HERE`
4. Start the development server: `npm run dev`
## Usage
1. Open the app in your browser: `http://localhost:5173`
2. Enter a search keyword in the input field
3. Select a sort option from the dropdown menu
4. Click the "Search" button to fetch video data
5. Browse the search results and click on a video to open its YouTube page
## Contributing
Contributions are welcome! If you'd like to report an issue or submit a pull request, please use the GitHub issue tracker.
## License
This project is licensed under the MIT License. See the `LICENSE` file for details.

1690
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview" "preview": "vite preview",
"test": "vitest"
}, },
"dependencies": { "dependencies": {
"@twind/core": "^1.1.3", "@twind/core": "^1.1.3",
@ -16,9 +17,7 @@
"twind": "^0.16.19" "twind": "^0.16.19"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.20", "vite": "^5.4.8",
"postcss": "^8.4.47", "vitest": "^2.1.2"
"tailwindcss": "^3.4.13",
"vite": "^5.4.8"
} }
} }

10
test/MainApp.test.js Normal file
View File

@ -0,0 +1,10 @@
import { describe, expect, test } from 'vitest';
import { render } from '@testing-library/dom';
import { MainApp } from '../src/MainApp';
describe('MainApp', () => {
test('renders the YoutubeDataGrid component', async () => {
const { container } = render(<MainApp />);
expect(container.querySelector('youtube-data-grid')).toBeInTheDocument();
});
});

View File

@ -0,0 +1,30 @@
import { describe, expect, test } from 'vitest';
import { render } from '@testing-library/dom';
import { YoutubeDataGrid } from '../../src/components/YoutubeDataGrid';
describe('YoutubeDataGrid', () => {
test('renders the search input field', async () => {
const { container } = render(<YoutubeDataGrid />);
expect(container.querySelector('input[type="text"]')).toBeInTheDocument();
});
test('renders the select dropdown', async () => {
const { container } = render(<YoutubeDataGrid />);
expect(container.querySelector('select')).toBeInTheDocument();
});
test('renders the search button', async () => {
const { container } = render(<YoutubeDataGrid />);
expect(container.querySelector('button')).toBeInTheDocument();
});
test('renders the video cards', async () => {
const { container } = render(<YoutubeDataGrid />);
expect(container.querySelectorAll('.video-card')).toHaveLength(1);
});
test('renders the pagination component', async () => {
const { container } = render(<YoutubeDataGrid />);
expect(container.querySelector('pagination-component')).toBeInTheDocument();
});
});

View File

@ -0,0 +1,20 @@
import { describe, expect, test } from 'vitest';
import { render } from '@testing-library/dom';
import { PaginationComponent } from '../../../src/components/ui/PaginationComponent';
describe('PaginationComponent', () => {
test('renders the page numbers', async () => {
const { container } = render(<PaginationComponent />);
expect(container.querySelectorAll('.page-number')).toHaveLength(1);
});
test('renders the next button', async () => {
const { container } = render(<PaginationComponent />);
expect(container.querySelector('.next-button')).toBeInTheDocument();
});
test('renders the previous button', async () => {
const { container } = render(<PaginationComponent />);
expect(container.querySelector('.previous-button')).toBeInTheDocument();
});
});

View File

@ -0,0 +1,12 @@
import { describe, expect, test } from 'vitest';
import { YoutubeService } from '../../src/utils/YoutubeService';
describe('YoutubeService', () => {
test('searchVideos returns a promise that resolves with an object', async () => {
const service = YoutubeService;
const result = await service.searchVideos('query', 'relevance', 10, 1);
expect(result).toBeInstanceOf(Object);
expect(result).toHaveProperty('videos');
expect(result).toHaveProperty('totalResults');
});
});