Improved error feedbacks
This commit is contained in:
1 parent
ece851f5a0
commit
cfb5334666
12 files changed
+253
-13
No files matched your search
@@ -60,3 +60,24 @@ test('groups plain app.log lines between explicit initialization markers',()=>{
|
||||
assert.equal(grouped[1].group_inferred,true);
|
||||
assert.equal(grouped[2].group_inferred,undefined);
|
||||
});
|
||||
|
||||
test('clears configured live files, keeps imported archives, and updates the log error count',()=>{
|
||||
const counts=[];const e=new LogExplorer({},count=>counts.push(count));
|
||||
messages=[];const webview={postMessage:m=>messages.push(m)};e.panel={webview};e.activeWebview=webview;
|
||||
const errorFile=path.join(root,'logs/error.log');
|
||||
const archive=path.join(root,'logs/history.log.1');
|
||||
fs.writeFileSync(file,'27-09-26 10:12:13 ERROR app: failed\n');
|
||||
fs.writeFileSync(errorFile,'27-09-26 10:12:13 ERROR app: failed\n');
|
||||
fs.writeFileSync(archive,'27-09-26 10:12:14 INFO app: archived\n');
|
||||
e.imported.add(archive);e.poll();
|
||||
assert.equal(counts.at(-1),1);
|
||||
e.clearLogs();
|
||||
assert.equal(fs.statSync(file).size,0);
|
||||
assert.equal(fs.statSync(errorFile).size,0);
|
||||
assert.match(fs.readFileSync(archive,'utf8'),/archived/);
|
||||
assert.equal(counts.at(-1),0);
|
||||
assert.deepEqual(messages.filter(message=>message.type==='entries').at(-1).entries,[]);
|
||||
fs.appendFileSync(file,'27-09-26 10:12:15 CRITICAL app: new failure\n');e.poll();
|
||||
assert.equal(counts.at(-1),1);
|
||||
assert.equal(latest()[0].message,'new failure');
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
const {test}=require('node:test');
|
||||
const assert=require('node:assert/strict');
|
||||
const {findLogSource}=require('../out/logSource');
|
||||
const expression='sensor.target_temperature_heatpump + 0.5';
|
||||
const entry={app:'living_room_heatpump',message:`Error parsing string "${expression}" at character 0:Unknown variable : sensor.target_temperature_heatpump`};
|
||||
test('resolves the failing expression inside the matching app rather than another app',()=>{
|
||||
const docs=[{path:'/conf/apps/heating.yaml',text:`bedroom_heatpump:\n target_temperature: ${expression}\nliving_room_heatpump:\n target_temperature: ${expression}\n`}];
|
||||
assert.deepEqual(findLogSource(entry,docs),{path:'/conf/apps/heating.yaml',line:4});
|
||||
});
|
||||
test('resolves a unique expression in a shared template and ignores comments',()=>{
|
||||
assert.deepEqual(findLogSource(entry,[{path:'/conf/apps/templates.yml',text:`# ${expression}\nlibrary:\n value: ${expression}`}]),{path:'/conf/apps/templates.yml',line:3});
|
||||
});
|
||||
test('does not guess when a source is missing or ambiguous',()=>{
|
||||
assert.equal(findLogSource(entry,[]),undefined);
|
||||
assert.equal(findLogSource(entry,[{path:'a.yaml',text:`living_room_heatpump:\n a: ${expression}\n b: ${expression}`}]),undefined);
|
||||
assert.equal(findLogSource({...entry,message:'Initialization failed'},[]),undefined);
|
||||
});
|
||||
@@ -157,3 +157,57 @@ test('shows consecutive logs from one explicit group as a single visible row',()
|
||||
assert.doesNotMatch(rows[0].textContent,/\[group=/);
|
||||
dom.window.close();
|
||||
});
|
||||
|
||||
test('global error counter shows all loaded errors and opens them despite active filters',()=>{
|
||||
const {dom,d,entries,send}=setup();
|
||||
send([...entries,{...entries[3],event_id:'alpha-error',level:'ERROR',message:'Alpha failed'},
|
||||
{...entries[4],event_id:'beta-critical',level:'CRITICAL',message:'Beta failed'},
|
||||
{...entries[4],event_id:'supplement',kind:'evaluation',level:'ERROR',message:'Supplemental'}]);
|
||||
const counter=d.getElementById('error-count');
|
||||
assert.equal(counter.textContent,'2 errors');assert.ok(counter.classList.contains('has-errors'));
|
||||
d.getElementById('search').value='nothing';d.getElementById('period').value='15';
|
||||
counter.click();
|
||||
assert.equal(d.getElementById('search').value,'');assert.equal(d.getElementById('period').value,'0');
|
||||
assert.equal(d.getElementById('level').value,'ERROR');
|
||||
assert.equal(d.querySelectorAll('#apps .row').length,2);
|
||||
assert.match(d.getElementById('detail').textContent,/failed/);
|
||||
dom.window.close();
|
||||
});
|
||||
|
||||
test('exits errors with the counter or All levels and restores normal app sorting',()=>{
|
||||
const {dom,d,entries,send}=setup();
|
||||
send([...entries,{...entries[3],event_id:'old-alpha-error',time:entries[0].time,level:'ERROR',message:'Old error'}]);
|
||||
const counter=d.getElementById('error-count');
|
||||
counter.click();assert.equal(counter.getAttribute('aria-pressed'),'true');
|
||||
assert.equal(d.querySelector('[data-app]').dataset.app,'alpha');
|
||||
counter.click();
|
||||
assert.equal(d.getElementById('level').value,'all');
|
||||
assert.equal(counter.getAttribute('aria-pressed'),'false');
|
||||
assert.equal(d.querySelector('[data-app]').dataset.app,'beta');
|
||||
counter.click();
|
||||
d.getElementById('level').value='all';d.getElementById('level').dispatchEvent(new dom.window.Event('input'));
|
||||
assert.equal(d.querySelector('[data-app]').dataset.app,'beta');
|
||||
assert.equal(d.querySelectorAll('.row.selected').length,0);
|
||||
assert.equal(counter.getAttribute('aria-pressed'),'false');
|
||||
dom.window.close();
|
||||
});
|
||||
|
||||
test('Open source in a group targets the parsing error even when the last entry has no source',()=>{
|
||||
const {dom,d,entries,send,sent}=setup();
|
||||
send([{...entries[0],event_id:'parse-error',level:'ERROR',source:{path:'/conf/apps/heating.yaml',line:160}},
|
||||
{...entries[1],event_id:'init-failed',level:'ERROR',message:'Initialization failed'}]);
|
||||
const app=d.querySelector('[data-app="alpha"]');app.open=true;app.dispatchEvent(new dom.window.Event('toggle'));
|
||||
app.querySelector('.row').click();
|
||||
const source=[...d.querySelectorAll('#detail button')].find(button=>button.textContent==='Open source');
|
||||
assert.ok(source);source.click();assert.equal(sent.at(-1).type,'source');assert.equal(sent.at(-1).id,'parse-error');
|
||||
dom.window.close();
|
||||
});
|
||||
|
||||
test('Clear logs sends a request and resets its button after completion',()=>{
|
||||
const {dom,d,sent}=setup();
|
||||
const button=d.getElementById('clear');button.click();
|
||||
assert.equal(sent.at(-1).type,'clear');assert.equal(button.disabled,true);
|
||||
dom.window.dispatchEvent(new dom.window.MessageEvent('message',{data:{type:'clear-result',cleared:2,failures:[]}}));
|
||||
assert.equal(button.disabled,false);assert.equal(button.textContent,'Clear logs');
|
||||
dom.window.close();
|
||||
});
|
||||
Reference in new issue
Block a user