Skip to content

Commit 6fb302a

Browse files
authored
Merge pull request #425 from gemini-testing/HERMIONE-303.dynamic_grouping
feat: add ability to group tests by keys from meta of tests
2 parents c68f9cd + 5fd3526 commit 6fb302a

File tree

50 files changed

+1197
-681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1197
-681
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ directory.
5454
* **errorPatterns** (optional) - `Array` - error message patterns are used:
5555

5656
* to show more understandable information about matched error;
57-
* in 'Group by error' mode.
57+
* in 'Group by' mode with selected 'error' key.
5858

5959
Array elements must be one of the types:
6060

@@ -66,7 +66,7 @@ directory.
6666
* *name* of error pattern will be displayed as title of error message and original error message will be hidden under details;
6767
* *hint* of error pattern will be displayed after error *stack* field. Can be specified as html string. For example, `<div>some-useful-hint</div>`.
6868

69-
In 'Group by error' mode test will be associated with group if test error matches on group error pattern. New group will be created if test cannot be associated with existing groups.
69+
In 'Group by' mode with selected 'error' key test will be associated with group if test error matches on group error pattern. New group will be created if test cannot be associated with existing groups.
7070

7171
* **metaInfoBaseUrls** (optional) `Object` - base paths for making link from Meta-info values. Object option must be Meta-info's key and value must be `String`. For example, {'file': 'base/path'}.
7272
* **saveFormat** (**DEPRECATED**, optional) `String` - allows to specify the format, in which the results will be saved. Available values are:

lib/constants/group-tests.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
exports.SECTIONS = {
2+
RESULT: 'result',
3+
META: 'meta'
4+
};
5+
exports.ERROR_KEY = 'error';
6+
exports.RESULT_KEYS = [exports.ERROR_KEY];
7+
exports.KEY_DELIMITER = '.';

lib/static/components/bottom-progress-bar/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
import {extend} from 'lodash';
3+
import {extend, isNumber} from 'lodash';
44
import React from 'react';
55
import {connect} from 'react-redux';
66

@@ -15,6 +15,10 @@ const BottomProgressBar = (props) => {
1515
const currentRootSuiteIdx = suiteIdsIndexMap[currentRootSuiteId];
1616
const percent = 100 / (visibleRootSuiteIds.length - 1) * currentRootSuiteIdx;
1717

18+
if (!isNumber(currentRootSuiteIdx)) {
19+
return null;
20+
}
21+
1822
return (
1923
<div className="bottom-progress-bar">
2024
<div className='bottom-progress-bar__progress-container'>

lib/static/components/controls/common-controls.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {connect} from 'react-redux';
44
import {capitalize} from 'lodash';
55
import * as actions from '../../modules/actions';
66
import ControlButton from './control-button';
7-
import ControlSelect from './control-select';
7+
import ControlSelect from './selects/control';
8+
import GroupTestsSelect from './selects/group-tests';
89
import BaseHostInput from './base-host-input';
910
import MenuBar from './menu-bar';
1011
import viewModes from '../../../constants/view-modes';
@@ -49,6 +50,7 @@ class ControlButtons extends Component {
4950
handler={actions.expandRetries}
5051
/>
5152
</div>
53+
<GroupTestsSelect />
5254
<ControlButton
5355
label="Show skipped"
5456
isActive={view.showSkipped}
@@ -63,11 +65,6 @@ class ControlButtons extends Component {
6365
})}
6466
extendClassNames="diff-mode"
6567
/>
66-
<ControlButton
67-
label="Group by error"
68-
isActive={Boolean(view.groupByError)}
69-
handler={actions.toggleGroupByError}
70-
/>
7168
<BaseHostInput/>
7269
<MenuBar />
7370
</div>

lib/static/components/controls/control-select/index.js renamed to lib/static/components/controls/selects/control.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ export default class ControlSelect extends Component {
3030
}));
3131

3232
const className = classNames(
33-
'control-select',
33+
'select',
34+
'select_type_control',
3435
extendClassNames
3536
);
3637

