To accept inserted content in a WordprocessingML paragraph, the revision wrapper (i.e., the <w:ins> element that marks inserted content) must be removed without deleting the run element (i.e., the <w:r> element that holds run-level content). The inserted content remains part of the document because accepting an insertion changes the revision state, not the authored words inside the wrapper.
acceptChanges applies that operation by unwrapping insertion wrappers and counting each accepted insertion in its summary result.[1] The wrapper removal is paired with content preservation because the function moves the wrapper's children into the surrounding document tree instead of removing the entire insertion subtree.
Below is a test scenario of the baseline successful case of acceptChanges: accepting one inserted text run by unwrapping its w:ins wrapper.
The scenario
Given a document with an inserted text run,
When insertions are accepted and wrappers unwrapped,
Then
- one insertion is accepted.
w:inswrappers are removed.- the inserted text is preserved.
The Fixture
The scenario uses a paragraph whose only content is an insertion wrapper around a single run. Below is the test fixture code.
humanReadableTest.openspec('accept insertions by unwrapping w:ins wrappers')(
'accept insertions by unwrapping w:ins wrappers',
async ({ given, when, then, and, attachPrettyJson }: AllureBddContext) => {
const input = '<w:p><w:ins><w:r><w:t>Inserted text</w:t></w:r></w:ins></w:p>';
let result: { xml: string; summary: ReturnType<typeof acceptChanges> };
await given('a document with an inserted text run', async () => {});
await when('insertions are accepted and wrappers unwrapped', async () => {
result = runAcceptChanges(input);
await attachPrettyJson('accept-insertions-result', result);
});
await then('one insertion is accepted', async () => {
expect(result.summary.insertionsAccepted).toBe(1);
});
await and('w:ins wrappers are removed', async () => {
expect(result.xml.includes('<w:ins')).toBe(false);
});
await and('the inserted text is preserved', async () => {
expect(result.xml.includes('Inserted text')).toBe(true);
});
},
);
The Expected Result Shape
The scenario asserts both the summary count returned by acceptChanges and the serialized XML produced after the document has been rewritten.[2] Below is the result that acceptChanges is expected to return for this scenario.
expect(result.summary.insertionsAccepted).toBe(1);
expect(result.xml.includes('<w:ins')).toBe(false);
expect(result.xml.includes('Inserted text')).toBe(true);
Below is a description of the expected fields:
result.summary.insertionsAcceptedis expected to be1, because the fixture contains one insertion wrapper that is accepted.result.xmlis expected not to include<w:ins, because accepting the insertion unwraps the revision wrapper.result.xmlis expected to includeInserted text, because the inserted run content remains in the paragraph after the wrapper is removed.
Conformance
The w:ins element is a tracked-change wrapper in WordprocessingML, so accepting the insertion must leave valid paragraph content after the wrapper is gone.[3] In this scenario, the remaining paragraph contains a run element with text content, which is the document state the assertion checks through serialized XML.