ken_nogi/NodeSrv/apps/app-portal/test/dokployClient.test.js
Kenichiro NOGI ce58cb4be4 初回コミット: dev配下(NodeSrv/Pleasanter等)をGitea管理下に統合
GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。
NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは
別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter
インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 15:37:06 +09:00

165 lines
6.2 KiB
JavaScript

const { test } = require('node:test');
const assert = require('node:assert');
function withMockFetch(mockFetch, fn) {
const original = global.fetch;
global.fetch = mockFetch;
return fn().finally(() => {
global.fetch = original;
});
}
test('trpcGet wraps params in {json:} and unwraps result.data.json', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { trpcGet } = require('../src/dokployClient');
await withMockFetch(async (url, options) => {
const parsed = new URL(url);
assert.strictEqual(parsed.pathname, '/api/trpc/environment.one');
const input = JSON.parse(parsed.searchParams.get('input'));
assert.deepStrictEqual(input, { json: { environmentId: 'env-1' } });
assert.strictEqual(options.headers['x-api-key'], 'test-key');
return {
ok: true,
json: async () => ({ result: { data: { json: { hello: 'world' } } } }),
};
}, async () => {
const result = await trpcGet('environment.one', { environmentId: 'env-1' });
assert.deepStrictEqual(result, { hello: 'world' });
});
});
test('trpcPost wraps data in {json:} in the request body', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { trpcPost } = require('../src/dokployClient');
await withMockFetch(async (url, options) => {
const parsed = new URL(url);
assert.strictEqual(parsed.pathname, '/api/trpc/compose.start');
assert.deepStrictEqual(JSON.parse(options.body), { json: { composeId: 'c1' } });
assert.strictEqual(options.method, 'POST');
return {
ok: true,
json: async () => ({ result: { data: { json: { success: true } } } }),
};
}, async () => {
const result = await trpcPost('compose.start', { composeId: 'c1' });
assert.deepStrictEqual(result, { success: true });
});
});
test('trpcGet throws when the response is not ok', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { trpcGet } = require('../src/dokployClient');
await withMockFetch(async () => ({ ok: false, status: 400 }), async () => {
await assert.rejects(() => trpcGet('compose.one', { composeId: 'c1' }), /400/);
});
});
test('listComposes returns the compose array from environment.one', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { listComposes } = require('../src/dokployClient');
await withMockFetch(async () => ({
ok: true,
json: async () => ({
result: { data: { json: { compose: [{ composeId: 'c1', name: 'auth-redirect', composeStatus: 'done' }] } } },
}),
}), async () => {
const composes = await listComposes('env-1');
assert.deepStrictEqual(composes, [{ composeId: 'c1', name: 'auth-redirect', composeStatus: 'done' }]);
});
});
test('getComposeEnv only returns env and appName, never leaks gitea/github credentials', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { getComposeEnv } = require('../src/dokployClient');
await withMockFetch(async () => ({
ok: true,
json: async () => ({
result: {
data: {
json: {
composeId: 'c1',
appName: 'auth-redirect-uzt5hx',
env: 'PORTAL_APP_TYPE=web\nPORTAL_APP_URL=https://x.apps.next-hd.net',
gitea: { clientSecret: 'SHOULD_NOT_LEAK', accessToken: 'SHOULD_NOT_LEAK_EITHER' },
deployments: [{ title: 'irrelevant' }],
},
},
},
}),
}), async () => {
const result = await getComposeEnv('c1');
assert.deepStrictEqual(Object.keys(result).sort(), ['appName', 'env']);
assert.strictEqual(result.appName, 'auth-redirect-uzt5hx');
assert.ok(result.env.includes('PORTAL_APP_TYPE=web'));
assert.ok(!JSON.stringify(result).includes('SHOULD_NOT_LEAK'));
});
});
test('getContainers calls docker.getContainersByAppNameMatch with appType docker-compose', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { getContainers } = require('../src/dokployClient');
await withMockFetch(async (url) => {
const parsed = new URL(url);
assert.strictEqual(parsed.pathname, '/api/trpc/docker.getContainersByAppNameMatch');
const input = JSON.parse(parsed.searchParams.get('input'));
assert.deepStrictEqual(input, { json: { appName: 'auth-redirect-uzt5hx', appType: 'docker-compose' } });
return {
ok: true,
json: async () => ({ result: { data: { json: [{ containerId: 'abc123', state: 'running' }] } } }),
};
}, async () => {
const containers = await getContainers('auth-redirect-uzt5hx');
assert.deepStrictEqual(containers, [{ containerId: 'abc123', state: 'running' }]);
});
});
test('readLogs passes composeId, containerId and tail through', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { readLogs } = require('../src/dokployClient');
await withMockFetch(async (url) => {
const parsed = new URL(url);
const input = JSON.parse(parsed.searchParams.get('input'));
assert.deepStrictEqual(input, { json: { composeId: 'c1', containerId: 'abc123', tail: 200 } });
return { ok: true, json: async () => ({ result: { data: { json: 'log line\n' } } }) };
}, async () => {
const logs = await readLogs('c1', 'abc123', 200);
assert.strictEqual(logs, 'log line\n');
});
});
test('startCompose/stopCompose/restartContainer POST to the right endpoints', async () => {
process.env.DOKPLOY_URL = 'https://dokploy.test';
process.env.DOKPLOY_API_KEY = 'test-key';
const { startCompose, stopCompose, restartContainer } = require('../src/dokployClient');
const calledEndpoints = [];
await withMockFetch(async (url) => {
calledEndpoints.push(new URL(url).pathname);
return { ok: true, json: async () => ({ result: { data: { json: { success: true } } } }) };
}, async () => {
await startCompose('c1');
await stopCompose('c1');
await restartContainer('abc123');
});
assert.deepStrictEqual(calledEndpoints, [
'/api/trpc/compose.start',
'/api/trpc/compose.stop',
'/api/trpc/docker.restartContainer',
]);
});