ソース情報
- リポジトリ
- dev-hann/song
- ソースの最終更新活動
- 2026年2月18日 13:08
- 検出された SKILL.md の言語
- 英語
- スター
- 0
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/dev-hann/song --skill youtube-mockingコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Runs PM-Designer-Doc triple review protocol to reach consensus on feature specs before implementation. Includes domain documentation consistency check. Use before implementing any new screen, component, or significant feature.
Create Server and Client React components with proper props, state, and patterns
Enforce docs ↔ code consistency before and after implementation. Launches doc-reviewer agent to cross-check domain documentation against actual codebase, detects drift, and ensures documentation updates accompany code changes.
SOC 職業分類に基づく
SKILL.md を表示中
| name | youtube-mocking |
| description | Mock YouTube.js API calls for isolated testing |
| license | MIT |
| compatibility | opencode |
| metadata | {"category":"testing","complexity":"intermediate"} |
Use this when you need to:
I'll ask clarifying questions if:
import { describe, it, expect, vi, beforeEach } from 'vitest';
vi.mock('youtubei.js', () => ({
Innertube: {
create: vi.fn(),
},
}));
describe('YouTube.js Mocking', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should mock Innertube.create', async () => {
const mockInnertube = { session: {} };
const { Innertube } = await import('youtubei.js');
vi.mocked(Innertube.create).mockResolvedValue(mockInnertube as any);
const result = await Innertube.create();
expect(result).toBe(mockInnertube);
expect(Innertube.create).toHaveBeenCalledWith({
generate_session_locally: true,
enable_session_cache: false,
lang: 'ko',
location: 'KR',
});
});
});
vi.mock('@/lib/youtube', () => ({
getInnertube: vi.fn(),
}));
describe('getInnertube', () => {
it('should return mocked Innertube instance', async () => {
const mockInnertube = {
search: vi.fn(),
getBasicInfo: vi.fn(),
getChannel: vi.fn(),
getPlaylist: vi.fn(),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const result = await getInnertube();
expect(result).toBe(mockInnertube);
});
});
it('should mock search results', async () => {
const mockInnertube = {
search: vi.fn().mockResolvedValue({
results: [
{
id: 'video123',
type: 'video',
title: 'Test Video',
thumbnail: 'https://example.com/thumb.jpg',
channel: { name: 'Test Channel' },
},
],
has_continuation: false,
}),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const results = await innertube.search('test query');
expect(results.results).toHaveLength(1);
expect(results.results[0].title).toBe('Test Video');
});
it('should mock video info', async () => {
const mockInnertube = {
getBasicInfo: vi.fn().mockResolvedValue({
basic_info: {
id: 'video123',
title: 'Test Video',
short_description: 'Test Description',
duration: { seconds: 120 },
view_count: 5000,
upload_date: '2024-01-01',
thumbnail: [{ url: 'https://example.com/thumb.jpg' }],
channel_id: 'channel123',
channel: {
name: 'Test Channel',
thumbnails: [{ url: 'https://example.com/channel.jpg' }],
},
},
}),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const info = await innertube.getBasicInfo('video123');
expect(info.basic_info.).();
(info...).();
});
it('should mock channel info', async () => {
const mockInnertube = {
getChannel: vi.fn().mockResolvedValue({
metadata: {
title: 'Test Channel',
description: 'Test Description',
thumbnail: [{ url: 'https://example.com/channel.jpg' }],
},
videos: [
{
id: 'video123',
title: 'Test Video',
duration: { seconds: 120 },
view_count: 5000,
thumbnails: [{ url: 'https://example.com/thumb.jpg' }],
upload_date: '2024-01-01',
},
],
}),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const channel = await innertube.getChannel('channel123');
expect(channel.metadata.title).();
(channel.).();
});
it('should mock playlist info', async () => {
const mockInnertube = {
getPlaylist: vi.fn().mockResolvedValue({
info: {
title: 'Test Playlist',
description: 'Test Description',
thumbnails: [{ url: 'https://example.com/playlist.jpg' }],
total_items: 10,
author: {
name: 'Test Channel',
},
},
items: [
{
id: 'video123',
title: 'Test Video',
duration: { seconds: 120 },
thumbnails: [{ url: 'https://example.com/thumb.jpg' }],
index: 1,
},
],
}),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const playlist = await innertube.getPlaylist('playlist123');
(playlist..).();
(playlist..).();
});
it('should mock home feed', async () => {
const mockInnertube = {
getHomeFeed: vi.fn().mockResolvedValue([
{
id: 'video123',
type: 'video',
title: 'Test Video',
thumbnail: 'https://example.com/thumb.jpg',
channel: { name: 'Test Channel' },
},
]),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const feed = await innertube.getHomeFeed();
expect(feed).toHaveLength(1);
});
it('should mock API error', async () => {
const mockInnertube = {
search: vi.fn().mockRejectedValue(new Error('API Error')),
};
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
await expect(innertube.search('test query')).rejects.toThrow('API Error');
});
// tests/mocks/youtube-helpers.ts
export function createMockVideo(overrides = {}) {
return {
id: 'video123',
type: 'video',
title: 'Test Video',
description: 'Test Description',
duration: 120,
viewCount: 5000,
thumbnail: 'https://example.com/thumb.jpg',
channel: {
id: 'channel123',
name: 'Test Channel',
thumbnail: 'https://example.com/channel.jpg',
},
...overrides,
};
}
export function createMockChannel(overrides = {}) {
return {
id: 'channel123',
type: 'channel',
name: 'Test Channel',
subscribers: 1000,
thumbnail: 'https://example.com/channel.jpg',
...overrides,
};
}
export function createMockPlaylist(overrides = {}) {
return {
id: 'playlist123',
type: 'playlist',
: ,
: ,
: ,
: {
: ,
},
...overrides,
};
}
() {
{
: vi.(),
: vi.(),
: vi.(),
: vi.(),
: vi.(),
: vi.(),
: vi.(),
};
}
import { createMockVideo, createMockInnertube } from '@/tests/mocks/youtube-helpers';
it('should use mock helpers', async () => {
const mockInnertube = createMockInnertube();
mockInnertube.search.mockResolvedValue({
results: [createMockVideo()],
has_continuation: false,
});
const { getInnertube } = await import('@/lib/youtube');
vi.mocked(getInnertube).mockResolvedValue(mockInnertube as any);
const innertube = await getInnertube();
const results = await innertube.search('test query');
expect(results.results).toHaveLength(1);
expect(results.results[0].id).toBe('video123');
});
| Method | Description |
|---|---|
Innertube.create() | Create Innertube instance |
innertube.search() | Search for videos |
innertube.getBasicInfo() | Get video info |
innertube.getChannel() | Get channel info |
innertube.getPlaylist() | Get playlist info |
innertube.getHomeFeed() | Get home feed |
innertube.getTrending() | Get trending videos |
innertube.getSubscriptionsFeed() | Get subscriptions feed |
Related SKILLS: api-testing.md, testing-infrastructure.md, hook-testing.md