post.test.ts•5.59 kB
import { jest, /*expect,*/ describe, it, beforeEach } from '@jest/globals';
import type { Mock } from 'jest-mock';
import { ProjectsClient } from '../../../client/projects.js';
// import { mockResponse, mockErrorResponse } from '../../helpers/mocks.js'; // Unused
// import * as fixtures from '../../helpers/fixtures.js'; // Unused
// import config from '../../../config.js'; // Unused
// import { RedmineApiError } from '../../../client/base.js'; // Unused
// import { RedmineProjectCreate } from '../../../types/index.js'; // Unused
// import { parseUrl } from '../../helpers/url.js'; // Unused
describe("Projects API (POST)", () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let client: ProjectsClient; // client is assigned but never used in the current skipped test
let mockFetch: Mock;
beforeEach(() => {
client = new ProjectsClient(); // Assigning client here for consistency, though not used in skipped test.
mockFetch = jest.spyOn(global, "fetch") as Mock;
mockFetch.mockReset();
});
describe("POST /projects.json (createProject)", () => {
// POST操作のテストは安全のためスキップ
it.skip("all POST operation tests are skipped for safety", () => {
// POST操作のテストは、実際のAPIへの影響を避けるため、通常はモックサーバーを使用するか、
// または特定のテスト環境でのみ実行するように制御します。
// Redmine APIの仕様では、POSTリクエストは成功すると201 Createdを返し、作成されたリソースをボディに含みます。
//
// 必須フィールド:
// - name: プロジェクト名
// - identifier: プロジェクト識別子(例: "my-project", "project123"など。小文字英数字とダッシュ、アンダースコア)
//
// オプションフィールド:
// - description: プロジェクトの説明
// - homepage: ホームページのURL
// - is_public: 公開/非公開プロジェクト (true/false)
// - parent_id: 親プロジェクトID
// - inherit_members: メンバーの継承 (true/false)
// - default_assigned_to_id: デフォルトの担当者ID
// - 親プロジェクトのメンバーである必要がある
// - default_version_id: デフォルトのバージョンID
// - 指定のプロジェクトのバージョンである必要がある
// - tracker_ids: トラッカーのID配列
// - enabled_module_names: 有効モジュール名配列
// - 有効な値: boards, calendar, documents, files, gantt,
// issue_tracking, news, repository, time_tracking, wiki
// - issue_custom_field_ids: カスタムフィールドID配列
// - custom_field_values: カスタムフィールド値 (id => value)
//
// 作成処理の検証ポイント:
// - プロジェクトが正しく作成され、期待されるレスポンスが返されるか
// - メンバーシップが正しく設定されるか(inherit_membersがtrueの場合など)
// - カスタムフィールドが正しく設定されるか
// - 必須フィールドの欠如
//
// 下記にテストのスケルトンを示します。
// 実際にテストを行う場合は、これらの点を考慮したモック戦略とアサーションが必要です。
//
// また、Redmineの設定によってはプロジェクト作成に管理者権限が必要な場合があるので注意。
});
});
});
// Example of how a test might look if it were enabled:
/*
import { RedmineProjectCreate } from '../../../types/index.js';
import { mockResponse, mockErrorResponse } from '../../helpers/mocks.js';
import * as fixtures from '../../helpers/fixtures.js';
import config from '../../../config.js';
import { RedmineApiError } from '../../../client/base.js';
it("creates a project successfully", async () => {
// Arrange
const projectData: RedmineProjectCreate = {
name: "New Test Project",
identifier: "new-test-project-ts-client",
description: "This is a test project created via the TypeScript client.",
is_public: true,
tracker_ids: [1, 2] // Example tracker IDs
};
const expectedResponse = { project: { ...fixtures.singleProjectResponse.project, ...projectData, id: 999 } }; // Mocked response
mockFetch.mockImplementationOnce(() =>
Promise.resolve(mockResponse(expectedResponse, 201))
);
// Act
const result = await client.createProject(projectData);
// Assert
expect(mockFetch).toHaveBeenCalledWith(
`${config.redmineUrl}/projects.json`,
expect.objectContaining({
method: "POST",
headers: expect.objectContaining({
"X-Redmine-API-Key": config.apiKey,
"Content-Type": "application/json",
}),
body: JSON.stringify({ project: projectData }),
})
);
expect(result).toEqual(expectedResponse);
});
it("handles validation error when creating a project with missing identifier", async () => {
// Arrange
const projectData: Partial<RedmineProjectCreate> = { // Using Partial to simulate missing required fields
name: "Project Without Identifier"
};
// Simulate a 422 Unprocessable Entity response with error messages
mockFetch.mockImplementationOnce(() =>
Promise.resolve(mockErrorResponse(422, ["Identifier cannot be blank"]))
);
// Act & Assert
await expect(client.createProject(projectData as RedmineProjectCreate)).rejects.toThrow(RedmineApiError);
});
*/