Skip to content

Commit 142a4c7

Browse files
committed
test: Add decorator and local file overload interaction tests; increase test timeouts
1 parent 38e6dc8 commit 142a4c7

File tree

3 files changed

+128
-25
lines changed

3 files changed

+128
-25
lines changed

tests/custom/integration/cli.test.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@ import {
1010
setupTestEnvironment,
1111
} from "./fixtures";
1212

13+
// Set global timeout for all tests in this suite
14+
jest.setTimeout(40 * 1000); // 40 seconds
15+
1316
// Helper function to run CLI commands with TypeScript
1417
async function runCli(
1518
args: string[],
1619
): Promise<{ stdout: string; stderr: string; exitCode: number }> {
1720
return new Promise((resolve) => {
1821
const packageRoot = path.resolve(__dirname, "../../../");
22+
// NB: cli.js must be compiled before running this test
23+
// This is fine in CI, since we compile before running tests
1924
const cliPath = path.join(packageRoot, "dist/cli.js");
2025

2126
// Use spawn to avoid shell interpretation issues
@@ -49,15 +54,12 @@ describe("CLI Integration Tests", () => {
4954
let syncableFiles: any[] = [];
5055

5156
beforeAll(async () => {
52-
// Increase timeout for setup operations
53-
jest.setTimeout(40000); // 40 seconds
54-
5557
// Set up test environment
5658
testSetup = await setupTestEnvironment("cli_test");
5759

5860
// Create test files in Humanloop for syncing
5961
syncableFiles = await createSyncableFilesFixture(testSetup);
60-
}, 30000);
62+
});
6163

6264
afterAll(async () => {
6365
await cleanupTestEnvironment(
@@ -67,25 +69,25 @@ describe("CLI Integration Tests", () => {
6769
id: file.id as string,
6870
})),
6971
);
70-
}, 30000);
72+
});
7173

