Skip to content

Commit 5567766

Browse files
committed
enhancing ux around suite iteration and error reporting
1 parent 00b662a commit 5567766

File tree

19 files changed

+138
-72
lines changed

19 files changed

+138
-72
lines changed

packages/selenium-ide/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@seleniumhq/selenium-ide",
3-
"version": "4.0.0-alpha.27",
3+
"version": "4.0.0-alpha.28",
44
"private": true,
55
"description": "Selenium IDE electron app",
66
"author": "Todd <[email protected]>",
@@ -107,7 +107,7 @@
107107
"@seleniumhq/code-export-ruby-rspec": "^4.0.0-alpha.0",
108108
"@seleniumhq/side-code-export": "^4.0.0-alpha.2",
109109
"@seleniumhq/get-driver": "^4.0.0-alpha.1",
110-
"@seleniumhq/side-api": "^4.0.0-alpha.13",
110+
"@seleniumhq/side-api": "^4.0.0-alpha.14",
111111
"@seleniumhq/side-model": "^4.0.0-alpha.2",
112112
"@seleniumhq/side-plugin-example": "^4.0.0-alpha.1",
113113
"@seleniumhq/side-runtime": "^4.0.0-alpha.15",

packages/selenium-ide/src/browser/windows/ProjectEditor/components/Drawer/RenamableListItem.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ import ListItem, { ListItemProps } from '@mui/material/ListItem'
22
import ListItemButton from '@mui/material/ListItemButton'
33
import ListItemText from '@mui/material/ListItemText'
44
import TextField from '@mui/material/TextField'
5+
import { CommandState } from '@seleniumhq/side-runtime'
56
import React, { FC } from 'react'
7+
import CommandOverlay from '../../tabs/Tests/TestCommandOverlay'
68

79
export interface TestListProps {
810
id: string
911
name: string
1012
rename: (id: string, name: string) => void
1113
selected: boolean
1214
setSelected: (id: string) => void
15+
state?: CommandState
1316
}
1417

