Change details: labelled APDU/time in the header, no zero counts (v2.7.4)
- the header's trailing meta is labelled instead of bare numbers: "ADF/EF_IMSI (6F07) — READ BINARY · APDU #490 · 0251.199 sec" (the record part already read "Record 2 / 5") - the summary counts only what happened: "{c} bytes changed · {n} bytes newly observed" drops whichever part is zero ("4 bytes changed" alone when nothing was first observed) and an empty diff reads "No changes" instead of "0 bytes changed, 0 bytes newly observed" - i18n: the combined key splits into '{c} bytes changed' / '{n} bytes newly observed' plus 'No changes', 'APDU' and 'sec' ('{c}','{n}' placeholders keep the existing replace-based substitution; the Russian keeps the established wording: «Изменено байт: {c}», «Впервые наблюдается байт: {n}», «с») - tests: the header and summary assertions follow the labels, a short-file case pins the omitted zero, and an empty-diff case pins 'No changes'; 527 Python + 76 Node tests - PWA_VERSION/pyproject/version.py 2.7.4, SW cache simtrace-analyser-v84
This commit is contained in:
1 parent
71a94f5f50
commit
06c6e952a9
6 files changed
+38
-13
No files matched your search
+17
-6
@@ -2320,8 +2320,12 @@ function renderFileDiff(image) {
|
||||
meta.push(`${t('Record')} ${image.record}` +
|
||||
(image.n_records ? ` / ${image.n_records}` : ''));
|
||||
}
|
||||
if (image.index !== null && image.index !== undefined) meta.push(`#${image.index}`);
|
||||
if (image.elapsed !== null && image.elapsed !== undefined) meta.push(fmt_elapsed(image.elapsed));
|
||||
if (image.index !== null && image.index !== undefined) {
|
||||
meta.push(`${t('APDU')} #${image.index}`);
|
||||
}
|
||||
if (image.elapsed !== null && image.elapsed !== undefined) {
|
||||
meta.push(`${fmt_elapsed(image.elapsed)} ${t('sec')}`);
|
||||
}
|
||||
el('file-diff-sub').textContent = `${image.path || image.name || ''} — ${meta.join(' · ')}`;
|
||||
const before = hexImageHtml(image, 'before');
|
||||
const after = hexImageHtml(image, 'after');
|
||||
@@ -2337,9 +2341,12 @@ function renderFileDiff(image) {
|
||||
used.fresh ? `<span class="hex-legend-item"><span class="hex-cell hex-new">aa</span> ${t('newly observed')}</span>` : '',
|
||||
used.unknown ? `<span class="hex-legend-item"><span class="hex-cell hex-unknown">--</span> ${t('never observed')}</span>` : '',
|
||||
].join('');
|
||||
// Mention only what happened: "0 bytes newly observed" is noise.
|
||||
const counts = [];
|
||||
if (changed) counts.push(t('{c} bytes changed').replace('{c}', changed));
|
||||
if (fresh) counts.push(t('{n} bytes newly observed').replace('{n}', fresh));
|
||||
el('file-diff-body').innerHTML =
|
||||
`<div class="hex-summary">${t('{c} bytes changed, {n} bytes newly observed')
|
||||
.replace('{c}', changed).replace('{n}', fresh)}</div>
|
||||
`<div class="hex-summary">${counts.length ? counts.join(' · ') : t('No changes')}</div>
|
||||
<div class="hex-pair">
|
||||
<div><h4>${t('Before')}</h4>${before.html}</div>
|
||||
<div><h4>${t('After')}</h4>${after.html}</div>
|
||||
@@ -3373,7 +3380,7 @@ function onSearchChange() {
|
||||
}
|
||||
|
||||
// ──────────────────── Versioning ────────────────────
|
||||
const PWA_VERSION = '2.7.3';
|
||||
const PWA_VERSION = '2.7.4';
|
||||
const MIN_SERVER_VERSION = '2.3.0';
|
||||
|
||||
function parseVersion(v) {
|
||||
@@ -3430,7 +3437,11 @@ const LANG_RU = {
|
||||
'changed': 'изменено',
|
||||
'newly observed': 'впервые наблюдается',
|
||||
'never observed': 'не наблюдалось',
|
||||
'{c} bytes changed, {n} bytes newly observed': 'Изменено байт: {c}; впервые наблюдается байт: {n}',
|
||||
'{c} bytes changed': 'Изменено байт: {c}',
|
||||
'{n} bytes newly observed': 'Впервые наблюдается байт: {n}',
|
||||
'No changes': 'Изменений нет',
|
||||
'APDU': 'APDU',
|
||||
'sec': 'с',
|
||||
'Showing the first {n} bytes of the image': 'Показаны первые {n} байт образа',
|
||||
'The image is frozen (size cap reached) — later changes are not tracked.': 'Образ заморожен (достигнут предел размера) — последующие изменения не отслеживаются.',
|
||||
'Close': 'Закрыть',
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simtrace-analyser-v83';
|
||||
const CACHE = 'simtrace-analyser-v84';
|
||||
|
||||
const PRECACHE = [
|
||||
'index.html',
|
||||
|
||||
@@ -379,7 +379,7 @@ test('Files view: strings carry Russian translations', () => {
|
||||
for (const s of ['Files', 'Read', 'Update', 'Changed on card!', 'Change details',
|
||||
'Show diff', 'Close', 'Offset', 'Record', 'Before', 'After', 'Show the change',
|
||||
'changed', 'newly observed', 'never observed',
|
||||
'{c} bytes changed, {n} bytes newly observed',
|
||||
'{c} bytes changed', '{n} bytes newly observed', 'No changes', 'sec',
|
||||
'Showing the first {n} bytes of the image',
|
||||
'The image is frozen (size cap reached) — later changes are not tracked.',
|
||||
'No file operations recorded', 'Failed to load files', 'Loading…']) {
|
||||
@@ -508,9 +508,10 @@ test('Change details modal: header, summary, legend and both views', () => {
|
||||
});
|
||||
const sub = el('file-diff-sub').textContent;
|
||||
assert.match(sub, /MF\/EF_ICCID \(2FE2\) — READ BINARY/);
|
||||
assert.match(sub, /#12/);
|
||||
assert.match(sub, /APDU #12/);
|
||||
assert.match(sub, /0003\.250 sec/);
|
||||
const body = el('file-diff-body').innerHTML;
|
||||
assert.match(body, /2 bytes changed, 4 bytes newly observed/);
|
||||
assert.match(body, /2 bytes changed · 4 bytes newly observed/);
|
||||
assert.match(body, /hex-cell hex-changed/); // legend + the changed byte
|
||||
assert.match(body, /hex-cell hex-new/);
|
||||
assert.match(body, /hex-cell hex-unknown/);
|
||||
@@ -542,6 +543,8 @@ test('Change details: a short file shows no filler, no offset, no stray legend',
|
||||
const body = el('file-diff-body').innerHTML;
|
||||
assert.doesNotMatch(body, /hex-unknown/); // no '--' cells at all
|
||||
assert.doesNotMatch(body, /hex-addr/); // a single row: no offset column
|
||||
// The summary mentions only what happened.
|
||||
assert.match(body, /^<div class="hex-summary">1 bytes changed<\/div>/);
|
||||
assert.match(body, /hex-cell hex-changed/);
|
||||
// The legend lists only what the views show: 'changed' (the summary line
|
||||
// above still counts the zero "newly observed" bytes).
|
||||
@@ -551,6 +554,17 @@ test('Change details: a short file shows no filler, no offset, no stray legend',
|
||||
assert.doesNotMatch(legend, /newly observed|never observed/);
|
||||
});
|
||||
|
||||
test('Change details: an empty diff says so instead of counting zeros', () => {
|
||||
renderFileDiff({
|
||||
name: 'EF_ICCID', path: 'MF/EF_ICCID (2FE2)', op: 'READ BINARY',
|
||||
record: null, size: 2, index: 1, elapsed: 0.5, ranges: [],
|
||||
observed_ranges: [], before: [{offset: 0, hex: 'aaaa'}],
|
||||
after: [{offset: 0, hex: 'aaaa'}], image_truncated: false,
|
||||
});
|
||||
assert.match(el('file-diff-body').innerHTML,
|
||||
/^<div class="hex-summary">No changes<\/div>/);
|
||||
});
|
||||
|
||||
test('Change details: a short record keeps its never-observed tail', () => {
|
||||
// A 9-byte record with 4 bytes observed: the row ends at 9 (no filler
|
||||
// past it) and '--' marks the bytes that were never observed.
|
||||
|
||||
Reference in new issue
Block a user