@@ -5,14 +5,11 @@ import { consume } from '@lit/context'
55
66import { consoleLogContext } from '../../controller/DataManager.js'
77
8- import '~icons/mdi/chevron-right.js'
9- import '../placeholder.js'
10-
11- const BG : Record < ConsoleLogs [ 'type' ] , string > = {
12- warn : 'editorOverviewRulerWarningForeground' ,
13- info : 'editorOverviewRulerInfoForeground' ,
14- error : 'editorOverviewRulerErrorForeground' ,
15- log : 'panelBorder'
8+ const LOG_ICONS : Record < ConsoleLogs [ 'type' ] , string > = {
9+ log : '📄' ,
10+ info : 'ℹ️' ,
11+ warn : '⚠️' ,
12+ error : '❌'
1613}
1714
1815const SOURCE_COMPONENT = 'wdio-devtools-console-logs'
@@ -23,46 +20,192 @@ export class DevtoolsConsoleLogs extends Element {
2320 css `
2421 :host {
2522 display: flex;
26- width: 100%;
27- height: 100%;
23+ flex: 1;
2824 flex-direction: column;
29- padding: 5px;
30- min-height: 200px;
25+ background-color: var(--vscode-editor-background);
26+ min-height: 0;
27+ position: relative;
28+ }
29+
30+ .console-container {
31+ flex: 1;
32+ overflow-y: auto;
33+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
34+ font-size: 13px;
35+ line-height: 1.6;
36+ }
37+
38+ .log-entry {
39+ display: flex;
40+ align-items: flex-start;
41+ padding: 2px 8px;
42+ border-bottom: 1px solid rgba(128, 128, 128, 0.05);
43+ min-height: 22px;
44+ }
45+
46+ .log-entry:hover {
47+ background-color: rgba(255, 255, 255, 0.02);
48+ }
49+
50+ .log-entry.log-type-error {
51+ background-color: rgba(244, 135, 113, 0.03);
52+ }
53+
54+ .log-entry.log-type-warn {
55+ background-color: rgba(205, 151, 49, 0.03);
56+ }
57+
58+ .log-entry.log-type-info {
59+ background-color: rgba(14, 99, 156, 0.03);
60+ }
61+
62+ .log-time,
63+ .log-icon {
64+ flex-shrink: 0;
65+ }
66+
67+ .log-time {
68+ width: 45px;
69+ text-align: right;
70+ margin-right: 12px;
71+ font-size: 11px;
72+ opacity: 0.5;
73+ user-select: none;
74+ color: var(--vscode-editorLineNumber-foreground);
75+ line-height: 18px;
76+ }
77+
78+ .log-icon {
79+ margin-right: 8px;
80+ font-size: 14px;
81+ line-height: 18px;
82+ }
83+
84+ .log-prefix {
85+ flex-shrink: 0;
86+ color: var(--vscode-foreground);
87+ opacity: 0.8;
88+ margin-right: 4px;
89+ }
90+
91+ .log-content {
92+ flex: 1;
93+ min-width: 0;
94+ word-break: break-word;
95+ line-height: 18px;
96+ display: flex;
97+ align-items: baseline;
98+ }
99+
100+ .log-message {
101+ color: var(--vscode-foreground);
102+ white-space: pre-wrap;
103+ word-break: break-word;
104+ }
105+
106+ .log-entry.log-type-error .log-message {
107+ color: #f48771;
108+ }
109+
110+ .log-entry.log-type-warn .log-message {
111+ color: #cd9731;
112+ }
113+
114+ .log-entry.log-type-info .log-message {
115+ color: #75beff;
116+ }
117+
118+ .empty-state {
119+ position: absolute;
120+ inset: 0;
121+ display: flex;
122+ flex-direction: column;
123+ align-items: center;
124+ justify-content: center;
125+ gap: 12px;
126+ color: var(--vscode-descriptionForeground);
127+ }
128+
129+ .empty-state-icon {
130+ font-size: 48px;
131+ opacity: 0.3;
132+ }
133+
134+ .empty-state-text {
135+ font-size: 14px;
136+ opacity: 0.6;
31137 }
32138 `
33139 ]
34140
35141 @consume ( { context : consoleLogContext , subscribe : true } )
36142 logs : ConsoleLogs [ ] | undefined = undefined
37143
144+ get logCount ( ) : number {
145+ return this . logs ?. length || 0
146+ }
147+
148+ #startTime?: number
149+
150+ #formatElapsedTime( timestamp : number ) : string {
151+ if ( this . #startTime === undefined ) {
152+ this . #startTime = this . logs ?. [ 0 ] ?. timestamp ?? timestamp
153+ }
154+ const elapsed = ( timestamp - this . #startTime! ) / 1000
155+ return `${ elapsed . toFixed ( 1 ) } s`
156+ }
157+
158+ #formatArgs( args : any [ ] ) : string {
159+ if ( Array . isArray ( args ) ) {
160+ return args . map ( arg => {
161+ if ( typeof arg === 'string' ) return arg
162+ try {
163+ return JSON . stringify ( arg , null , 2 )
164+ } catch {
165+ return String ( arg )
166+ }
167+ } ) . join ( ' ' )
168+ }
169+ return String ( args )
170+ }
171+
38172 render ( ) {
39- if ( ! this . logs ) {
40- return html `< wdio-devtools-placeholder > </ wdio-devtools-placeholder > `
173+ if ( ! this . logs || this . logs . length === 0 ) {
174+ return html `
175+ < div class ="empty-state ">
176+ < div class ="empty-state-icon "> 📋</ div >
177+ < div class ="empty-state-text "> No console logs captured yet</ div >
178+ </ div >
179+ `
41180 }
42181
43- const logs = this . logs . length === 0 ? [ { args : '' } ] : this . logs
182+ if ( this . logs . length === 0 ) {
183+ return html `
184+ < div class ="empty-state ">
185+ < div class ="empty-state-icon "> 📋</ div >
186+ < div class ="empty-state-text "> No console logs captured yet</ div >
187+ </ div >
188+ `
189+ }
44190
45191 return html `
46- ${ Object . values ( logs ) . map (
47- ( log : any ) => html `
48- < dl class ="w-full flex grow-0 ">
49- < dt class ="flex ">
50- < icon-mdi-chevron-right
51- class ="text-base transition-transform block "
52- > </ icon-mdi-chevron-right >
53- ${ log . type
54- ? html `< span
55- class ="block bg-${ BG [
56- log . type
57- ] } rounded text-sm py-[1px] px-[5px] my-1 "
58- > ${ log . type } </ span
59- > `
192+ < div class ="console-container ">
193+ ${ this . logs . map ( ( log : any ) => {
194+ const icon = LOG_ICONS [ log . type ] || LOG_ICONS . log
195+ return html `
196+ < div class ="log-entry log-type- ${ log . type || 'log' } ">
197+ ${ log . timestamp
198+ ? html `< div class ="log-time "> ${ this . #formatElapsedTime( log . timestamp ) } </ div > `
60199 : nothing }
61- </ dt >
62- < dd class ="flex justify-center items-center mx-2 "> ${ log . args } </ dd >
63- </ dl >
64- `
65- ) }
200+ < div class ="log-icon "> ${ icon } </ div >
201+ < div class ="log-content ">
202+ ${ log . source === 'test' ? html `< span class ="log-prefix "> > > > </ span > ` : nothing }
203+ < span class ="log-message "> ${ this . #formatArgs( log . args ) } </ span >
204+ </ div >
205+ </ div >
206+ `
207+ } ) }
208+ </ div >
66209 `
67210 }
68211}
0 commit comments