UseJunior Book a Demo

safe-docx · Compare Documents

Two-file DOCX redline comparison

When comparing a revised DOCX against an original DOCX, a redline document (i.e., a DOCX that records the differences as tracked changes) lets reviewers inspect the change set without replacing either source file. The output path matters because the comparison result must be written as a separate document that can be opened or passed to later review steps.

compareDocuments_tool supports that workflow by loading the two input DOCX files, running the document comparison engine, and writing the redline document to the requested path. The tool returns file information and comparison metadata so the caller can confirm which mode ran and where the redline document was saved.[1]

Below is a test scenario of the baseline successful case of compareDocuments_tool: two-file mode compares two DOCX files and writes a redline document.

The scenario

Given an original DOCX containing Hello world, a revised DOCX containing Hello brave new world, and a save path for redline.docx,
When compareDocuments_tool is called in two-file mode with those paths,
Then

  • the redline file at outputPath is a file.
  • the redline file size is greater than 0.
  • result.mode is two_file.
  • result.stats is defined.
  • result.saved_to is outputPath.
  • result.size_bytes is greater than 0.
  • result.engine_used is defined.

The test fixture

The fixture creates two small DOCX files in a tracked temporary directory, asks the tool to save a redline document, and then checks both the file system side effect and selected response fields.[2]

Below is the test fixture code.

test(
  'Two-file mode: compares two DOCX files and writes redline',
  async ({ given, when, then, attachPrettyJson }: AllureBddContext) => {
    const mgr = createTestSessionManager();
    const dir = await createTrackedTempDir();

    const originalPath = await writeTestDocx(dir, 'original.docx', ['Hello world']);
    const revisedPath = await writeTestDocx(dir, 'revised.docx', ['Hello brave new world']);
    const outputPath = path.join(dir, 'redline.docx');

    const result = await when('Call compare_documents (two-file)', () =>
      compareDocuments_tool(mgr, {
        original_file_path: originalPath,
        revised_file_path: revisedPath,
        save_to_local_path: outputPath,
      }),
    );
    assertSuccess(result, 'compare_documents');
    await attachPrettyJson('result', result);

    await then('Redline file written to disk', async () => {
      const stat = await fs.stat(outputPath);
      expect(stat.isFile()).toBe(true);
      expect(stat.size).toBeGreaterThan(0);
    });

    await then('Response includes stats and file info', () => {
      expect(result.mode).toBe('two_file');
      expect(result.stats).toBeDefined();
      expect(result.saved_to).toBe(outputPath);
      expect(result.size_bytes).toBeGreaterThan(0);
      expect(result.engine_used).toBeDefined();
    });
  },
);

The expected outcome

The scenario asserts that the tool writes a nonempty redline document to disk and returns response metadata for the two-file comparison. Because the file path and byte counts are produced at runtime, the expected outcome is best represented by the literal assertions that the scenario evaluates.

Below is the result that compareDocuments_tool is expected to return for this scenario.

expect(stat.isFile()).toBe(true);
expect(stat.size).toBeGreaterThan(0);

expect(result.mode).toBe('two_file');
expect(result.stats).toBeDefined();
expect(result.saved_to).toBe(outputPath);
expect(result.size_bytes).toBeGreaterThan(0);
expect(result.engine_used).toBeDefined();

Below is a description of the expected fields:

A non-obvious detail

The redline document is a side effect as well as a response value. The scenario checks the saved file with fs.stat(outputPath) before checking the response fields, so the expected outcome includes evidence that a real file was written, not only that the response named a save path.

The tracked-change conformance reference matters because a redline DOCX represents revisions using OOXML change markup. ECMA-376 Part 1, section 17.13.5 defines paragraph-level revision markers, and this scenario uses the CT_TrackChange schema reference for the tracked-change shape used by comparison output.[3]