Visual Diff Validator
- A color-coded, visual diff viewer in Postman that compares API responses to a stored baseline and highlights added, changed, and removed fields
- Powered by the
diffnpm package for precision.
Why I think it could help people?
It helps testers and developers quickly identify added, removed, or changed fields in API responses with a clear, color-coded summary and highlights, making regression testing faster, more reliable, and easier to interpret.
Problem inspired from: Compare 2 responses using Postman
Code:
Public collection link
Request 1
Pre Request Script
// Update the baseline_response environment variable with the current response
const response = pm.response.json();
pm.globals.set("baseline_response", JSON.stringify(response));
Request 2
Pre Request Script:
// Check if the environment variable 'baseline_response' is set
const baselineResponse = pm.globals.get("baseline_response");
if (!baselineResponse) {
console.warn("Warning: The 'baseline_response' variable is not set. Please run the previous request before proceeding to compare responses.");
}
Post Response Script:
const Diff = pm.require('npm:[email protected]');
const _ = require('lodash');
// Get current and baseline responses
let current = pm.response.json();
let baselineStr = pm.globals.get("baseline_response");
let baseline = {};
try {
baseline = JSON.parse(baselineStr);
} catch (e) {
console.error("Failed to parse baseline:", e);
}
// Clean both objects
let cleanedCurrent = _.omit(current, ['id', 'createdAt', 'updatedAt']);
let cleanedBaseline = _.omit(baseline, ['id', 'createdAt', 'updatedAt']);
// Compare
let allKeys = _.union(Object.keys(cleanedCurrent), Object.keys(cleanedBaseline));
let addedFields = [];
let changedFields = [];
let removedFields = [];
let rows = allKeys.map(key => {
let baselineVal = cleanedBaseline[key];
let currentVal = cleanedCurrent[key];
let isChanged = baselineVal !== undefined && currentVal !== undefined && !_.isEqual(baselineVal, currentVal);
let isAdded = baselineVal === undefined && currentVal !== undefined;
let isRemoved = baselineVal !== undefined && currentVal === undefined;
if (isChanged) changedFields.push(key);
if (isAdded) addedFields.push(key);
if (isRemoved) removedFields.push(key);
// Word-level diff for changed values
let diffHtml = '';
if (isChanged) {
let diffParts = Diff.diffWords(
JSON.stringify(baselineVal),
JSON.stringify(currentVal)
);
diffHtml = diffParts.map(part => {
if (part.added) return `<span style="background:#d4f8d4">${part.value}</span>`;
if (part.removed) return `<span style="background:#f8d4d4;text-decoration:line-through">${part.value}</span>`;
return part.value;
}).join('');
}
return {
field: key,
baseline: baselineVal !== undefined ? JSON.stringify(baselineVal) : '',
current: currentVal !== undefined ? JSON.stringify(currentVal) : '',
currentDiff: isChanged ? diffHtml : (currentVal !== undefined ? JSON.stringify(currentVal) : ''),
changed: isChanged,
added: isAdded,
removed: isRemoved
};
});
// Visualizer
pm.visualizer.set(`
<style>
body { font-family: monospace; padding: 1rem; }
.summary h3 { margin: 0 0 .5rem 0; }
.summary ul { margin: 0 0 1.5rem 1.25rem; padding: 0; }
li { margin: .3rem 0; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; vertical-align: top; text-align: left; }
.changed { background-color: #fff3b0; }
.added { background-color: #d4f8d4; }
.removed { background-color: #f8d4d4; }
</style>
<div class="summary">
<h3>📊 Changes Summary:</h3>
<ul>
<li><strong>Fields Added:</strong> {{addedCount}} {{#if addedList.length}}→ {{addedList}}{{/if}}</li>
<li><strong>Fields Modified:</strong> {{changedCount}} {{#if changedList.length}}→ {{changedList}}{{/if}}</li>
<li><strong>Fields Deleted:</strong> {{removedCount}} {{#if removedList.length}}→ {{removedList}}{{/if}}</li>
</ul>
</div>
<table>
<thead>
<tr>
<th>Field</th>
<th>Baseline</th>
<th>Current</th>
</tr>
</thead>
<tbody>
{{#each rows}}
<tr class="{{#if changed}}changed{{/if}}{{#if added}} added{{/if}}{{#if removed}} removed{{/if}}">
<td>{{field}}</td>
<td>{{baseline}}</td>
<td>{{{currentDiff}}}</td>
</tr>
{{/each}}
</tbody>
</table>
`, {
rows,
addedCount: addedFields.length,
changedCount: changedFields.length,
removedCount: removedFields.length,
addedList: addedFields.join(', '),
changedList: changedFields.join(', '),
removedList: removedFields.join(', ')
});
Reference: Compare two responses | Documentation | Postman API Network
