UNPKG

@qaflag/core

Version:

Base requirements for the QA Flag library

152 lines (125 loc) 3.96 kB
import { ValueInterface } from '../value/value.interface'; import { DebugContent, LoggerInterface } from '../types/log-provider.interface'; import { LogContent, LogMessage, LogMessageType } from './log-message'; export class Logger implements LoggerInterface { #messages: LogMessage[] = []; #started: number | null = null; #ended: number | null = null; public get started() { return this.#started; } public get ended() { return this.#ended; } public get duration(): number { this.enforceHasEnded(); return (this.ended || 0) - (this.started || 0); } public get length(): number { return this.#messages.length; } public get lastLine(): LogMessage { return this.#messages[this.#messages.length - 1]; } public lastLineIsBreak(): boolean { return ( this.lastLine.type == 'lineBreak' || this.lastLine.text.trim().length == 0 ); } public start() { this.enforceNotStarted(); this.#started = Date.now(); } public end() { this.enforceStartedButNotEnded(); this.#ended = Date.now(); } public get messages(): LogMessage[] { return this.#messages; } public count(type: LogMessageType | LogMessageType[]): number { return this.filter(type).length; } public filter(type: LogMessageType | LogMessageType[]): LogMessage[] { type = Array.isArray(type) ? type : [type]; return this.#messages.filter(message => type.includes(message.type)); } public get failed(): boolean { return this.#messages.some(message => message.type == 'fail'); } protected enforceNotStarted() { if (this.started) throw 'Already started.'; if (this.ended) throw 'Already ended.'; } protected enforceStartedButNotEnded() { if (!this.started) throw 'Not yet started.'; if (this.ended) throw 'Already ended.'; } protected enforceHasEnded() { if (!this.started) throw 'Not yet started.'; if (!this.ended) throw 'Not yet ended.'; } protected messageToString(message: DebugContent) { if ( typeof message == 'string' || typeof message == 'number' || typeof message == 'boolean' ) { return String(message); } return message.string.$; } public log(type: LogMessageType, content: LogContent | string) { this.enforceStartedButNotEnded(); const message = new LogMessage( type, typeof content == 'string' ? { text: content } : content, ); this.#messages.push(message); return message; } public debug(content: DebugContent | DebugContent[]) { const messages = Array.isArray(content) ? content : [content]; messages.forEach(message => { this.log('info', { text: this.messageToString(message) }); }); } public horizontalRule() { this.log('horizontalRule', '-------'); } public lineBreak() { this.log('lineBreak', ''); } public info(content: string | string[]) { const messages = Array.isArray(content) ? content : [content]; messages.forEach(message => { this.log('info', { text: this.messageToString(message) }); }); } public heading(content: string | string[]) { const messages = Array.isArray(content) ? content : [content]; messages.forEach(message => { this.log('heading', { text: this.messageToString(message) }); }); } public action(name: string, target?: ValueInterface, text?: string) { this.log('action', { name, target: target?.name, text: text || '', }); } public pass(content: LogContent | string | LogContent[]) { const messages = Array.isArray(content) ? content : [content]; messages.forEach(message => this.log('pass', message)); } public fail( content: LogContent | string | LogContent[], isOptional: boolean = false, ) { const messages = Array.isArray(content) ? content : [content]; messages.forEach(message => { this.log(isOptional ? 'fail' : 'optionalFail', message); }); } }