@vizzly-testing/cli 0.29.2 → 0.29.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,6 +58,78 @@ export function createEventsRouter(context) {
58
58
  res.write(`event: ${eventType}\n`);
59
59
  res.write(`data: ${JSON.stringify(data)}\n\n`);
60
60
  };
61
+
62
+ /**
63
+ * Build a lookup map from comparisons array keyed by id
64
+ */
65
+ const buildComparisonMap = comparisons => {
66
+ let map = new Map();
67
+ for (let c of comparisons) {
68
+ map.set(c.id, c);
69
+ }
70
+ return map;
71
+ };
72
+ const comparisonChanged = (oldComp, newComp) => {
73
+ return JSON.stringify(oldComp) !== JSON.stringify(newComp);
74
+ };
75
+
76
+ /**
77
+ * Extract summary fields (everything except comparisons) for diffing
78
+ */
79
+ const extractSummary = data => {
80
+ let {
81
+ comparisons: _c,
82
+ ...summary
83
+ } = data;
84
+ return summary;
85
+ };
86
+
87
+ /**
88
+ * Check if summary-level fields changed between old and new data
89
+ */
90
+ const summaryChanged = (oldData, newData) => {
91
+ let oldSummary = extractSummary(oldData);
92
+ let newSummary = extractSummary(newData);
93
+ return JSON.stringify(oldSummary) !== JSON.stringify(newSummary);
94
+ };
95
+
96
+ /**
97
+ * Send incremental updates by diffing old vs new report data.
98
+ * Returns true if any events were sent.
99
+ */
100
+ const sendIncrementalUpdates = (res, oldData, newData) => {
101
+ let sent = false;
102
+ let oldComparisons = oldData.comparisons || [];
103
+ let newComparisons = newData.comparisons || [];
104
+ let oldMap = buildComparisonMap(oldComparisons);
105
+ let newMap = buildComparisonMap(newComparisons);
106
+
107
+ // New or changed comparisons — sends the full comparison object, not a partial delta
108
+ for (let [id, newComp] of newMap) {
109
+ let oldComp = oldMap.get(id);
110
+ if (!oldComp || comparisonChanged(oldComp, newComp)) {
111
+ sendEvent(res, 'comparisonUpdate', newComp);
112
+ sent = true;
113
+ }
114
+ }
115
+
116
+ // Removed comparisons
117
+ for (let [id] of oldMap) {
118
+ if (!newMap.has(id)) {
119
+ sendEvent(res, 'comparisonRemoved', {
120
+ id
121
+ });
122
+ sent = true;
123
+ }
124
+ }
125
+
126
+ // Summary-level changes (total, passed, failed, etc.)
127
+ if (summaryChanged(oldData, newData)) {
128
+ sendEvent(res, 'summaryUpdate', extractSummary(newData));
129
+ sent = true;
130
+ }
131
+ return sent;
132
+ };
61
133
  return async function handleEventsRoute(req, res, pathname) {
62
134
  if (req.method !== 'GET' || pathname !== '/api/events') {
63
135
  return false;
@@ -71,20 +143,28 @@ export function createEventsRouter(context) {
71
143
  'X-Accel-Buffering': 'no' // Disable nginx buffering
72
144
  });
73
145
 
74
- // Send initial data immediately
75
- const initialData = readReportData();
76
- if (initialData) {
77
- sendEvent(res, 'reportData', initialData);
146
+ // Send initial full data immediately
147
+ let lastSentData = readReportData();
148
+ if (lastSentData) {
149
+ sendEvent(res, 'reportData', lastSentData);
78
150
  }
79
151
 
80
152
  // Debounce file change events (fs.watch can fire multiple times)
81
153
  let debounceTimer = null;
82
154
  let watcher = null;
83
155
  const sendUpdate = () => {
84
- const data = readReportData();
85
- if (data) {
86
- sendEvent(res, 'reportData', data);
156
+ const newData = readReportData();
157
+ if (!newData) return;
158
+ if (!lastSentData) {
159
+ // No previous data — send full payload
160
+ sendEvent(res, 'reportData', newData);
161
+ } else {
162
+ // Diff and send incremental updates
163
+ let sent = sendIncrementalUpdates(res, lastSentData, newData);
164
+ // If nothing changed, skip (no event needed)
165
+ if (!sent) return;
87
166
  }
167
+ lastSentData = newData;
88
168
  };
89
169
 
90
170
  // Watch for file changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/cli",
3
- "version": "0.29.2",
3
+ "version": "0.29.3",
4
4
  "description": "Visual review platform for UI developers and designers",
5
5
  "keywords": [
6
6
  "visual-testing",