1518
const RenamableListItem: FC<ListItemProps & TestListProps> = ({
@@ -18,6 +21,7 @@ const RenamableListItem: FC<ListItemProps & TestListProps> = ({
1821
rename,
1922
selected,
2023
setSelected,
24+
state = null,
2125
...props
2226
}) => {
2327
const [renaming, setRenaming] = React.useState(false)
@@ -48,6 +52,7 @@ const RenamableListItem: FC<ListItemProps & TestListProps> = ({
4852
) : (
4953
<ListItemButton disableRipple selected={selected}>
5054
<ListItemText>{name}</ListItemText>
55+
<CommandOverlay state={state} />
5156
</ListItemButton>
5257
)}
5358
</ListItem>

packages/selenium-ide/src/browser/windows/ProjectEditor/components/Drawer/index.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,45 @@ import SuitesDrawer from '../../tabs/Suites/SuitesDrawer'
77
import TestsDrawer from '../../tabs/Tests/TestsDrawer'
88
import ProjectDrawer from '../../tabs/Project/ProjectDrawer'
99

10-
interface SIDEDrawerProps extends Omit<DrawerWrapperProps, 'footerID' | 'header'> {
10+
interface SIDEDrawerProps
11+
extends Omit<DrawerWrapperProps, 'footerID' | 'header'> {
1112
session: CoreSessionData
1213
tab: TAB
1314
}
1415

1516
const SIDEDrawer: React.FC<SIDEDrawerProps> = ({ session, tab, ...props }) => {
1617
const {
1718
project: { suites, tests },
18-
state: { activeSuiteID, activeTestID, editor: { configSettingsGroup, suiteMode } },
19+
state: {
20+
activeSuiteID,
21+
activeTestID,
22+
editor: { configSettingsGroup, suiteMode },
23+
playback: {
24+
commands,
25+
testResults,
26+
}
27+
},
1928
} = session
2029
return (
2130
<>
2231
<TabPanel index={TESTS_TAB} value={tab}>
23-
<TestsDrawer activeTest={activeTestID} tests={tests} {...props} />
32+
<TestsDrawer
33+
activeTest={activeTestID}
34+
activeSuite={activeSuiteID}
35+
commandResults={commands}
36+
suites={suites}
37+
tests={tests}
38+
testResults={testResults}
39+
{...props}
40+
/>
2441
</TabPanel>
2542
<TabPanel index={SUITES_TAB} value={tab}>
26-
<SuitesDrawer activeSuite={activeSuiteID} suiteMode={suiteMode} suites={suites} {...props} />
43+
<SuitesDrawer
44+
activeSuite={activeSuiteID}
45+
suiteMode={suiteMode}
46+
suites={suites}
47+
{...props}
48+
/>
2749
</TabPanel>
2850
<TabPanel index={PROJECT_TAB} value={tab}>
2951
<ProjectDrawer configSettingsGroup={configSettingsGroup} {...props} />

packages/selenium-ide/src/browser/windows/ProjectEditor/tabs/Tests/CommandFields/CommandSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const CommandSelector: FC<CommandSelectorProps> = ({
5656
/>
5757

5858
<Tooltip
59-
className="flex-fixed ml-4 my-auto"
59+
className="flex-initial ml-4 my-auto"
6060
title={`${isDisabled ? 'En' : 'Dis'}able this command`}
6161
placement="top-end"
6262
>
@@ -69,7 +69,7 @@ const CommandSelector: FC<CommandSelectorProps> = ({
6969
</IconButton>
7070
</Tooltip>
7171
<Tooltip
72-
className="flex-fixed mx-2 my-auto"
72+
className="flex-initial mx-2 my-auto"
7373
title={commandData.description}
7474
placement="top-end"
7575
>

packages/selenium-ide/src/browser/windows/ProjectEditor/tabs/Tests/Controls.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import PlayButton from '../../components/Controls/PlayButton'
44
import RecordButton from '../../components/Controls/RecordButton'
55
import StopButton from '../../components/Controls/StopButton'
66
import PauseButton from '../../components/Controls/PauseButton'
7+
import PlayListButton from '../../components/Controls/PlayListButton'
78

89
export interface TestControlsProps {
910
state: StateShape
@@ -15,6 +16,7 @@ const TestControls: FC<TestControlsProps> = ({ state }) => {
1516
return (
1617
<>
1718
<PlayButton state={state} />
19+
{!state.activeSuiteID ? null : <PlayListButton state={state} />}
1820
<RecordButton />
1921
</>
2022
)

packages/selenium-ide/src/browser/windows/ProjectEditor/tabs/Tests/TestsDrawer.tsx

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,64 @@
11
import List from '@mui/material/List'
2-
import { TestShape } from '@seleniumhq/side-model'
2+
import FormControl from '@mui/material/FormControl'
3+
import MenuItem from '@mui/material/MenuItem'
4+
import Select from '@mui/material/Select'
5+
import { SuiteShape, TestShape } from '@seleniumhq/side-model'
36
import React, { FC } from 'react'
47
import Drawer from '../../components/Drawer/Wrapper'
58
import EditorToolbar from '../../components/Drawer/EditorToolbar'
69
import RenamableListItem from '../../components/Drawer/RenamableListItem'
710
import TestNewDialog from './TestNewDialog'
11+
import { StateShape } from '@seleniumhq/side-api'
812
// import TestNewDialog from '../Tests/TestNewDialog'
913

1014
export interface TestListProps {
15+
activeSuite: string
1116
activeTest: string
17+
commandResults: StateShape['playback']['commands']
1218
open: boolean
1319
setOpen: (b: boolean) => void
20+
suites: SuiteShape[]
1421
tests: TestShape[]
22+
testResults: StateShape['playback']['testResults']
1523
}
1624

1725
const {
18-
state: { setActiveTest: setSelected },
26+
state: { setActiveTest: setSelected, setActiveSuite },
1927
tests: { rename },
2028
} = window.sideAPI
2129

22-
const TestList: FC<TestListProps> = ({ activeTest, open, setOpen, tests }) => {
30+
const TestList: FC<TestListProps> = ({
31+
activeSuite,
32+
activeTest,
33+
commandResults,
34+
open,
35+
setOpen,
36+
suites,
37+
tests,
38+
testResults,
39+
}) => {
2340
const [confirmNew, setConfirmNew] = React.useState(false)
41+
const testList = activeSuite
42+
? suites
43+
.find((s) => s.id === activeSuite)
44+
?.tests.map((id) => tests.find((t) => t.id === id) as TestShape) ??
45+
tests
46+
: tests
47+
const safeSuiteID = suites.find((s) => s.id === activeSuite)?.id ?? ''
2448

2549
return (
2650
<Drawer
51+
className="flex flex-col h-100"
2752
footerID="command-editor"
2853
open={open}
2954
header="Select Test"
3055
setOpen={setOpen}
3156
>
3257
<TestNewDialog confirmNew={confirmNew} setConfirmNew={setConfirmNew} />
3358
<List
59+
className="flex-1"
3460
dense
35-
sx={{ borderColor: 'primary.main' }}
61+
sx={{ borderColor: 'primary.main', paddingBottom: '48px' }}
3662
subheader={
3763
<EditorToolbar
3864
onAdd={async () => {
@@ -56,23 +82,54 @@ const TestList: FC<TestListProps> = ({ activeTest, open, setOpen, tests }) => {
5682
/>
5783
}
5884
>
59-
{tests
85+
{testList
6086
.slice()
6187
.sort((a, b) => a.name.localeCompare(b.name))
62-
.map(({ id, name }) => (
63-
<RenamableListItem
64-
id={id}
65-
key={id}
66-
name={name}
67-
onContextMenu={() => {
68-
window.sideAPI.menus.open('testManager', [id]);
69-
}}
70-
rename={rename}
71-
selected={id === activeTest}
72-
setSelected={setSelected}
73-
/>
74-
))}
88+
.map(({ id, name }) => {
89+
const lastCommand = testResults[id]?.lastCommand
90+
return (
91+
<RenamableListItem
92+
id={id}
93+
key={id}
94+
name={name}
95+
onContextMenu={() => {
96+
window.sideAPI.menus.open('testManager', [id])
97+
}}
98+
rename={rename}
99+
selected={id === activeTest}
100+
setSelected={setSelected}
101+
state={commandResults[lastCommand]?.state}
102+
/>
103+
)
104+
})}
75105
</List>
106+
<FormControl size="small">
107+
<Select
108+
MenuProps={{
109+
anchorOrigin: {
110+
horizontal: 'center',
111+
vertical: 'top',
112+
},
113+
transformOrigin: {
114+
horizontal: 'center',
115+
vertical: 'bottom',
116+
},
117+
}}
118+
className="flex-initial"
119+
displayEmpty
120+
onChange={(e) => setActiveSuite(e.target.value as string)}
121+
placeholder="[All tests]"
122+
sx={{ bottom: 0 }}
123+
value={safeSuiteID}
124+
>
125+
<MenuItem value="">[All tests]</MenuItem>
126+
{suites.map((s) => (
127+
<MenuItem key={s.id} value={s.id}>
128+
{s.name}
129+
</MenuItem>
130+
))}
131+
</Select>
132+
</FormControl>
76133
</Drawer>
77134
)
78135
}

packages/selenium-ide/src/browser/windows/ProjectEditor/tabs/Tests/TestsTab.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Paper from '@mui/material/Paper'
22
import { getActiveCommand, getActiveTest } from '@seleniumhq/side-api/dist/helpers/getActiveData'
33
import { useHeightFromElement } from 'browser/helpers/useHeightFromElement'
4-
import React, { useEffect } from 'react'
4+
import React from 'react'
55
import CommandEditor from './TestCommandEditor'
66
import CommandList from './TestCommandList'
77
import CommandTable from './TestCommandTable'
@@ -35,12 +35,6 @@ const TestsTab: React.FC<{
3535
const isTableWidth = useMediaQuery('only screen and (min-width: 600px)')
3636
const CommandsComponent = isTableWidth ? CommandTable : CommandList
3737
const bottomOffset = useHeightFromElement('command-editor')
38-
useEffect(() => {
39-
window.sideAPI.state.openTestEditor()
40-
return () => {
41-
window.sideAPI.state.closeTestEditor()
42-
}
43-
}, [])
4438

4539
if (activeTestID === loadingID) {
4640
return <NoTestFound />

packages/selenium-ide/src/main/session/controllers/Playback/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ export default class PlaybackController extends BaseController {
181181
handlePlaybackStateChanged = (
182182
e: PlaybackEventShapes['PLAYBACK_STATE_CHANGED']
183183
) => {
184-
console.debug(`Playing state changed ${e.state}`)
184+
const testName = this.session.tests.getByID(this.playingTest)?.name
185+
console.debug(`Playing state changed ${e.state} for test ${testName}`)
185186
switch (e.state) {
186187
case 'aborted':
187188
case 'errored':

packages/side-api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@seleniumhq/side-api",
3-
"version": "4.0.0-alpha.13",
3+
"version": "4.0.0-alpha.14",
44
"description": "Selenium IDE shared models",
55
"author": "Todd Tarsi <[email protected]>",
66
"homepage": "http://github.com/SeleniumHQ/selenium-ide",

packages/side-api/src/commands/projects/load.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { SuiteShape } from '@seleniumhq/side-model'
21
import { loadingID } from '../../constants/loadingID'
32
import { CoreSessionData, Mutator } from '../../types'
43

@@ -7,11 +6,6 @@ import { CoreSessionData, Mutator } from '../../types'
76
*/
87
export type Shape = (filepath: string) => Promise<CoreSessionData | null>
98

10-
const defaultSuite: Partial<SuiteShape> = {
11-
id: loadingID,
12-
name: 'Default',
13-
tests: [loadingID],
14-
}
159
export const mutator: Mutator<Shape> = (session, { result }) => {
1610
if (!result) {
1711
return session
@@ -21,14 +15,12 @@ export const mutator: Mutator<Shape> = (session, { result }) => {
2115
if (state) {
2216
return result
2317
}
24-
const firstSuite = project.suites?.[0] ?? defaultSuite
25-
const activeSuiteID = firstSuite.id
26-
const activeTestID = firstSuite.tests[0] ?? loadingID
18+
const activeTestID = project.tests[0]?.id ?? loadingID
2719
return {
2820
project,
2921
state: {
3022
...session.state,
31-
activeSuiteID,
23+
activeSuiteID: '',
3224
activeTestID,
3325
},
3426
}

0 commit comments

Comments
 (0)