Files
qinglong/test/contracts/pluginPackageAutomationPublicationRepositoryContract.cjs

183 lines
5.7 KiB
JavaScript

const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
PluginPackageAutomationPublicationConflictError,
createInitialPluginPackageAutomationPublication,
createNextPluginPackageAutomationPublication,
} = require('../../packages/ql3-runtime-core/dist/plugin-package/pluginPackageAutomationPublication');
const {
pluginPackageTaskReconciliationFixture,
} = require('./pluginPackageTaskReconciliationRepositoryContract.cjs');
function automationOptions(name = 'daily') {
return {
workflows: [
{
schema: 'qinglong/plugin-package-workflow-resource@v1',
id: name,
name: `Workflow ${name}`,
enabled: true,
steps: [{ id: 'run', task: 'alpha', needs: [] }],
},
],
prompts: [
{
schema: 'qinglong/plugin-package-prompt-resource@v1',
id: `${name}-prompt`,
name: `Prompt ${name}`,
template: 'Hello {{name}}',
parameters: [{ name: 'name', required: true }],
},
],
};
}
function fixture(namespace, options = {}) {
return pluginPackageTaskReconciliationFixture(namespace, {
profile: options.profile,
previous: options.previous,
...automationOptions(options.name),
});
}
function registerPluginPackageAutomationPublicationRepositoryContract(options) {
test(`${options.name} publishes and replays one exact current head`, async (t) => {
const value = fixture(`${options.namespace}-initial`, {
profile: options.profile,
name: 'daily',
});
const harness = await options.createRepository(t, value);
t.after(() => harness.close?.());
await harness.materializedRepository.publish(value.revision);
const publication = createInitialPluginPackageAutomationPublication(
value.revision,
value.registry,
1_000,
);
const created = await harness.repository.publish(publication);
assert.equal(created.status, 'created');
assert.deepEqual(created.publication, publication);
assert.equal((await harness.repository.publish(publication)).status, 'existing');
assert.deepEqual(
await harness.repository.findByDigest(publication.publicationDigest),
publication,
);
assert.deepEqual(
await harness.repository.findCurrent(value.projectId, value.packageName),
publication,
);
});
test(`${options.name} advances generations with one CAS publication chain`, async (t) => {
const first = fixture(`${options.namespace}-upgrade`, {
profile: options.profile,
name: 'daily',
});
const harness = await options.createRepository(t, first);
t.after(() => harness.close?.());
await harness.materializedRepository.publish(first.revision);
const initial = createInitialPluginPackageAutomationPublication(
first.revision,
first.registry,
1_000,
);
await harness.repository.publish(initial);
const second = fixture(first.namespace, {
profile: options.profile,
previous: first,
name: 'hourly',
});
await harness.materializedRepository.publish(second.revision);
const next = createNextPluginPackageAutomationPublication(
second.revision,
second.registry,
initial,
1_100,
);
assert.equal((await harness.repository.publish(next)).status, 'created');
assert.deepEqual(
await harness.repository.findCurrent(first.projectId, first.packageName),
next,
);
assert.deepEqual(
await harness.repository.findByDigest(initial.publicationDigest),
initial,
);
const staleFork = createNextPluginPackageAutomationPublication(
second.revision,
second.registry,
initial,
1_101,
);
await assert.rejects(
harness.repository.publish(staleFork),
PluginPackageAutomationPublicationConflictError,
);
assert.deepEqual(
await harness.repository.findCurrent(first.projectId, first.packageName),
next,
);
});
test(`${options.name} persists absent tombstones across Package generations`, async (t) => {
const first = fixture(`${options.namespace}-tombstone`, {
profile: options.profile,
name: 'daily',
});
const harness = await options.createRepository(t, first);
t.after(() => harness.close?.());
await harness.materializedRepository.publish(first.revision);
const initial = createInitialPluginPackageAutomationPublication(
first.revision,
first.registry,
1_000,
);
await harness.repository.publish(initial);
const second = pluginPackageTaskReconciliationFixture(first.namespace, {
profile: options.profile,
previous: first,
});
await harness.materializedRepository.publish(second.revision);
const absent = createNextPluginPackageAutomationPublication(
second.revision,
second.registry,
initial,
1_100,
);
assert.equal(absent.state, 'absent');
assert.equal((await harness.repository.publish(absent)).status, 'created');
const third = fixture(first.namespace, {
profile: options.profile,
previous: second,
name: 'restored',
});
await harness.materializedRepository.publish(third.revision);
const restored = createNextPluginPackageAutomationPublication(
third.revision,
third.registry,
absent,
1_200,
);
assert.equal(restored.state, 'active');
assert.equal((await harness.repository.publish(restored)).status, 'created');
assert.deepEqual(
await harness.repository.findCurrent(first.projectId, first.packageName),
restored,
);
assert.deepEqual(
await harness.repository.findByDigest(absent.publicationDigest),
absent,
);
});
}
module.exports = {
pluginPackageAutomationPublicationFixture: fixture,
registerPluginPackageAutomationPublicationRepositoryContract,
};