mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 01:32:44 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const path = require('node:path');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
BoundedTaskListProjectionUnavailableError,
|
||||
DEFAULT_BOUNDED_TASK_LIST_LIMIT,
|
||||
InvalidBoundedTaskListProjectionError,
|
||||
MAX_BOUNDED_TASK_LIST_LIMIT,
|
||||
executeBoundedTaskListProjection,
|
||||
} = require('../dist/task-definition/projection/boundedTaskListProjection.js');
|
||||
|
||||
function task(taskId, overrides = {}) {
|
||||
return Object.freeze({
|
||||
projectId: 'prj_default',
|
||||
taskId,
|
||||
revision: 2,
|
||||
name: `Task ${taskId}`,
|
||||
description: 'must-not-cross-projection',
|
||||
kind: 'command',
|
||||
spec: Object.freeze({
|
||||
schema: 'qinglong/command@v1',
|
||||
config: Object.freeze({ command: ['private'] }),
|
||||
}),
|
||||
labels: Object.freeze({ private: 'value' }),
|
||||
enabled: true,
|
||||
mutationId: 'mutation-private',
|
||||
contentDigest: 'digest-private',
|
||||
createdAtMs: 10,
|
||||
updatedAtMs: 20,
|
||||
...overrides,
|
||||
});
|
||||
}
|
||||
|
||||
test('projects one bounded ascending current-head page and stable cursor', async () => {
|
||||
const calls = [];
|
||||
const result = await executeBoundedTaskListProjection(
|
||||
{
|
||||
async listTaskDefinitions(query) {
|
||||
calls.push(query);
|
||||
return {
|
||||
definitions: [
|
||||
task('task-a'),
|
||||
task('task-b', { enabled: false }),
|
||||
],
|
||||
truncated: true,
|
||||
next: { taskId: 'task-b' },
|
||||
};
|
||||
},
|
||||
},
|
||||
'prj_default',
|
||||
{ limit: 2 },
|
||||
);
|
||||
assert.deepEqual(calls, [{ projectId: 'prj_default', limit: 2 }]);
|
||||
assert.deepEqual(result, {
|
||||
tasks: [
|
||||
{
|
||||
taskId: 'task-a',
|
||||
revision: 2,
|
||||
name: 'Task task-a',
|
||||
kind: 'command',
|
||||
specSchema: 'qinglong/command@v1',
|
||||
enabled: true,
|
||||
updatedAtMs: 20,
|
||||
},
|
||||
{
|
||||
taskId: 'task-b',
|
||||
revision: 2,
|
||||
name: 'Task task-b',
|
||||
kind: 'command',
|
||||
specSchema: 'qinglong/command@v1',
|
||||
enabled: false,
|
||||
updatedAtMs: 20,
|
||||
},
|
||||
],
|
||||
hasMore: true,
|
||||
next: { taskId: 'task-b' },
|
||||
});
|
||||
assert.equal(JSON.stringify(result).includes('private'), false);
|
||||
});
|
||||
|
||||
test('uses default and maximum bounds and passes an exact cursor', async () => {
|
||||
const seen = [];
|
||||
const source = {
|
||||
async listTaskDefinitions(query) {
|
||||
seen.push(query);
|
||||
return { definitions: [], truncated: false };
|
||||
},
|
||||
};
|
||||
assert.deepEqual(
|
||||
await executeBoundedTaskListProjection(source, 'prj_default', {}),
|
||||
{ tasks: [], hasMore: false },
|
||||
);
|
||||
assert.deepEqual(
|
||||
await executeBoundedTaskListProjection(source, 'prj_default', {
|
||||
limit: MAX_BOUNDED_TASK_LIST_LIMIT,
|
||||
after: { taskId: 'task-a' },
|
||||
}),
|
||||
{ tasks: [], hasMore: false },
|
||||
);
|
||||
assert.deepEqual(seen, [
|
||||
{ projectId: 'prj_default', limit: DEFAULT_BOUNDED_TASK_LIST_LIMIT },
|
||||
{
|
||||
projectId: 'prj_default',
|
||||
limit: MAX_BOUNDED_TASK_LIST_LIMIT,
|
||||
after: { taskId: 'task-a' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('fails closed on malformed input before storage', async () => {
|
||||
let calls = 0;
|
||||
const source = {
|
||||
async listTaskDefinitions() {
|
||||
calls += 1;
|
||||
return { definitions: [], truncated: false };
|
||||
},
|
||||
};
|
||||
for (const input of [
|
||||
null,
|
||||
{ limit: 0 },
|
||||
{ limit: 65 },
|
||||
{ extra: true },
|
||||
{ after: null },
|
||||
{ after: { taskId: '' } },
|
||||
{ after: { taskId: 'task-a', extra: true } },
|
||||
]) {
|
||||
await assert.rejects(
|
||||
executeBoundedTaskListProjection(source, 'prj_default', input),
|
||||
InvalidBoundedTaskListProjectionError,
|
||||
);
|
||||
}
|
||||
assert.equal(calls, 0);
|
||||
});
|
||||
|
||||
test('fails closed on cross-Project, ordering, shape and continuation drift', async () => {
|
||||
for (const page of [
|
||||
{ definitions: [task('task-a', { projectId: 'prj_other' })], truncated: false },
|
||||
{ definitions: [task('task-b'), task('task-a')], truncated: false },
|
||||
{ definitions: [task('task-a'), task('task-a')], truncated: false },
|
||||
{ definitions: [task('task-a', { kind: 'invented' })], truncated: false },
|
||||
{ definitions: [task('task-a')], truncated: true },
|
||||
{
|
||||
definitions: [task('task-a')],
|
||||
truncated: true,
|
||||
next: { taskId: 'task-b' },
|
||||
},
|
||||
{ definitions: [], truncated: true, next: { taskId: 'task-a' } },
|
||||
{ definitions: [task('task-a'), task('task-b')], truncated: false },
|
||||
]) {
|
||||
await assert.rejects(
|
||||
executeBoundedTaskListProjection(
|
||||
{ async listTaskDefinitions() { return page; } },
|
||||
'prj_default',
|
||||
page.definitions.length > 1 ? { limit: 1 } : {},
|
||||
),
|
||||
BoundedTaskListProjectionUnavailableError,
|
||||
);
|
||||
}
|
||||
await assert.rejects(
|
||||
executeBoundedTaskListProjection(
|
||||
{ async listTaskDefinitions() { throw new Error('offline'); } },
|
||||
'prj_default',
|
||||
{},
|
||||
),
|
||||
BoundedTaskListProjectionUnavailableError,
|
||||
);
|
||||
});
|
||||
|
||||
test('leaf import does not load Tool Registry or SemVer', () => {
|
||||
const entry = path.resolve(
|
||||
__dirname,
|
||||
'../dist/task-definition/projection/boundedTaskListProjection.js',
|
||||
);
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'-e',
|
||||
`require(${JSON.stringify(entry)});
|
||||
const loaded = Object.keys(require.cache);
|
||||
if (loaded.some((value) => /node_modules[\\/]semver(?:[\\/]|$)/.test(value))) process.exit(2);
|
||||
if (loaded.some((value) => /tool-execution[\\/]tool-registry/.test(value))) process.exit(3);
|
||||
process.stdout.write(String(loaded.length));`,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.ok(Number(result.stdout) <= 4);
|
||||
});
|
||||
Reference in New Issue
Block a user