import { describe, it, expect } from 'vitest';
import { createTestHarness } from './utils/testHarness.js';
import { setupMockApi, MOCK_BLOG_ID } from './utils/mockApi.js';
/**
* 記事CRUD操作のシナリオテスト
* ログイン → 記事作成 → 更新 → 公開 → 削除 のフロー全体をテスト
*/
describe('記事管理シナリオ統合テスト', () => {
setupMockApi();
describe('完全なCRUDフロー', () => {
it('ログイン → 記事作成 → 取得 → 更新 → 公開 → 削除の一連の流れが正常に動作する', async () => {
const harness = await createTestHarness();
try {
// 1. ログイン
const loginResult = await harness.client.callTool({
name: 'verge_login',
arguments: {
email: 'test@example.com',
password: 'password123',
},
});
expect(loginResult.isError).toBeFalsy();
// 2. 記事作成 (下書き)
const createResult = await harness.client.callTool({
name: 'verge_create_article',
arguments: {
blog_id: MOCK_BLOG_ID,
title: 'テスト記事',
content: 'これはテスト記事の本文です。',
slug: 'test-article',
status: 'draft',
},
});
expect(createResult.isError).toBeFalsy();
const createResponse = JSON.parse((createResult.content[0] as any).text);
expect(createResponse.success).toBe(true);
expect(createResponse.article).toHaveProperty('id');
expect(createResponse.article.title).toBe('テスト記事');
expect(createResponse.article.status).toBe('draft');
expect(createResponse.article.published_at).toBeNull();
const articleId = createResponse.article.id;
// 3. 記事取得
const getResult = await harness.client.callTool({
name: 'verge_get_article',
arguments: {
article_id: articleId,
blog_id: MOCK_BLOG_ID,
},
});
expect(getResult.isError).toBeFalsy();
const getResponse = JSON.parse((getResult.content[0] as any).text);
expect(getResponse.success).toBe(true);
expect(getResponse.article.id).toBe(articleId);
expect(getResponse.article.title).toBe('テスト記事');
// 4. 記事更新
const updateResult = await harness.client.callTool({
name: 'verge_update_article',
arguments: {
article_id: articleId,
blog_id: MOCK_BLOG_ID,
title: 'テスト記事 (更新版)',
content: 'これは更新されたテスト記事の本文です。',
},
});
expect(updateResult.isError).toBeFalsy();
const updateResponse = JSON.parse((updateResult.content[0] as any).text);
expect(updateResponse.success).toBe(true);
expect(updateResponse.article.title).toBe('テスト記事 (更新版)');
expect(updateResponse.article.content).toBe(
'これは更新されたテスト記事の本文です。'
);
// 5. 記事公開
const publishResult = await harness.client.callTool({
name: 'verge_publish_article',
arguments: {
article_id: articleId,
blog_id: MOCK_BLOG_ID,
},
});
expect(publishResult.isError).toBeFalsy();
const publishResponse = JSON.parse((publishResult.content[0] as any).text);
expect(publishResponse.success).toBe(true);
expect(publishResponse.article.status).toBe('published');
expect(publishResponse.article.published_at).toBeTruthy();
// 6. 記事削除
const deleteResult = await harness.client.callTool({
name: 'verge_delete_article',
arguments: {
article_id: articleId,
blog_id: MOCK_BLOG_ID,
},
});
expect(deleteResult.isError).toBeFalsy();
const deleteResponse = JSON.parse((deleteResult.content[0] as any).text);
expect(deleteResponse.success).toBe(true);
// 7. 削除後に取得を試みるとエラーになることを確認
const getAfterDeleteResult = await harness.client.callTool({
name: 'verge_get_article',
arguments: {
article_id: articleId,
blog_id: MOCK_BLOG_ID,
},
});
expect(getAfterDeleteResult.isError).toBe(true);
const errorResponse = JSON.parse(
(getAfterDeleteResult.content[0] as any).text
);
expect(errorResponse.success).toBe(false);
expect(errorResponse.error).toContain('Article not found');
} finally {
await harness.close();
}
});
it('複数の記事を作成して一覧取得できる', async () => {
const harness = await createTestHarness();
try {
// ログイン
await harness.client.callTool({
name: 'verge_login',
arguments: {
email: 'test@example.com',
password: 'password123',
},
});
// 記事1: 下書き
await harness.client.callTool({
name: 'verge_create_article',
arguments: {
blog_id: MOCK_BLOG_ID,
title: '下書き記事',
content: '下書き中です。',
slug: 'draft-article',
status: 'draft',
},
});
// 記事2: 公開済み
await harness.client.callTool({
name: 'verge_create_article',
arguments: {
blog_id: MOCK_BLOG_ID,
title: '公開記事',
content: '公開済みです。',
slug: 'published-article',
status: 'published',
},
});
// 記事3: 公開済み
await harness.client.callTool({
name: 'verge_create_article',
arguments: {
blog_id: MOCK_BLOG_ID,
title: '公開記事2',
content: '公開済みです。',
slug: 'published-article-2',
status: 'published',
},
});
// 全記事一覧取得
const listAllResult = await harness.client.callTool({
name: 'verge_list_articles',
arguments: {
blog_id: MOCK_BLOG_ID,
},
});
expect(listAllResult.isError).toBeFalsy();
const listAllResponse = JSON.parse((listAllResult.content[0] as any).text);
expect(listAllResponse.success).toBe(true);
expect(listAllResponse.articles).toHaveLength(3);
// 公開済み記事のみフィルタ
const listPublishedResult = await harness.client.callTool({
name: 'verge_list_articles',
arguments: {
blog_id: MOCK_BLOG_ID,
status: 'published',
},
});
expect(listPublishedResult.isError).toBeFalsy();
const listPublishedResponse = JSON.parse(
(listPublishedResult.content[0] as any).text
);
expect(listPublishedResponse.success).toBe(true);
expect(listPublishedResponse.articles).toHaveLength(2);
expect(
listPublishedResponse.articles.every((a: any) => a.status === 'published')
).toBe(true);
// 検索機能テスト
const searchResult = await harness.client.callTool({
name: 'verge_list_articles',
arguments: {
blog_id: MOCK_BLOG_ID,
search: '下書き',
},
});
expect(searchResult.isError).toBeFalsy();
const searchResponse = JSON.parse((searchResult.content[0] as any).text);
expect(searchResponse.success).toBe(true);
expect(searchResponse.articles).toHaveLength(1);
expect(searchResponse.articles[0].title).toBe('下書き記事');
} finally {
await harness.close();
}
});
});
describe('記事作成時の詳細フィールド', () => {
it('アイキャッチ画像と抜粋を含む記事を作成できる', async () => {
const harness = await createTestHarness();
try {
// ログイン
await harness.client.callTool({
name: 'verge_login',
arguments: {
email: 'test@example.com',
password: 'password123',
},
});
// フィールド全指定で記事作成
const createResult = await harness.client.callTool({
name: 'verge_create_article',
arguments: {
blog_id: MOCK_BLOG_ID,
title: '完全な記事',
content: '本文です。',
slug: 'complete-article',
status: 'published',
featured_image: 'https://example.com/image.jpg',
excerpt: 'これは抜粋です。',
},
});
expect(createResult.isError).toBeFalsy();
const createResponse = JSON.parse((createResult.content[0] as any).text);
expect(createResponse.success).toBe(true);
expect(createResponse.article.featured_image).toBe(
'https://example.com/image.jpg'
);
expect(createResponse.article.excerpt).toBe('これは抜粋です。');
expect(createResponse.article.status).toBe('published');
expect(createResponse.article.published_at).toBeTruthy();
} finally {
await harness.close();
}
});
});
});