Skip to content

Commit 14627a4

Browse files
author
Emil Kais
committed
Setup jest and fix test and add sample files
1 parent 6fcb732 commit 14627a4

File tree

8 files changed

+2432
-156
lines changed

8 files changed

+2432
-156
lines changed

jest.config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
preset: "ts-jest",
3+
testEnvironment: "node",
4+
testMatch: [
5+
"<rootDir>/**/*.(test|spec).(ts|js)",
6+
],
7+
};

nodes/Markitdown/Markitdown.node.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,23 @@ export class Markitdown implements INodeType {
4747

4848
const binaryData = this.helpers.assertBinaryData(i, inputBinaryField);
4949

50-
// Step 2: Write the file to a tmp directory
5150
const inputTmpFile = await tmpFile({
5251
prefix: 'n8n-markitdown-input-',
5352
postfix: binaryData.fileName
5453
});
5554
await fsPromise.writeFile(inputTmpFile.path, Buffer.from(binaryData.data, 'base64'));
5655

57-
// Step 3: Run markitdown command on the tmp file
5856
const outputTmpFile = await tmpFile({
5957
prefix: 'n8n-markitdown-output-',
60-
postfix: '.md'
58+
postfix: '.md',
6159
});
6260

63-
// Build the markitdown command
6461
const command = `markitdown "${inputTmpFile.path}" -o "${outputTmpFile.path}"`.trim();
6562

66-
// Execute markitdown
67-
await execPromise(command);
63+
await execPromise(command);
6864

69-
// Read the output file
7065
const outputContent = await fsPromise.readFile(outputTmpFile.path, 'utf-8');
7166

72-
// Prepare the output item
7367
const newItem: INodeExecutionData = {
7468
json: {
7569
data: outputContent
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { IExecuteFunctions } from 'n8n-workflow';
2+
import { promises as fsPromise } from 'fs-extra';
3+
import { Markitdown } from '../Markitdown.node'
4+
import * as path from 'path';
5+
6+
describe('Markitdown Node', () => {
7+
let nodeInstance = new Markitdown()
8+
9+
const sampleFilePath = path.join(__dirname, 'test.docx');
10+
let sampleFileBuffer: Buffer;
11+
beforeAll(async () => {
12+
// Create a real sample file for testing
13+
sampleFileBuffer = await fsPromise.readFile(sampleFilePath);
14+
})
15+
afterAll(async () => {
16+
// Clean up the sample file
17+
try {
18+
jest.restoreAllMocks(); // Reset mocks after each test
19+
await fsPromise.unlink(sampleFilePath);
20+
} catch (error) {
21+
// Ignore if already deleted
22+
}
23+
});
24+
25+
it('should convert a document to markdown', async () => {
26+
// jest.spyOn(fsPromise, 'readFile').mockResolvedValue(``)
27+
// jest.spyOn(fsPromise, 'writeFile').mockResolvedValue()
28+
// Create a mock execution context with real binary data
29+
const mockExecuteFunctions: IExecuteFunctions = {
30+
getInputData: () => [{
31+
json: { filename: 'test-sample.docx' },
32+
binary: {
33+
data: {
34+
fileName: 'test-sample.docx',
35+
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
36+
data: sampleFileBuffer.toString('base64')
37+
}
38+
}
39+
}],
40+
getNodeParameter: () => 'data',
41+
helpers: {
42+
assertBinaryData: (itemIndex: number, field: string) => {
43+
const items = mockExecuteFunctions.getInputData();
44+
if (itemIndex >= items.length) {
45+
throw new Error(`Item index ${itemIndex} out of bounds`);
46+
}
47+
48+
const item = items[itemIndex];
49+
if (!item.binary || !item.binary[field]) {
50+
throw new Error(`Binary data not found for field ${field}`);
51+
}
52+
53+
return item.binary[field];
54+
}
55+
},
56+
continueOnFail: () => false
57+
} as unknown as IExecuteFunctions;
58+
59+
// Execute the node function
60+
const result = await nodeInstance.execute.call(mockExecuteFunctions);
61+
62+
// Verify the results
63+
expect(result).toHaveLength(1);
64+
expect(result[0]).toHaveLength(1);
65+
const readSample = await fsPromise.readFile(path.join(__dirname, 'test.md'))
66+
expect(result[0][0].json.data).toBe(readSample.toString());
67+
68+
// Verify the command execution
69+
expect(nodeInstance.execute).toHaveBeenCalledTimes(1);
70+
// expect(nodeInstance.execute.calls[0][0]).toMatch(/markitdown ".*n8n-markitdown-input-test-sample.docx" -o ".*n8n-markitdown-output-.md"/);
71+
}, 30000)
72+
73+
});

nodes/Markitdown/test/test.docx

16.9 KB
Binary file not shown.

nodes/Markitdown/test/test.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation
2+
3+
Qingyun Wu , Gagan Bansal , Jieyu Zhang, Yiran Wu, Beibin Li, Erkang Zhu, Li Jiang, Xiaoyun Zhang, Shaokun Zhang, Jiale Liu, Ahmed Awadallah, Ryen W. White, Doug Burger, Chi Wang
4+
5+
# Abstract
6+
7+
AutoGen is an open-source framework that allows developers to build LLM applications via multiple agents that can converse with each other to accomplish tasks. AutoGen agents are customizable, conversable, and can operate in various modes that employ combinations of LLMs, human inputs, and tools. Using AutoGen, developers can also flexibly define agent interaction behaviors. Both natural language and computer code can be used to program flexible conversation patterns for different applications. AutoGen serves as a generic framework for building diverse applications of various complexities and LLM capacities. Empirical studies demonstrate the effectiveness of the framework in many example applications, with domains ranging from mathematics, coding, question answering, operations research, online decision-making, entertainment, etc.
8+
9+
# Introduction
10+
11+
Large language models (LLMs) are becoming a crucial building block in developing powerful agents that utilize LLMs for reasoning, tool usage, and adapting to new observations (Yao et al., 2022; Xi et al., 2023; Wang et al., 2023b) in many real-world tasks. Given the expanding tasks that could benefit from LLMs and the growing task complexity, an intuitive approach to scale up the power of agents is to use multiple agents that cooperate. Prior work suggests that multiple agents can help encourage divergent thinking (Liang et al., 2023), improve factuality and reasoning (Du et al., 2023), and provide validation (Wu et al., 2023).
12+
13+
## d666f1f7-46cb-42bd-9a39-9a39cf2a509f
14+
15+
In light of the intuition and early evidence of promise, it is intriguing to ask the following question: how can we facilitate the development of LLM applications that could span a broad spectrum of domains and complexities based on the multi-agent approach? Our insight is to use multi-agent conversations to achieve it. There are at least three reasons confirming its general feasibility and utility thanks to recent advances in LLMs: First, because chat optimized LLMs (e.g., GPT-4) show the ability to incorporate feedback, LLM agents can cooperate through conversations with each other or human(s), e.g., a dialog where agents provide and seek reasoning, observations, critiques, and validation. Second, because a single LLM can exhibit a broad range of capabilities (especially when configured with the correct prompt and inference settings), conversations between differently configured agents can help combine these broad LLM capabilities in a modular and complementary manner. Third, LLMs have demonstrated ability to solve complex tasks when the tasks are broken into simpler subtasks. Here is a random UUID in the middle of the paragraph! 314b0a30-5b04-470b-b9f7-eed2c2bec74a Multi-agent conversations can enable this partitioning and integration in an intuitive manner. How can we leverage the above insights and support different applications with the common requirement of coordinating multiple agents, potentially backed by LLMs, humans, or tools exhibiting different capacities? We desire a multi-agent conversation framework with generic abstraction and effective implementation that has the flexibility to satisfy different application needs. Achieving this requires addressing two critical questions: (1) How can we design individual agents that are capable, reusable, customizable, and effective in multi-agent collaboration? (2) How can we develop a straightforward, unified interface that can accommodate a wide range of agent conversation patterns? In practice, applications of varying complexities may need distinct sets of agents with specific capabilities, and may require different conversation patterns, such as single- or multi-turn dialogs, different human involvement modes, and static vs. dynamic conversation. Moreover, developers may prefer the flexibility to program agent interactions in natural language or code. Failing to adequately address these two questions would limit the framework’s scope of applicability and generality.
16+
17+
Here is a random table for .docx parsing test purposes:
18+
19+
| | | | | | |
20+
| --- | --- | --- | --- | --- | --- |
21+
| 1 | 2 | 3 | 4 | 5 | 6 |
22+
| 7 | 8 | 9 | 10 | 11 | 12 |
23+
| 13 | 14 | 49e168b7-d2ae-407f-a055-2167576f39a1 | 15 | 16 | 17 |
24+
| 18 | 19 | 20 | 21 | 22 | 23 |
25+
| 24 | 25 | 26 | 27 | 28 | 29 |

package.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"format": "prettier nodes --write",
2929
"lint": "eslint nodes package.json",
3030
"lintfix": "eslint nodes package.json --fix",
31-
"prepublishOnly": "pnpm build && pnpm lint -c .eslintrc.prepublish.js nodes package.json"
31+
"prepublishOnly": "pnpm build && pnpm lint -c .eslintrc.prepublish.js nodes package.json",
32+
"test": "jest"
3233
},
3334
"files": [
3435
"dist"
@@ -41,6 +42,8 @@
4142
},
4243
"devDependencies": {
4344
"@types/fs-extra": "^11.0.4",
45+
"@types/jest": "^29.5.14",
46+
"@types/mocha": "^10.0.10",
4447
"@types/node": "^22.13.8",
4548
"@typescript-eslint/parser": "^7.15.0",
4649
"eslint": "^8.56.0",
@@ -54,9 +57,15 @@
5457
"n8n-workflow": "*"
5558
},
5659
"dependencies": {
60+
"@n8n/di": "^0.2.0",
5761
"child_process": "^1.0.2",
5862
"fs-extra": "^11.3.0",
59-
"tmp-promise": "^3.0.3"
63+
"jest": "^29.7.0",
64+
"jest-mock": "^29.7.0",
65+
"jest-mock-extended": "4.0.0-beta1",
66+
"nock": "^14.0.1",
67+
"tmp-promise": "^3.0.3",
68+
"ts-jest": "^29.2.6"
6069
},
6170
"pnpm": {
6271
"overrides": {

0 commit comments

Comments
 (0)