|
1 | | -// Doctor state migration tests cover legacy state moves, archive markers, and repair behavior. |
2 | 1 | import fs from "node:fs"; |
3 | 2 | import os from "node:os"; |
4 | 3 | import path from "node:path"; |
@@ -1511,18 +1510,35 @@ describe("doctor legacy state migrations", () => { |
1511 | 1510 | current: InstalledPluginInstallRecordInfo; |
1512 | 1511 | legacy: InstalledPluginInstallRecordInfo; |
1513 | 1512 | }>) { |
1514 | | - it(`keeps legacy plugin install index when same-version npm records ${fixture.label}`, async () => { |
| 1513 | + it(`archives legacy plugin install index and warns (once) when same-version npm records ${fixture.label}`, async () => { |
1515 | 1514 | const root = await makeTempRoot(); |
1516 | 1515 | await writeExistingPluginInstallIndex(root, { demo: fixture.current }); |
1517 | 1516 | const sourcePath = writeLegacyPluginInstallIndex(root, { demo: fixture.legacy }); |
1518 | 1517 |
|
1519 | 1518 | const result = await runLegacyStateMigrationsForRoot(root); |
1520 | 1519 |
|
| 1520 | + // The conflict warning is emitted once, then the legacy file is archived so it |
| 1521 | + // cannot trigger the same warning on subsequent gateway startups (fixes #90213). |
1521 | 1522 | expect(result.warnings).toStrictEqual([ |
1522 | | - "Left plugin install index in place because shared SQLite state has conflicting plugin install metadata for: demo", |
| 1523 | + "Archived plugin install index after detecting conflicting plugin install metadata for: demo", |
1523 | 1524 | ]); |
1524 | | - expect(fs.existsSync(sourcePath)).toBe(true); |
1525 | | - expect(fs.existsSync(`${sourcePath}.migrated`)).toBe(false); |
| 1525 | + expect(fs.existsSync(sourcePath)).toBe(false); |
| 1526 | + expect(fs.existsSync(`${sourcePath}.migrated`)).toBe(true); |
| 1527 | + }); |
| 1528 | + |
| 1529 | + it(`does not re-emit plugin install conflict warning on subsequent runs when ${fixture.label}`, async () => { |
| 1530 | + const root = await makeTempRoot(); |
| 1531 | + await writeExistingPluginInstallIndex(root, { demo: fixture.current }); |
| 1532 | + const sourcePath = writeLegacyPluginInstallIndex(root, { demo: fixture.legacy }); |
| 1533 | + |
| 1534 | + // First run: archives the legacy file and emits the warning once. |
| 1535 | + const first = await runLegacyStateMigrationsForRoot(root); |
| 1536 | + expect(first.warnings).toHaveLength(1); |
| 1537 | + expect(fs.existsSync(sourcePath)).toBe(false); |
| 1538 | + |
| 1539 | + // Second run: no legacy file exists, so migration is skipped entirely — no repeated warning. |
| 1540 | + const second = await runLegacyStateMigrationsForRoot(root); |
| 1541 | + expect(second.warnings).toHaveLength(0); |
1526 | 1542 | }); |
1527 | 1543 | } |
1528 | 1544 |
|
|
0 commit comments