Skip to content

Commit 4548c34

Browse files
Copilotvobu
andauthored
test: add integration test coverage for diagram feature (#63)
* Initial plan * test: add integration tests for diagram feature Co-authored-by: vobu <6573426+vobu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vobu <6573426+vobu@users.noreply.github.com>
1 parent 8637883 commit 4548c34

File tree

2 files changed

+116
-1
lines changed

2 files changed

+116
-1
lines changed

package-lock.json

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/process-instances.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,109 @@ describe('Process Instance Integration Tests (requires Camunda 8 at localhost:80
139139
assert.ok(outputWithAlias.includes('completed'), 'Output with await alias should indicate process completed');
140140
assert.ok(outputWithAlias.includes('variables'), 'Output with await alias should contain variables');
141141
});
142+
143+
test('get process instance with --diagram flag saves PNG to file', async () => {
144+
// Deploy and create a process instance
145+
await deploy(['tests/fixtures/simple.bpmn'], {});
146+
const result = await createProcessInstance({
147+
processDefinitionId: 'simple-process',
148+
});
149+
150+
assert.ok(result, 'Create result should exist');
151+
const instanceKey = result.processInstanceKey.toString();
152+
153+
// Run CLI command to generate diagram with --output flag
154+
const { execSync } = await import('node:child_process');
155+
const { mkdtempSync } = await import('node:fs');
156+
const { tmpdir } = await import('node:os');
157+
const tmpDir = mkdtempSync(join(tmpdir(), 'c8ctl-diagram-test-'));
158+
const outputPath = join(tmpDir, 'diagram.png');
159+
160+
try {
161+
const output = execSync(
162+
`node src/index.ts get pi --key ${instanceKey} --diagram --output ${outputPath}`,
163+
{ encoding: 'utf8', cwd: process.cwd(), stdio: 'pipe' }
164+
);
165+
166+
// Verify the file was created
167+
assert.ok(existsSync(outputPath), 'Diagram PNG file should be created');
168+
169+
// Verify the file has content (PNG files start with specific bytes)
170+
const { readFileSync } = await import('node:fs');
171+
const fileContent = readFileSync(outputPath);
172+
assert.ok(fileContent.length > 0, 'PNG file should have content');
173+
// Verify PNG signature (starts with 0x89504E47)
174+
assert.strictEqual(fileContent[0], 0x89, 'PNG file should start with PNG signature byte 1');
175+
assert.strictEqual(fileContent[1], 0x50, 'PNG file should start with PNG signature byte 2');
176+
assert.strictEqual(fileContent[2], 0x4E, 'PNG file should start with PNG signature byte 3');
177+
assert.strictEqual(fileContent[3], 0x47, 'PNG file should start with PNG signature byte 4');
178+
179+
// Verify success message in output
180+
assert.ok(output.includes('Diagram saved'), 'Output should indicate diagram was saved');
181+
} finally {
182+
// Cleanup: remove temp directory
183+
const { rmSync } = await import('node:fs');
184+
rmSync(tmpDir, { recursive: true, force: true });
185+
}
186+
});
187+
188+
test('get process instance with --diagram flag without --output prints inline', async () => {
189+
// Deploy and create a process instance
190+
await deploy(['tests/fixtures/simple.bpmn'], {});
191+
const result = await createProcessInstance({
192+
processDefinitionId: 'simple-process',
193+
});
194+
195+
assert.ok(result, 'Create result should exist');
196+
const instanceKey = result.processInstanceKey.toString();
197+
198+
// Run CLI command to generate diagram without --output flag
199+
const { execSync } = await import('node:child_process');
200+
201+
try {
202+
const output = execSync(
203+
`node src/index.ts get pi --key ${instanceKey} --diagram`,
204+
{ encoding: 'utf8', cwd: process.cwd(), stdio: 'pipe' }
205+
);
206+
207+
// Verify iTerm2 inline image protocol is present in output
208+
// The protocol uses OSC 1337 escape sequence: \x1b]1337;File=...
209+
assert.ok(output.includes('\x1b]1337;File='), 'Output should contain iTerm2 inline image protocol');
210+
assert.ok(output.includes('inline=1'), 'Output should indicate inline display mode');
211+
} catch (error: any) {
212+
// On systems without Chrome/Chromium, this test may fail
213+
// Verify it fails with a helpful error message
214+
if (error.stderr && error.stderr.includes('No Chrome or Chromium browser found')) {
215+
assert.ok(true, 'Test skipped: Chrome/Chromium not installed');
216+
} else {
217+
throw error;
218+
}
219+
}
220+
});
221+
222+
test('get process instance with --diagram handles non-existent process instance', async () => {
223+
// Run CLI command with a non-existent process instance key
224+
const { execSync } = await import('node:child_process');
225+
const nonExistentKey = '9999999999999';
226+
227+
try {
228+
execSync(
229+
`node src/index.ts get pi --key ${nonExistentKey} --diagram`,
230+
{ encoding: 'utf8', cwd: process.cwd(), stdio: 'pipe' }
231+
);
232+
assert.fail('Should have thrown an error for non-existent process instance');
233+
} catch (error: any) {
234+
// CLI should exit with non-zero code
235+
assert.ok(error.status !== 0, 'CLI should exit with non-zero status for non-existent process instance');
236+
// Check that error output contains an error message
237+
const hasErrorMessage = error.stderr && (
238+
error.stderr.includes('Failed') ||
239+
error.stderr.includes('NOT_FOUND') ||
240+
error.stderr.includes('✗') ||
241+
error.stderr.includes('Error')
242+
);
243+
assert.ok(hasErrorMessage,
244+
`CLI should output error message for non-existent process instance. Got stderr: ${error.stderr}`);
245+
}
246+
});
142247
});

0 commit comments

Comments
 (0)