| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import chai from 'chai'; // not esm |
| import chaiDom from 'chai-dom'; // not esm |
| import * as constant from '../src/constants'; |
| import { FakeWebviewAPi, ffxEventForTest, logDataForTest, malformedLogForTest } |
| from './util'; |
| import { Filter } from '../src/filter'; |
| import { LogList, WRAP_LOG_TEXT_ATTR } from '../components/log_list'; |
| import { State } from '../src/state'; |
| import {LitElement} from 'lit'; |
| |
| before(function () { |
| chai.should(); |
| chai.use(chaiDom); |
| }); |
| |
| describe('LogList', () => { |
| let root: HTMLElement; |
| let state: State; |
| |
| beforeEach(() => { |
| root = document.createElement('div'); |
| document.body.appendChild(root); |
| state = new State(new FakeWebviewAPi()); |
| }); |
| |
| afterEach(() => { |
| root.remove(); |
| }); |
| |
| describe('#constructor', () => { |
| it('crates a new empty view', () => { |
| const logsList = new LogList(state); |
| logsList.element.children.length.should.equal(1); |
| logsList.element.children[0].id.should.equal('logs-table-header'); |
| }); |
| |
| it('sets the log wrapping from the state', () => { |
| state.shouldWrapLogs = true; |
| let logList = new LogList(state); |
| logList.element.hasAttribute(WRAP_LOG_TEXT_ATTR).should.be.true; |
| |
| state.shouldWrapLogs = false; |
| logList = new LogList(state); |
| logList.element.hasAttribute(WRAP_LOG_TEXT_ATTR).should.be.false; |
| }); |
| }); |
| |
| describe('#addLog', () => { |
| it('appends a log', async () => { |
| const view = new LogList(state); |
| const logsList = view.element; |
| document.body.appendChild(logsList); |
| |
| logsList.children.length.should.equal(1); |
| logsList.children[0].id.should.equal('logs-table-header'); |
| view.addLog(logDataForTest('core/foo')); |
| logsList.children.length.should.equal(2); |
| |
| const logLine = logsList.children[1] as LitElement; |
| await logLine.updateComplete; |
| logLine.children[0].should.have.class('log-entry'); |
| logLine.children[0].should.have.attr('data-moniker', 'core/foo'); |
| logLine.children[0].should.have.attr('data-pid', '123'); |
| logLine.children[0].should.have.attr('data-tid', '456'); |
| (logLine.children[0] as HTMLElement).hidden.should.be.false; |
| |
| const testFields = ['000000.12', '123', '456', 'core/foo', 'my_tag', 'Info', 'msg']; |
| let field: keyof typeof testFields; |
| for (field in testFields) { |
| const logField = logLine.children[0].children[field] as HTMLElement; |
| logField.innerText.should.equal(testFields[field]); |
| } |
| logsList.remove(); |
| }); |
| |
| |
| it('hides the log if the filters require so', () => { |
| const view = new LogList(state); |
| |
| state.registerFilter(new Filter({ |
| category: 'moniker', |
| subCategory: undefined, |
| operator: 'contains', |
| value: 'core/bar', |
| }), 'moniker:core/bar'); |
| |
| view.addLog(logDataForTest('core/foo')); |
| |
| const logsList = view.element; |
| logsList.children.length.should.equal(2); |
| const logLine = logsList.children[1] as HTMLElement; |
| logLine.hidden.should.be.true; |
| }); |
| |
| it('handles ffx events', async () => { |
| const view = new LogList(state); |
| let moniker = constant.FFX_MONIKER; |
| const msg = 'Logger lost connection to target. Retrying...'; |
| view.addLog(ffxEventForTest('TargetDisconnected')); |
| |
| const logsList = view.element; |
| document.body.appendChild(logsList); |
| logsList.children.length.should.equal(2); |
| logsList.children[0].id.should.equal('logs-table-header'); |
| |
| const logLine = logsList.children[1] as LitElement; |
| await logLine.updateComplete; |
| |
| logLine.children[0].children.length.should.equal(7); |
| logLine.children[0].should.have.class('log-entry'); |
| logLine.children[0].should.have.attr('data-moniker', '<ffx>'); |
| (logLine.children[0] as HTMLElement).hidden.should.be.false; |
| |
| let monikerEl = logLine.children[0].children[3] as HTMLElement; |
| let msgEl = logLine.children[0].children[6] as HTMLElement; |
| monikerEl.innerText.should.equal(moniker); |
| msgEl.innerText.should.equal(msg); |
| logsList.remove(); |
| }); |
| |
| it('handles malformed logs', async () => { |
| const view = new LogList(state); |
| const msg = 'Malformed target log: oh no something went wrong'; |
| view.addLog(malformedLogForTest('oh no something went wrong')); |
| |
| const logsList = view.element; |
| document.body.appendChild(logsList); |
| logsList.children.length.should.equal(2); |
| logsList.children[0].id.should.equal('logs-table-header'); |
| |
| const logLine = logsList.children[1] as LitElement; |
| await logLine.updateComplete; |
| logLine.children[0].children.length.should.equal(7); |
| logLine.children[0].should.have.class('log-entry'); |
| (logLine.children[0] as HTMLElement).hidden.should.be.false; |
| let msgEl = logLine.children[0].children[6] as HTMLElement; |
| msgEl.innerText.should.equal(msg); |
| logsList.remove(); |
| }); |
| |
| it('detects user hovering logs', () => { |
| const view = new LogList(state); |
| view.addLog(logDataForTest('core/foo')); |
| const scrollArea = view.element.parentElement; |
| scrollArea?.matches(':hover').should.equal(false); |
| scrollArea?.dispatchEvent(new MouseEvent('onmouseenter')); |
| scrollArea?.matches(':hover').should.equal(true); |
| }); |
| }); |
| |
| describe('#reset', () => { |
| it('resets the log list', () => { |
| const view = new LogList(state); |
| view.addLog(logDataForTest('core/foo')); |
| |
| let logsList = view.element; |
| logsList.children.length.should.equal(2); |
| view.reset(); |
| logsList.children.length.should.equal(1); |
| }); |
| }); |
| }); |