Skip to content

Commit d1571d6

Browse files
committed
Eslint fix
1 parent 2ed2cd7 commit d1571d6

11 files changed

Lines changed: 204 additions & 90 deletions

File tree

packages/app/src/app.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ export class WebdriverIODevtoolsApplication extends Element {
7171
this.requestUpdate()
7272
}
7373

74-
#clearExecutionData({ detail }: { detail?: { uid?: string; entryType?: 'suite' | 'test' } }) {
74+
#clearExecutionData({
75+
detail
76+
}: {
77+
detail?: { uid?: string; entryType?: 'suite' | 'test' }
78+
}) {
7579
this.dataManager.clearExecutionData(detail?.uid, detail?.entryType)
7680
}
7781

packages/app/src/components/sidebar/constants.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export const DEFAULT_CAPABILITIES: RunCapabilities = {
1616

1717
export const FRAMEWORK_CAPABILITIES: Record<string, RunCapabilities> = {
1818
cucumber: { canRunSuites: true, canRunTests: false, canRunAll: true },
19-
'nightwatch-cucumber': { canRunSuites: true, canRunTests: false, canRunAll: false },
19+
'nightwatch-cucumber': {
20+
canRunSuites: true,
21+
canRunTests: false,
22+
canRunAll: false
23+
},
2024
nightwatch: { canRunSuites: true, canRunTests: true, canRunAll: false }
2125
}

packages/app/src/components/sidebar/explorer.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ import { consume } from '@lit/context'
55
import type { TestStats, SuiteStats } from '@wdio/reporter'
66
import type { Metadata } from '@wdio/devtools-service/types'
77
import { repeat } from 'lit/directives/repeat.js'
8-
import {
9-
suiteContext,
10-
metadataContext
11-
} from '../../controller/context.js'
8+
import { suiteContext, metadataContext } from '../../controller/context.js'
129
import type {
1310
TestEntry,
1411
RunCapabilities,
@@ -419,7 +416,10 @@ export class DevtoolsSidebarExplorer extends CollapseableEntry {
419416
// For suites with no explicit terminal state, derive from children.
420417
// A suite with state=undefined or state=pending that has no terminal
421418
// children yet is still in-progress — don't show PASSED prematurely.
422-
if ('tests' in entry && (state == null || state === 'pending' || state === 'running')) {
419+
if (
420+
'tests' in entry &&
421+
(state === null || state === 'pending' || state === 'running')
422+
) {
423423
const allDescendants = [...entry.tests, ...entry.suites]
424424
if (allDescendants.length > 0) {
425425
const allTerminal = allDescendants.every(
@@ -466,7 +466,9 @@ export class DevtoolsSidebarExplorer extends CollapseableEntry {
466466
// backend runner can distinguish it from a scenario/spec-level suite and
467467
// avoid applying a --name filter that would match no scenarios.
468468
const hasChildSuites = entry.suites && entry.suites.length > 0
469-
const derivedType = hasChildSuites ? 'feature' : ((entry as any).type || 'suite')
469+
const derivedType = hasChildSuites
470+
? 'feature'
471+
: (entry as any).type || 'suite'
470472
return {
471473
uid: entry.uid,
472474
label: entry.title,
@@ -521,18 +523,32 @@ export class DevtoolsSidebarExplorer extends CollapseableEntry {
521523
</h3>
522524
<nav class="flex ml-auto">
523525
<button
524-
class="p-1 rounded text-sm group ${this.#getRunCapabilities().canRunAll ? 'hover:bg-toolbarHoverBackground' : 'opacity-30 cursor-not-allowed'}"
526+
class="p-1 rounded text-sm group ${this.#getRunCapabilities()
527+
.canRunAll
528+
? 'hover:bg-toolbarHoverBackground'
529+
: 'opacity-30 cursor-not-allowed'}"
525530
?disabled=${!this.#getRunCapabilities().canRunAll}
526531
@click="${() => this.#runAllSuites()}"
527532
>
528-
<icon-mdi-play class="${this.#getRunCapabilities().canRunAll ? 'group-hover:text-chartsGreen' : ''}"></icon-mdi-play>
533+
<icon-mdi-play
534+
class="${this.#getRunCapabilities().canRunAll
535+
? 'group-hover:text-chartsGreen'
536+
: ''}"
537+
></icon-mdi-play>
529538
</button>
530539
<button
531-
class="p-1 rounded text-sm group ${this.#getRunCapabilities().canRunAll ? 'hover:bg-toolbarHoverBackground' : 'opacity-30 cursor-not-allowed'}"
540+
class="p-1 rounded text-sm group ${this.#getRunCapabilities()
541+
.canRunAll
542+
? 'hover:bg-toolbarHoverBackground'
543+
: 'opacity-30 cursor-not-allowed'}"
532544
?disabled=${!this.#getRunCapabilities().canRunAll}
533545
@click="${() => this.#stopActiveRun()}"
534546
>
535-
<icon-mdi-stop class="${this.#getRunCapabilities().canRunAll ? 'group-hover:text-chartsRed' : ''}"></icon-mdi-stop>
547+
<icon-mdi-stop
548+
class="${this.#getRunCapabilities().canRunAll
549+
? 'group-hover:text-chartsRed'
550+
: ''}"
551+
></icon-mdi-stop>
536552
</button>
537553
<button
538554
class="p-1 rounded hover:bg-toolbarHoverBackground text-sm group"

packages/app/src/components/workbench/actions.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import { customElement } from 'lit/decorators.js'
44
import { consume } from '@lit/context'
55

66
import type { CommandLog } from '@wdio/devtools-service/types'
7-
import {
8-
mutationContext,
9-
commandContext
10-
} from '../../controller/context.js'
7+
import { mutationContext, commandContext } from '../../controller/context.js'
118

129
import '~icons/mdi/pencil.js'
1310
import '~icons/mdi/family-tree.js'

packages/app/src/components/workbench/source.ts

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,20 @@ export class DevtoolsSource extends Element {
3232
.cm-content {
3333
padding: 0 !important;
3434
}
35+
36+
.source-container {
37+
width: 100%;
38+
height: 100%;
39+
}
3540
`
3641
]
3742

3843
@consume({ context: sourceContext, subscribe: true })
3944
sources: Record<string, string> = {}
4045

46+
#editorView?: EditorView
47+
#activeFile?: string
48+
4149
connectedCallback(): void {
4250
super.connectedCallback()
4351
window.addEventListener(
@@ -46,49 +54,82 @@ export class DevtoolsSource extends Element {
4654
)
4755
}
4856

49-
#renderEditor(filePath: string, highlightLine?: number) {
50-
if (!this.sources) {
57+
disconnectedCallback(): void {
58+
super.disconnectedCallback()
59+
this.#editorView?.destroy()
60+
this.#editorView = undefined
61+
}
62+
63+
updated() {
64+
const sourceFileNames = Object.keys(this.sources || {})
65+
if (sourceFileNames.length === 0) {
5166
return
5267
}
53-
const source = this.sources[filePath]
68+
// Mount or refresh the editor for the first source file
69+
this.#mountEditor(sourceFileNames[0])
70+
}
71+
72+
#mountEditor(filePath: string, highlightLine?: number) {
73+
const source = this.sources?.[filePath]
5474
if (!source) {
5575
return
5676
}
5777

5878
const container =
59-
this.shadowRoot?.querySelector('section') ||
60-
this.shadowRoot?.querySelector('.cm-editor')
79+
this.shadowRoot?.querySelector<HTMLElement>('.source-container')
6180
if (!container) {
6281
return
6382
}
6483

84+
// Reuse the existing editor if the file hasn't changed
85+
if (this.#editorView && this.#activeFile === filePath) {
86+
if (highlightLine && highlightLine > 0) {
87+
this.#scrollToLine(this.#editorView, highlightLine)
88+
}
89+
return
90+
}
91+
92+
// Destroy previous editor instance before creating a new one
93+
this.#editorView?.destroy()
94+
6595
const opts: EditorViewConfig = {
6696
root: this.shadowRoot!,
6797
extensions: [basicSetup, javascript(), oneDark],
6898
doc: source,
69-
selection: { anchor: 4 }
99+
parent: container
70100
}
71-
const editorView = new EditorView(opts)
72-
container.replaceWith(editorView.dom)
101+
this.#editorView = new EditorView(opts)
102+
this.#activeFile = filePath
73103

74104
if (highlightLine && highlightLine > 0) {
75-
try {
76-
const lineInfo = editorView.state.doc.line(highlightLine)
77-
requestAnimationFrame(() => {
78-
editorView.dispatch({
79-
selection: { anchor: lineInfo.from },
80-
effects: EditorView.scrollIntoView(lineInfo.from, { y: 'center' })
81-
})
105+
this.#scrollToLine(this.#editorView, highlightLine)
106+
}
107+
}
108+
109+
#scrollToLine(editorView: EditorView, line: number) {
110+
try {
111+
const lineInfo = editorView.state.doc.line(line)
112+
requestAnimationFrame(() => {
113+
editorView.dispatch({
114+
selection: { anchor: lineInfo.from },
115+
effects: EditorView.scrollIntoView(lineInfo.from, { y: 'center' })
82116
})
83-
} catch {
84-
/* ignore */
85-
}
117+
})
118+
} catch {
119+
/* ignore out-of-range line numbers */
86120
}
87121
}
88122

89-
#highlightCallSource(ev: CustomEvent<string>) {
90-
const [filePath, line] = ev.detail.split(':')
91-
this.#renderEditor(filePath, parseInt(line, 10))
123+
#highlightCallSource(ev: Event) {
124+
const [filePath, line] = (ev as CustomEvent<string>).detail.split(':')
125+
// If the source for this file is already loaded, mount and scroll immediately
126+
if (this.sources?.[filePath]) {
127+
this.#mountEditor(filePath, parseInt(line, 10))
128+
} else {
129+
// Source not yet available — will be mounted in updated() once it arrives;
130+
// store desired highlight so we can apply it then.
131+
this.#activeFile = filePath
132+
}
92133
this.closest('wdio-devtools-tabs')?.activateTab('Source')
93134
}
94135

@@ -98,8 +139,7 @@ export class DevtoolsSource extends Element {
98139
return html`<wdio-devtools-placeholder></wdio-devtools-placeholder>`
99140
}
100141

101-
this.#renderEditor(sourceFileNames[0])
102-
return html` <section class="p-2">loading...</section> `
142+
return html`<div class="source-container"></div>`
103143
}
104144
}
105145

packages/app/src/controller/DataManager.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { createContext, ContextProvider } from '@lit/context'
22
import type { ReactiveController, ReactiveControllerHost } from 'lit'
3-
import type { Metadata, CommandLog, TraceLog } from '@wdio/devtools-service/types'
3+
import type {
4+
Metadata,
5+
CommandLog,
6+
TraceLog
7+
} from '@wdio/devtools-service/types'
48

59
import {
610
mutationContext,
@@ -12,7 +16,11 @@ import {
1216
sourceContext,
1317
suiteContext
1418
} from './context.js'
15-
import type { TestStatsFragment, SuiteStatsFragment, SocketMessage } from './types.js'
19+
import type {
20+
TestStatsFragment,
21+
SuiteStatsFragment,
22+
SocketMessage
23+
} from './types.js'
1624

1725
const CACHE_ID = 'wdio-trace-cache'
1826

@@ -117,13 +125,12 @@ export class DataManagerController implements ReactiveController {
117125
state: 'running',
118126
start: new Date(),
119127
end: undefined,
120-
tests:
121-
(s.tests?.map((test) => ({
122-
...test,
123-
state: 'pending',
124-
start: new Date(),
125-
end: undefined
126-
})) ?? []) as TestStatsFragment[],
128+
tests: (s.tests?.map((test) => ({
129+
...test,
130+
state: 'pending',
131+
start: new Date(),
132+
end: undefined
133+
})) ?? []) as TestStatsFragment[],
127134
suites: s.suites?.map(markAllAsRunning) || []
128135
}
129136
}
@@ -162,15 +169,13 @@ export class DataManagerController implements ReactiveController {
162169
state: 'running',
163170
start: runStart,
164171
end: undefined,
165-
tests:
166-
(suiteNode.tests?.map((test) => ({
167-
...test,
168-
state: 'pending',
169-
start: runStart,
170-
end: undefined
171-
})) ?? []) as TestStatsFragment[],
172-
suites:
173-
suiteNode.suites?.map(markSuiteTreeAsRunning) || []
172+
tests: (suiteNode.tests?.map((test) => ({
173+
...test,
174+
state: 'pending',
175+
start: runStart,
176+
end: undefined
177+
})) ?? []) as TestStatsFragment[],
178+
suites: suiteNode.suites?.map(markSuiteTreeAsRunning) || []
174179
})
175180

176181
return {
@@ -437,7 +442,10 @@ export class DataManagerController implements ReactiveController {
437442

438443
// Derive the suite's own state from its updated children so that
439444
// STATE_MAP['running'] no longer produces a spinner after stop.
440-
const allTests = [...(updatedTests || []), ...(updatedNestedSuites || [])]
445+
const allTests = [
446+
...(updatedTests || []),
447+
...(updatedNestedSuites || [])
448+
]
441449
const hasFailed = allTests.some((t) => t?.state === 'failed')
442450
const hasRunning = allTests.some((t) => !t?.end)
443451
const derivedState: SuiteStatsFragment['state'] = hasRunning
@@ -598,7 +606,7 @@ export class DataManagerController implements ReactiveController {
598606
// Treat incoming state=undefined the same as pending — both mean the backend
599607
// hasn't assigned a terminal state yet.
600608
const incomingStateIsPendingOrUnset =
601-
incoming.state === 'pending' || incoming.state == null
609+
incoming.state === 'pending' || incoming.state === null
602610

603611
const allChildren = [...(mergedTests || []), ...(mergedSuites || [])]
604612
// Treat children with undefined/null state as in-progress (not yet terminal).
@@ -607,9 +615,11 @@ export class DataManagerController implements ReactiveController {
607615
(child) =>
608616
child?.state === 'running' ||
609617
child?.state === 'pending' ||
610-
child?.state == null
618+
child?.state === null
619+
)
620+
const hasFailedChildren = allChildren.some(
621+
(child) => child?.state === 'failed'
611622
)
612-
const hasFailedChildren = allChildren.some((child) => child?.state === 'failed')
613623
const hasChildren = allChildren.length > 0
614624

615625
// Only derive 'passed' when ALL children have reached a terminal state.
@@ -629,14 +639,20 @@ export class DataManagerController implements ReactiveController {
629639
existing.state === 'running' && incomingStateIsPendingOrUnset
630640

631641
const derivedCompletedState: SuiteStatsFragment['state'] | undefined =
632-
allChildrenTerminal ? (hasFailedChildren ? 'failed' : 'passed') : undefined
642+
allChildrenTerminal
643+
? hasFailedChildren
644+
? 'failed'
645+
: 'passed'
646+
: undefined
633647

634648
return {
635649
...existing,
636650
...incomingProps,
637651
...(keepRunningState && hasInProgressChildren
638652
? { state: 'running' as const }
639-
: incomingStateIsPendingOrUnset && !hasInProgressChildren && derivedCompletedState
653+
: incomingStateIsPendingOrUnset &&
654+
!hasInProgressChildren &&
655+
derivedCompletedState
640656
? { state: derivedCompletedState }
641657
: {}),
642658
tests: mergedTests,
@@ -727,5 +743,3 @@ export class DataManagerController implements ReactiveController {
727743
this.suitesContextProvider.setValue(traceFile.suites || [])
728744
}
729745
}
730-
731-

0 commit comments

Comments
 (0)