Skip to content

Commit 8275b95

Browse files
committed
feat: add ability to mark matched results on selected group
1 parent 6fb302a commit 8275b95

File tree

11 files changed

+492
-66
lines changed

11 files changed

+492
-66
lines changed

lib/static/components/group-tests/item.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default class GroupTestsItem extends Component {
1313

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

1818
const body = isActive ? (
1919
<div className="tests-group__body">
@@ -30,7 +30,7 @@ export default class GroupTestsItem extends Component {
3030
<div className={className}>
3131
<div className="tests-group__title" onClick={onClick} title={pattern}>
3232
<span className="tests-group__name">{name}</span>
33-
<span className="tests-group__count">&nbsp;({testCount})</span>
33+
<span className="tests-group__count">&nbsp;({`tests: ${testCount}, runs: ${resultCount}`})</span>
3434
</div>
3535
{body}
3636
</div>

lib/static/components/group-tests/list.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ class GroupTestsList extends Component {
2727

2828
this.setState({activeGroupIndex}, () => {
2929
const groups = groupedTests[selectedGroupSection].byKey[selectedGroupKey];
30-
const {browserIds = []} = isActive ? groups[index] : {};
30+
const {browserIds = [], resultIds = []} = isActive ? groups[index] : {};
3131

32-
this.props.actions.toggleTestsGroup({browserIds, isActive});
32+
this.props.actions.toggleTestsGroup({browserIds, resultIds, isActive});
3333
});
3434
}
3535

lib/static/components/retry-switcher/item.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44
import {connect} from 'react-redux';
5+
import {get} from 'lodash';
56
import {isNoRefImageError, isAssertViewError} from '../../modules/utils';
67
import {ERROR} from '../../../constants/test-statuses';
78
import {isFailStatus} from '../../../common-utils';
@@ -14,31 +15,38 @@ class RetrySwitcherItem extends Component {
1415
title: PropTypes.string,
1516
// from store
1617
status: PropTypes.string.isRequired,
17-
attempt: PropTypes.number.isRequired
18+
attempt: PropTypes.number.isRequired,
19+
keyToGroupTestsBy: PropTypes.string.isRequired,
20+
matchedSelectedGroup: PropTypes.bool.isRequired
1821
}
1922

2023
render() {
21-
const {status, attempt, isActive, onClick, title} = this.props;
24+
const {status, attempt, isActive, onClick, title, keyToGroupTestsBy, matchedSelectedGroup} = this.props;
2225

2326
const className = classNames(
2427
'state-button',
2528
'tab-switcher__button',
2629
{[`tab-switcher__button_status_${status}`]: status},
27-
{'tab-switcher__button_active': isActive}
30+
{'tab-switcher__button_active': isActive},
31+
{'tab-switcher__button_non-matched': keyToGroupTestsBy && !matchedSelectedGroup}
2832
);
2933

3034
return <button title={title} className={className} onClick={onClick}>{attempt + 1}</button>;
3135
}
3236
}
3337

3438
export default connect(
35-
({tree}, {resultId}) => {
39+
({tree, view: {keyToGroupTestsBy}}, {resultId}) => {
3640
const result = tree.results.byId[resultId];
41+
const matchedSelectedGroup = get(tree.results.stateById[resultId], 'matchedSelectedGroup', false);
3742
const {status, attempt, error} = result;
3843

39-
return hasScreenAndAssertErrors(status, error)
40-
? {status: `${status}_${ERROR}`, attempt}
41-
: {status, attempt};
44+
return {
45+
status: hasScreenAndAssertErrors(status, error) ? `${status}_${ERROR}` : status,
46+
attempt,
47+
keyToGroupTestsBy,
48+
matchedSelectedGroup
49+
};
4250
}
4351
)(RetrySwitcherItem);
4452

lib/static/components/section/body/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, {Component} from 'react';
22
import {connect} from 'react-redux';
33
import {bindActionCreators} from 'redux';
4+
import {isNumber} from 'lodash';
45
import PropTypes from 'prop-types';
56
import RetrySwitcher from '../../retry-switcher';
67
import ControlButton from '../../controls/control-button';
@@ -98,10 +99,14 @@ class Body extends Component {
9899

99100
export default connect(
100101
({gui, running, view: {retryIndex: viewRetryIndex}, tree}, {browserId}) => {
101-
const {retryIndex: browserRetryIndex} = tree.browsers.stateById[browserId] || {};
102-
const retryIndex = typeof viewRetryIndex === 'number'
103-
? Math.min(viewRetryIndex, browserRetryIndex)
104-
: browserRetryIndex;
102+
const {retryIndex: browserRetryIndex, lastMatchedRetryIndex} = tree.browsers.stateById[browserId] || {};
103+
let retryIndex;
104+
105+
if (typeof viewRetryIndex === 'number') {
106+
retryIndex = Math.min(viewRetryIndex, browserRetryIndex);
107+
} else {
108+
retryIndex = isNumber(lastMatchedRetryIndex) ? lastMatchedRetryIndex : browserRetryIndex;
109+
}
105110

106111
return {gui, running, retryIndex};
107112
},

lib/static/modules/reducers/tree/index.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
initBrowsersState, changeAllBrowsersState, changeBrowserState,
99
calcBrowsersShowness, calcBrowsersOpenness, setBrowsersLastRetry
1010
} from './nodes/browsers';
11-
import {addResult} from './nodes/results';
11+
import {initResultsState, changeAllResultsState, changeResultState, addResult} from './nodes/results';
1212
import {
1313
initImagesState, changeAllImagesState, changeImageState, addImages, calcImagesOpenness
1414
} from './nodes/images';
@@ -27,6 +27,7 @@ export default produce((state, action) => {
2727

2828
state.tree.suites.stateById = {};
2929
state.tree.browsers.stateById = {};
30+
state.tree.results.stateById = {};
3031
state.tree.images.stateById = {};
3132

3233
updateAllSuitesStatus(state.tree, filteredBrowsers);
@@ -90,8 +91,13 @@ export default produce((state, action) => {
9091

9192
case actionNames.CHANGE_TEST_RETRY: {
9293
const {browserId, retryIndex} = action.payload;
94+
const browserState = {retryIndex};
9395

94-
changeBrowserState(state.tree, browserId, {retryIndex});
96+
if (state.view.keyToGroupTestsBy) {
97+
browserState.lastMatchedRetryIndex = null;
98+
}
99+
100+
changeBrowserState(state.tree, browserId, browserState);
95101

96102
break;
97103
}
@@ -138,8 +144,6 @@ export default produce((state, action) => {
138144
calcBrowsersOpenness(tree, view.expand);
139145
calcImagesOpenness(tree, view.expand);
140146

141-
setBrowsersLastRetry(tree);
142-
143147
break;
144148
}
145149

@@ -154,12 +158,13 @@ export default produce((state, action) => {
154158
}
155159

156160
case actionNames.TOGGLE_TESTS_GROUP: {
157-
const {browserIds, isActive} = action.payload;
161+
const {browserIds, resultIds, isActive} = action.payload;
158162
const {tree, view} = state;
159163

160164
if (!isActive) {
161-
changeAllBrowsersState(tree, {shouldBeShown: false});
165+
changeAllBrowsersState(tree, {shouldBeShown: false, lastMatchedRetryIndex: null});
162166
changeAllSuitesState(tree, {shouldBeShown: false});
167+
changeAllResultsState(tree, {matchedSelectedGroup: false});
163168

164169
return;
165170
}
@@ -169,11 +174,28 @@ export default produce((state, action) => {
169174
tree.browsers.allIds.forEach((browserId) => {
170175
const {shouldBeShown} = tree.browsers.stateById[browserId];
171176

172-
if (browserIds.includes(browserId) || !shouldBeShown) {
177+
if (!shouldBeShown) {
173178
return;
174179
}
175180

176-
changeBrowserState(tree, browserId, {shouldBeShown: false});
181+
if (!browserIds.includes(browserId)) {
182+
return changeBrowserState(tree, browserId, {shouldBeShown: false});
183+
}
184+
185+
const broResultIds = tree.browsers.byId[browserId].resultIds;
186+
let lastMatchedRetryIndex = broResultIds.length - 1;
187+
188+
broResultIds.forEach((resultId, ind) => {
189+
if (!resultIds.includes(resultId)) {
190+
changeResultState(tree, resultId, {matchedSelectedGroup: false});
191+
return;
192+
}
193+
194+
lastMatchedRetryIndex = ind;
195+
changeResultState(tree, resultId, {matchedSelectedGroup: true});
196+
});
197+
198+
changeBrowserState(tree, browserId, {lastMatchedRetryIndex});
177199
});
178200

179201
calcSuitesShowness(tree);
@@ -184,15 +206,18 @@ export default produce((state, action) => {
184206
case actionNames.GROUP_TESTS_BY_KEY: {
185207
const {tree, view} = state;
186208

209+
changeAllResultsState(tree, {matchedSelectedGroup: false});
210+
187211
if (view.keyToGroupTestsBy) {
188-
changeAllBrowsersState(tree, {shouldBeShown: false});
212+
changeAllBrowsersState(tree, {shouldBeShown: false, lastMatchedRetryIndex: null});
189213
changeAllSuitesState(tree, {shouldBeShown: false});
190214

191215
return;
192216
}
193217

194218
calcBrowsersShowness(tree, view);
195219
calcSuitesShowness(tree);
220+
changeAllBrowsersState(tree, {lastMatchedRetryIndex: null});
196221

197222
break;
198223
}
@@ -205,6 +230,7 @@ function initNodesStates(state) {
205230
initBrowsersState(tree, view);
206231
initSuitesState(tree, view);
207232
initImagesState(tree, view.expand);
233+
initResultsState(tree);
208234
}
209235

210236
function addNodesToTree(state, payload) {

lib/static/modules/reducers/tree/nodes/browsers.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import _ from 'lodash';
1+
import {isEmpty, last, initial} from 'lodash';
22
import {isStatusMatchViewMode, isTestNameMatchFilters, shouldShowBrowser} from '../../../utils';
33
import {isNodeFailed} from '../../../utils';
44
import {changeNodeState, shouldNodeBeOpened} from '../helpers';
@@ -19,8 +19,7 @@ export function initBrowsersState(tree, view) {
1919

2020
export function changeAllBrowsersState(tree, state) {
2121
tree.browsers.allIds.forEach((browserId) => {
22-
const retryIndex = getLastRetryIndex(tree, browserId);
23-
changeBrowserState(tree, browserId, {retryIndex, ...state});
22+
changeBrowserState(tree, browserId, state);
2423
});
2524
}
2625

@@ -29,7 +28,7 @@ export function changeBrowserState(tree, browserId, state) {
2928
}
3029

3130
export function setBrowsersLastRetry(tree, browserIds) {
32-
if (_.isEmpty(browserIds)) {
31+
if (isEmpty(browserIds)) {
3332
browserIds = tree.browsers.allIds;
3433
}
3534

@@ -40,27 +39,27 @@ export function setBrowsersLastRetry(tree, browserIds) {
4039
}
4140

4241
export function calcBrowsersShowness(tree, view, browserIds) {
43-
if (_.isEmpty(browserIds)) {
42+
if (isEmpty(browserIds)) {
4443
browserIds = tree.browsers.allIds;
4544
}
4645

4746
[].concat(browserIds).forEach((browserId) => {
4847
const browser = tree.browsers.byId[browserId];
49-
const lastResult = tree.results.byId[_.last(browser.resultIds)];
48+
const lastResult = tree.results.byId[last(browser.resultIds)];
5049
const shouldBeShown = calcBrowserShowness(browser, lastResult, view);
5150

5251
changeBrowserState(tree, browserId, {shouldBeShown});
5352
});
5453
}
5554

5655
export function calcBrowsersOpenness(tree, expand, browserIds) {
57-
if (_.isEmpty(browserIds)) {
56+
if (isEmpty(browserIds)) {
5857
browserIds = tree.browsers.allIds;
5958
}
6059

6160
[].concat(browserIds).forEach((browserId) => {
6261
const browser = tree.browsers.byId[browserId];
63-
const lastResult = tree.results.byId[_.last(browser.resultIds)];
62+
const lastResult = tree.results.byId[last(browser.resultIds)];
6463
const shouldBeOpened = calcBrowserOpenness(browser, lastResult, expand, tree);
6564

6665
changeBrowserState(tree, browserId, {shouldBeOpened});
@@ -74,7 +73,7 @@ function getLastRetryIndex(tree, browserId) {
7473
function calcBrowserOpenness(browser, lastResult, expand, tree) {
7574
const errorsCb = () => isNodeFailed(lastResult);
7675
const retriesCb = () => {
77-
const retries = [].concat(_.initial(browser.resultIds)).map((resultId) => tree.results.byId[resultId]);
76+
const retries = [].concat(initial(browser.resultIds)).map((resultId) => tree.results.byId[resultId]);
7877

7978
return retries.some((retry) => isNodeFailed(retry));
8079
};

lib/static/modules/reducers/tree/nodes/results.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
import {changeNodeState} from '../helpers';
2+
3+
export function initResultsState(tree) {
4+
changeAllResultsState(tree, {matchedSelectedGroup: false});
5+
}
6+
7+
export function changeAllResultsState(tree, state) {
8+
tree.results.allIds.forEach((resultId) => {
9+
changeResultState(tree, resultId, state);
10+
});
11+
}
12+
13+
export function changeResultState(tree, resultId, state) {
14+
changeNodeState(tree.results.stateById, resultId, state);
15+
}
16+
117
export function addResult(tree, result) {
218
tree.results.byId[result.id] = result;
319

0 commit comments

Comments
 (0)