3738
return (
3839
<div className={className}>
39-
<Label className="control-select__label">{label}</Label>
40+
<Label className="select__label">{label}</Label>
4041
<Dropdown
41-
className="control-select__dropdown"
42+
className="select__dropdown"
4243
selection
4344
options={formattedOpts}
4445
value={value}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React, {Component, Fragment} from 'react';
2+
import {bindActionCreators} from 'redux';
3+
import {connect} from 'react-redux';
4+
import PropTypes from 'prop-types';
5+
import {Label, Dropdown} from 'semantic-ui-react';
6+
import classNames from 'classnames';
7+
import {isEmpty} from 'lodash';
8+
9+
import * as actions from '../../../modules/actions';
10+
import {groupedTestsType} from '../../group-tests/prop-types';
11+
import {SECTIONS, KEY_DELIMITER} from '../../../../constants/group-tests';
12+
import {getParsedKeyToGroupTestsBy} from '../../../modules/selectors/grouped-tests';
13+
14+
import './index.styl';
15+
16+
class GroupTestsSelect extends Component {
17+
static propTypes = {
18+
actions: PropTypes.object.isRequired,
19+
// from store
20+
keyToGroupTestsBy: PropTypes.string.isRequired,
21+
groupedTests: groupedTestsType.isRequired,
22+
selectedGroupSection: PropTypes.string,
23+
selectedGroupKey: PropTypes.string
24+
}
25+
26+
_groupTestsByKey = (_, dom) => {
27+
if (dom.value !== this.props.keyToGroupTestsBy) {
28+
this.props.actions.groupTestsByKey(dom.value);
29+
}
30+
}
31+
32+
_renderSection(sectionName) {
33+
const {groupedTests} = this.props;
34+
const keys = groupedTests[sectionName].allKeys;
35+
36+
if (isEmpty(keys)) {
37+
return null;
38+
}
39+
40+
return (
41+
<Fragment key={sectionName}>
42+
<Dropdown.Divider/>
43+
<Dropdown.Header content={sectionName} />
44+
<Dropdown.Divider/>
45+
{keys.map(key => {
46+
const id = getGroupElemId(sectionName, key);
47+
const isActive = id === this.props.keyToGroupTestsBy;
48+
49+
return <Dropdown.Item key={id} value={id} active={isActive} onClick={this._groupTestsByKey}>{key}</Dropdown.Item>;
50+
})}
51+
</Fragment>
52+
);
53+
}
54+
55+
render() {
56+
const {selectedGroupKey} = this.props;
57+
const className = classNames(
58+
'select',
59+
'select_type_group'
60+
);
61+
62+
return (
63+
<div className={className}>
64+
<Label className="select__label">Group by</Label>
65+
<Dropdown
66+
className="select__dropdown selection"
67+
value={selectedGroupKey}
68+
text={selectedGroupKey}
69+
onChange={this._groupTestsByKey}
70+
placeholder="select key"
71+
clearable={Boolean(selectedGroupKey)}
72+
>
73+
<Dropdown.Menu>
74+
{Object.values(SECTIONS).map((sectionName) => this._renderSection(sectionName))}
75+
</Dropdown.Menu>
76+
</Dropdown>
77+
</div>
78+
);
79+
}
80+
}
81+
82+
export default connect(
83+
(state) =>{
84+
const {view: {keyToGroupTestsBy}, groupedTests} = state;
85+
const [selectedGroupSection, selectedGroupKey] = getParsedKeyToGroupTestsBy(state);
86+
87+
return {keyToGroupTestsBy, groupedTests, selectedGroupSection, selectedGroupKey};
88+
},
89+
(dispatch) => ({actions: bindActionCreators(actions, dispatch)})
90+
)(GroupTestsSelect);
91+
92+
function getGroupElemId(groupName, groupKey) {
93+
return `${groupName}${KEY_DELIMITER}${groupKey}`;
94+
}
Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
.control-select
1+
.select
22
display: inline-flex
33
margin-right: 15px
44
margin-bottom: 15px
55

6-
.control-select__label
6+
.select__label
77
font-size: 11px
88
margin: 0
99
padding: 0 5px
@@ -13,12 +13,13 @@
1313
border-top-right-radius: 0
1414
border-bottom-right-radius: 0
1515

16-
.control-select__dropdown.ui.dropdown
16+
.select__dropdown.ui.dropdown
1717
min-height: 25px
18-
min-width: 60px
18+
min-width: 70px
1919
font-size: 11px
2020
line-height: 13px
2121
padding: 5px
22+
padding-right: 25px
2223
border: 1px solid #ccc
2324
border-radius: 2px
2425
border-top-left-radius: 0
@@ -32,13 +33,26 @@
3233
.menu
3334
border-color: #ffd947
3435

35-
.icon
36-
top: 50%
37-
right: 10px
36+
.icon.dropdown
3837
padding: 0
3938
margin: 0
40-
transform: translateY(-50%)
39+
line-height: initial
4140

4241
&.diff-mode
43-
.control-select__dropdown.ui.dropdown
42+
.select__dropdown.ui.dropdown
4443
min-width: 90px
44+
45+
&.select_type_group
46+
.select__dropdown.ui.dropdown
47+
min-width: 110px
48+
49+
.menu > .header
50+
margin: 0
51+
padding: 0 0 0 5px
52+
border-bottom: 0
53+
54+
.menu > .divider
55+
margin: 5px 0
56+
57+
.menu > .item
58+
padding-left: 10px !important

lib/static/components/error-groups/list.js

Lines changed: 0 additions & 56 deletions
This file was deleted.

lib/static/components/error-groups/item.js renamed to lib/static/components/group-tests/item.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import classNames from 'classnames';
44

55
import Suites from '../suites';
66

7-
export default class ErrorGroupsItem extends Component {
7+
export default class GroupTestsItem extends Component {
88
static propTypes = {
99
group: PropTypes.object.isRequired,
1010
isActive: PropTypes.bool.isRequired,
@@ -13,24 +13,24 @@ export default class ErrorGroupsItem extends Component {
1313

1414
render() {
1515
const {group, isActive, onClick} = this.props;
16-
const {name, pattern, count} = group;
16+
const {name, pattern, testCount} = group;
1717

1818
const body = isActive ? (
19-
<div className="error-group__body">
19+
<div className="tests-group__body">
2020
<Suites />
2121
</div>
2222
) : null;
2323

2424
const className = classNames(
25-
'error-group',
26-
{'error-group_collapsed': !isActive}
25+
'tests-group',
26+
{'tests-group_collapsed': !isActive}
2727
);
2828

2929
return (
3030
<div className={className}>
31-
<div className="error-group__title" onClick={onClick} title={pattern}>
32-
<span className="error-group__name">{name}</span>
33-
<span className="error-group__count">&nbsp;({count})</span>
31+
<div className="tests-group__title" onClick={onClick} title={pattern}>
32+
<span className="tests-group__name">{name}</span>
33+
<span className="tests-group__count">&nbsp;({testCount})</span>
3434
</div>
3535
{body}
3636
</div>

0 commit comments

Comments
 (0)