UseJunior Book a Demo

safe-docx · Compare Documents

Session redline comparison against original

When reviewing changes made during a document-editing session, a redline file (i.e., a DOCX that shows tracked differences) needs to compare the edited session state against the original document baseline. The baseline matters because session edits may exist in memory before a separate revised file has been saved.

compareDocuments_tool supports that session workflow by resolving the open document session, generating comparison baselines when needed, comparing the original buffer with the current session buffer, and writing the redline file to the requested output path.[1] The tool returns response fields that identify session mode and expose comparison metadata so the caller can report what was written.

Scenario

The scenario records the session comparison behavior after a paragraph replacement has been applied through the document session.[2]

Below is a test scenario of the session comparison case of compareDocuments_tool: session mode compares session edits against the original document.

The scenario

Given a session opened from a DOCX whose paragraph contains Original text here, and the paragraph is edited with replace_text to contain Modified text here,
When compareDocuments_tool is called with file_path and save_to_local_path,
Then

  • the redline file exists on disk.
  • the redline file size is greater than 0.
  • result.mode is session.
  • result.stats is defined.
  • result.resolved_file_path is truthy.

Fixture

The fixture opens a one-paragraph session document, applies a replacement through replace_text, and then calls the comparison tool in session mode.

Below is the test fixture code.

test(
  'Session mode: compares session edits against original',
  async ({ given, when, then, attachPrettyJson }: AllureBddContext) => {
    const dir = await createTrackedTempDir();

    const docXml =
      `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
      `<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">` +
      `<w:body><w:p><w:r><w:t>Original text here</w:t></w:r></w:p></w:body></w:document>`;
    const { mgr, firstParaId, inputPath } = await openSession([], {
      xml: docXml,
      extraFiles: {
        '[Content_Types].xml': CONTENT_TYPES_XML,
        '_rels/.rels': RELS_XML,
      },
    });

    await when('Make an edit via replace_text', async () => {
      const editResult = await replaceText(mgr, {
        file_path: inputPath,
        target_paragraph_id: firstParaId,
        old_string: 'Original text here',
        new_string: 'Modified text here',
        instruction: 'Change original to modified',
      });
      assertSuccess(editResult, 'replace_text');
    });

    const outputPath = path.join(dir, 'session-redline.docx');
    const result = await when('Call compare_documents (session)', () =>
      compareDocuments_tool(mgr, {
        file_path: inputPath,
        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 indicates session mode', () => {
      expect(result.mode).toBe('session');
      expect(result.stats).toBeDefined();
      expect(result.resolved_file_path).toBeTruthy();
    });
  },
);

Expected Outcome

The expected outcome is the file-system evidence that the redline file was written, plus the response fields that show session comparison was used.

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('session');
expect(result.stats).toBeDefined();
expect(result.resolved_file_path).toBeTruthy();

Below is a description of the expected fields:

Conformance

Session comparison produces a redline file using OOXML tracked-change structures, and those structures must remain valid at paragraph level when the document is reconstructed.[3]