Update Harbor client and gateway functionality
This commit is contained in:
@@ -61,7 +61,7 @@ test('schema v2 state migrates built-in .ru into a normal enabled rule', (t) =>
|
||||
|
||||
assert.equal(migrated.schemaVersion, STATE_SCHEMA_VERSION);
|
||||
assert.deepEqual(migrated.routeRules, [
|
||||
{ type: 'domain_suffix', value: 'ru', enabled: true },
|
||||
{ type: 'domain_suffix', value: 'ru', enabled: true, outbound: 'direct' },
|
||||
]);
|
||||
const primary = migrated.profiles[0];
|
||||
assert.equal(primary.label, 'Основной');
|
||||
@@ -74,6 +74,61 @@ test('schema v2 state migrates built-in .ru into a normal enabled rule', (t) =>
|
||||
assert.equal(JSON.parse(fs.readFileSync(filePath, 'utf8')).schemaVersion, STATE_SCHEMA_VERSION);
|
||||
});
|
||||
|
||||
test('schema v5 migrates saved and applied rules to v6 with an exact backup', (t) => {
|
||||
const filePath = fixture(t);
|
||||
const legacy = {
|
||||
schemaVersion: 5,
|
||||
revision: 11,
|
||||
routeRulesRevision: 7,
|
||||
routeRules: [
|
||||
{ type: 'domain', value: 'api.example.com', enabled: true },
|
||||
{ type: 'domain_suffix', value: 'example.com', enabled: false },
|
||||
],
|
||||
appliedRouteRules: [
|
||||
{ type: 'domain_suffix', value: 'example.com', enabled: false },
|
||||
{ type: 'domain', value: 'api.example.com', enabled: true },
|
||||
],
|
||||
};
|
||||
const bytes = JSON.stringify(legacy);
|
||||
fs.writeFileSync(filePath, bytes);
|
||||
|
||||
const store = createStateStore(filePath, {
|
||||
now: () => new Date('2026-08-17T12:00:00.000Z'),
|
||||
});
|
||||
const migrated = store.read();
|
||||
|
||||
assert.equal(migrated.schemaVersion, 6);
|
||||
assert.equal(migrated.routeRulesRevision, 7);
|
||||
assert.deepEqual(migrated.routeRules.map(({ outbound }) => outbound), ['direct', 'direct']);
|
||||
assert.deepEqual(migrated.appliedRouteRules.map(({ type, outbound }) => [type, outbound]), [
|
||||
['domain_suffix', 'direct'],
|
||||
['domain', 'direct'],
|
||||
]);
|
||||
assert.equal(store.migration.fromVersion, 5);
|
||||
assert.equal(store.migration.toVersion, 6);
|
||||
assert.match(store.migration.backupPath, /\.backup-v5-/);
|
||||
assert.equal(fs.readFileSync(store.migration.backupPath, 'utf8'), bytes);
|
||||
});
|
||||
|
||||
test('schema v6 rejects missing or unknown outbound without rewriting source bytes', (t) => {
|
||||
for (const [name, rule] of [
|
||||
['missing', { type: 'domain', value: 'example.com', enabled: true }],
|
||||
['unknown', { type: 'domain', value: 'example.com', enabled: true, outbound: 'block' }],
|
||||
]) {
|
||||
const filePath = `${fixture(t)}-${name}`;
|
||||
const bytes = JSON.stringify({
|
||||
schemaVersion: 6,
|
||||
routeRules: [rule],
|
||||
appliedRouteRules: [],
|
||||
});
|
||||
fs.writeFileSync(filePath, bytes);
|
||||
const store = createStateStore(filePath);
|
||||
assert.throws(() => store.read(), /outbound/);
|
||||
assert.equal(fs.readFileSync(filePath, 'utf8'), bytes);
|
||||
assert.equal(store.migration, null);
|
||||
}
|
||||
});
|
||||
|
||||
test('ambiguous legacy selectedTag explicitly requires a new choice', (t) => {
|
||||
const filePath = fixture(t);
|
||||
fs.writeFileSync(filePath, JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user