Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/RELEASE-PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Workers coordinate protocol changes directly. Only the coordinator changes Git s
- Minimum-version exports with translucent diagram backgrounds also require captured page colors. Resolved background/foreground variables now apply to both the exported body and content. Contrast assertions composite actual ancestor backgrounds and pass on both supported-version test targets.
- Initial GitHub CI passed all three OS build/type/unit jobs and stable VS Code E2E. Minimum-version Linux screenshots exposed a test harness mismatch: the emulated viewport was 1,440 pixels wide but the native window was 1,024, so right-side mouse targets fell outside it. The harness now sizes the actual BrowserWindow and CI provides a 1,920-pixel display. Both corrected CI runs passed all jobs on `dd88879`.
- The final automated review identified an IME composition-completion gap and persisted CI checkout credentials. Search now schedules the committed composition value and cancels pending searches while composing; CI and release checkouts remove credentials before subsequent steps. The follow-up commit must pass its own checks before merge.
- PR #13 merged after both final CI runs passed, and its exact packaged VSIX passed rendering, HTML, PDF and IME smoke checks. The post-merge release gate then caught a stable-VS-Code PDF export still pending at the test's 30-second deadline. Trace evidence confirms the correct save path and no visible error; exporter logs were missing, so it cannot distinguish slow Chromium from a hang. PDF tests now allow 60 seconds for the two browser processes and retain isolated application logs on failure; assertions remain unchanged and automatic retries remain disabled.
- The candidate VSIX contains 19 files (about 3 MB), with manifest version 0.5.0 and bundled outputs byte-matching the production build. Sources, tests, node_modules, maps, declarations and demo GIFs are excluded.

## Research sources
Expand All @@ -67,5 +68,6 @@ Workers coordinate protocol changes directly. Only the coordinator changes Git s
- Consider a persistent preview lock and richer Markdown workspace navigation after current lifecycle behavior is tested.
- Evaluate additional export layout controls against real authoring needs after export safety and fidelity are verified.
- Consider an explicit print-friendly palette option; exports now preserve the captured preview background/foreground to keep translucent diagram backgrounds legible.
- Add an explicit wall-clock deadline and cancellation/progress for PDF browser subprocesses; Chromium's virtual-time budget does not bound real process duration.
- Consider architectural extraction from the large preview controller where it simplifies future changes; avoid a broad rewrite in this delivery.
- Evaluate publishing identity modernization when account configuration is available; keep release authentication aligned with official guidance.
4 changes: 3 additions & 1 deletion test/e2e/export.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ test('exports a PDF from a cold preview through the real command and Chromium re
const target = join(vscode.workspace, 'journey.pdf');
await saveInput.fill(target);
await saveInput.press('Enter');
const pdf = await waitForFile(target);
// PDF export starts two Chromium processes; virtual-time budgets do not bound
// their wall time on a busy CI worker. Keep a finite deadline for the real file.
const pdf = await waitForFile(target, 60_000);
expect(pdf.subarray(0, 5).toString()).toBe('%PDF-');
expect(pdf.length).toBeGreaterThan(5000);
expect(pdf.subarray(-1024).toString()).toContain('%%EOF');
Expand Down
43 changes: 40 additions & 3 deletions test/e2e/vscodeFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const test = base.extend<{ vscode: VsCodeSession }>({
const sandbox = await mkdtemp(join(tmpdir(), 'omv-e2e-'));
const workspace = join(sandbox, 'workspace');
const userData = join(sandbox, 'user-data');
const processOutput = { stdout: '', stderr: '' };
let closeApp: () => Promise<unknown> = async () => undefined;
try {
await cp(join(root, '.e2e-workspace'), workspace, {
Expand Down Expand Up @@ -103,6 +104,14 @@ export const test = base.extend<{ vscode: VsCodeSession }>({
env,
timeout: 60_000
});
for (const stream of ['stdout', 'stderr'] as const) {
app.process()[stream]?.on('data', (chunk: Buffer | string) => {
// Keep useful tail diagnostics without unbounded memory on a noisy failure.
processOutput[stream] = (
processOutput[stream] + chunk.toString()
).slice(-1_048_576);
});
}
closeApp = async () => {
const timer = setTimeout(() => app.process().kill('SIGKILL'), 5_000);
try {
Expand Down Expand Up @@ -222,15 +231,43 @@ export const test = base.extend<{ vscode: VsCodeSession }>({
try {
await closeApp();
} finally {
await rm(sandbox, { recursive: true, force: true });
try {
if (testInfo.status !== testInfo.expectedStatus) {
await writeFile(
testInfo.outputPath('vscode-process.log'),
`STDOUT (last 1 MiB):\n${processOutput.stdout}\nSTDERR (last 1 MiB):\n${processOutput.stderr}`
);
try {
// Includes extension-host and output-channel logs, flushed on close.
await cp(
join(userData, 'logs'),
testInfo.outputPath('vscode-logs'),
{
recursive: true
}
);
} catch (error) {
// Preserve the original test failure and make missing diagnostics explicit.
await writeFile(
testInfo.outputPath('vscode-log-capture-error.txt'),
String(error)
);
}
}
} finally {
await rm(sandbox, { recursive: true, force: true });
}
}
}
}
});

export { expect };

export async function waitForFile(path: string): Promise<Buffer> {
export async function waitForFile(
path: string,
timeout = 30_000
): Promise<Buffer> {
let bytes: Buffer | undefined;
await expect
.poll(
Expand All @@ -242,7 +279,7 @@ export async function waitForFile(path: string): Promise<Buffer> {
return 0;
}
},
{ timeout: 30_000, message: `Export should write ${path}` }
{ timeout, message: `Export should write ${path}` }
)
.toBeGreaterThan(0);
return bytes!;
Expand Down
Loading