7274
/**
7375
* NOTE: This test is currently skipped due to issues with CLI environment isolation.
74-
*
75-
* The test attempts to verify behavior when no API key is available, but faces
76+
*
77+
* The test attempts to verify behavior when no API key is available, but faces
7678
* challenges with how Node.js handles process execution during tests:
77-
*
78-
* 1. When executed via child_process.exec, the path to nonexistent env files
79+
*
80+
* 1. When executed via child_process.exec, the path to nonexistent env files
7981
* causes Node to return exit code 9 (SIGKILL) instead of the expected code 1
8082
* 2. Shell interpretation of arguments makes it difficult to reliably test this edge case
81-
*
83+
*
8284
* If this functionality needs testing, consider:
8385
* - Using child_process.spawn for better argument handling
8486
* - Unit testing the API key validation logic directly
8587
* - Moving this test to a separate process with full environment isolation
86-
*
88+
*
8789
* @see https://nodejs.org/api/child_process.html for more info on process execution
88-
*/
90+
*/
8991
test.skip("pull_without_api_key: should show error when no API key is available", async () => {
9092
// GIVEN a temporary directory and no API key
9193
const { tempDir, cleanup } = createTempDir("cli-no-api-key");
@@ -118,9 +120,6 @@ describe("CLI Integration Tests", () => {
118120
});
119121

120122
test("pull_basic: should pull all files successfully", async () => {
121-
// Increase timeout for this test
122-
jest.setTimeout(30000); // 30 seconds
123-
124123
// GIVEN a base directory for pulled files
125124
const { tempDir, cleanup } = createTempDir("cli-basic-pull");
126125

@@ -152,7 +151,7 @@ describe("CLI Integration Tests", () => {
152151
}
153152

154153
cleanup();
155-
}, 30000);
154+
});
156155

157156
test("pull_with_specific_path: should pull files from a specific path", async () => {
158157
// GIVEN a base directory and specific path
@@ -193,9 +192,6 @@ describe("CLI Integration Tests", () => {
193192
});
194193

195194
test("pull_with_environment: should pull files from a specific environment", async () => {
196-
// Increase timeout for this test
197-
jest.setTimeout(30000); // 30 seconds
198-
199195
// GIVEN a base directory and environment
200196
const { tempDir, cleanup } = createTempDir("cli-env-pull");
201197

@@ -216,7 +212,7 @@ describe("CLI Integration Tests", () => {
216212
expect(result.stdout).toContain("Environment: staging");
217213

218214
cleanup();
219-
}, 30000);
215+
});
220216

221217
test("pull_with_quiet_mode: should pull files with quiet mode enabled", async () => {
222218
// GIVEN a base directory and quiet mode
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
4+
import { HumanloopClient } from "../../../src/humanloop.client";
5+
import { createTempDir } from "../fixtures";
6+
import { TestSetup, cleanupTestEnvironment, setupTestEnvironment } from "./fixtures";
7+
8+
// Set global timeout for all tests in this suite
9+
jest.setTimeout(30 * 1000); // 30 seconds
10+
11+
describe("Decorator and Local File Integration Tests", () => {
12+
let testSetup: TestSetup;
13+
let tempDirInfo: { tempDir: string; cleanup: () => void };
14+
let flowId: string | null = null;
15+
16+
beforeAll(async () => {
17+
testSetup = await setupTestEnvironment("decorator_local_file");
18+
tempDirInfo = createTempDir("decorator-local-file-integration");
19+
});
20+
21+
afterAll(async () => {
22+
tempDirInfo.cleanup();
23+
if (flowId) {
24+
await cleanupTestEnvironment(testSetup, [
25+
{
26+
type: "flow",
27+
id: flowId,
28+
},
29+
]);
30+
} else {
31+
await cleanupTestEnvironment(testSetup);
32+
}
33+
});
34+
35+
test("flow decorator should work with local prompt files", async () => {
36+
// GIVEN a local prompt file
37+
const promptContent = `---
38+
model: gpt-4o-mini
39+
temperature: 0
40+
max_tokens: -1
41+
provider: openai
42+
endpoint: chat
43+
tools: []
44+
---
45+
46+
<system>
47+
You are a helpful assistant that provides concise answers. When asked about capitals of countries,
48+
you respond with just the capital name, lowercase, with no punctuation or additional text.
49+
</system>
50+
`;
51+
52+
// Create local file structure
53+
const promptPath = `${testSetup.sdkTestDir.path}/capital_prompt`;
54+
const promptFilePath = path.join(tempDirInfo.tempDir, `${promptPath}.prompt`);
55+
fs.mkdirSync(path.dirname(promptFilePath), { recursive: true });
56+
fs.writeFileSync(promptFilePath, promptContent);
57+
58+
// GIVEN a client with local files enabled
59+
const client = new HumanloopClient({
60+
apiKey: process.env.HUMANLOOP_API_KEY,
61+
localFilesDirectory: tempDirInfo.tempDir,
62+
useLocalFiles: true,
63+
});
64+
65+
// GIVEN a flow that uses the local prompt
66+
const flowPath = `${testSetup.sdkTestDir.path}/test_flow_with_local_prompt`;
67+
const myFlow = client.flow({
68+
path: flowPath,
69+
callable: async (question: { question: string }) => {
70+
// This is the key integration point - using a local prompt within a flow
71+
const response = await client.prompts.call({
72+
path: promptPath,
73+
messages: [{ role: "user", content: question.question }],
74+
providerApiKeys: { openai: testSetup.openaiApiKey },
75+
});
76+
return response.logs?.[0]?.output || "";
77+
},
78+
});
79+
80+
// WHEN calling the flow
81+
const result = await myFlow({
82+
question: "What is the capital of France?",
83+
});
84+
85+
// THEN it should work with the local prompt
86+
expect(result?.toLowerCase()).toContain("paris");
87+
88+
// AND the logs should be properly linked
89+
await new Promise((resolve) => setTimeout(resolve, 5000));
90+
91+
// Get file IDs for log verification
92+
const [flowFile, promptFile] = await Promise.all([
93+
client.files.retrieveByPath({ path: flowPath }),
94+
client.files.retrieveByPath({ path: promptPath }),
95+
]);
96+
flowId = flowFile.id;
97+
98+
// Verify the logs are linked
99+
const [flowLogs, promptLogs] = await Promise.all([
100+
client.logs.list({ fileId: flowFile.id, page: 1, size: 1 }),
101+
client.logs.list({ fileId: promptFile.id, page: 1, size: 1 }),
102+
]);
103+
104+
// The key assertion - verify tracing works with local files
105+
expect(promptLogs.data[0].traceParentId).toBe(flowLogs.data[0].id);
106+
});
107+
});

tests/custom/integration/localFileOperations.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import {
1212
setupTestEnvironment,
1313
} from "./fixtures";
1414

15+
// Set global timeout for all tests in this suite
16+
jest.setTimeout(40 * 1000); // 40 seconds
17+
1518
// Define SyncableFile interface to match Python version
1619
interface SyncableFile {
1720
path: string;
@@ -34,9 +37,6 @@ describe("Local File Operations Integration Tests", () => {
3437
let tempDirInfo: { tempDir: string; cleanup: () => void };
3538

3639
beforeAll(async () => {
37-
// Increase timeout for setup operations
38-
jest.setTimeout(30000); // 30 seconds
39-
4040
// Set up test environment
4141
testSetup = await setupTestEnvironment("local_file_ops");
4242
tempDirInfo = createTempDir("local-file-integration");
@@ -52,7 +52,7 @@ describe("Local File Operations Integration Tests", () => {
5252
});
5353

5454
await setupClient.pull();
55-
}, 30000);
55+
});
5656

5757
afterAll(async () => {
5858
// Clean up resources
@@ -64,7 +64,7 @@ describe("Local File Operations Integration Tests", () => {
6464
id: file.id as string,
6565
})),
6666
);
67-
}, 30000);
67+
});
6868

6969
describe("Path Validation", () => {
7070
// Path validation test cases

0 commit comments

Comments
 (0)