Skip to content

Commit

Permalink
feat: strict match filter
Browse files Browse the repository at this point in the history
  • Loading branch information
rmdm committed Dec 27, 2019
1 parent 828bcfa commit 7148df2
Show file tree
Hide file tree
Showing 17 changed files with 384 additions and 21 deletions.
2 changes: 2 additions & 0 deletions lib/static/components/controls/common-filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import React, {Component} from 'react';
import TestNameFilterInput from './test-name-filter-input';
import StrictMatchFilterInput from './strict-match-filter-input';

class CommonFilters extends Component {
render() {
return (
<div className="control-filters">
<TestNameFilterInput/>
<StrictMatchFilterInput/>
</div>
);
}
Expand Down
50 changes: 50 additions & 0 deletions lib/static/components/controls/strict-match-filter-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as actions from '../../modules/actions';

class StrictMatchFilterInput extends Component {
static propTypes = {
strictMatchFilter: PropTypes.bool.isRequired,
actions: PropTypes.object.isRequired
}

constructor(props) {
super(props);

this.state = {
strictMatchFilter: this.props.strictMatchFilter
};

this._onChange = (event) => {
this.setState({strictMatchFilter: event.target.checked});
this.props.actions.setStrictMatchFilter(event.target.checked);
};
}

render() {
return (
<Fragment>
<input
type="checkbox"
id="strictMatchFilter"
onChange={this._onChange}
checked={this.state.strictMatchFilter}
/>
<label
className="checkbox-label"
htmlFor="strictMatchFilter">
Strict match
</label>
</Fragment>
);
}
}

export default connect(
(state) => ({strictMatchFilter: state.view.strictMatchFilter}),
(dispatch) => ({actions: bindActionCreators(actions, dispatch)})
)(StrictMatchFilterInput);
7 changes: 4 additions & 3 deletions lib/static/components/section/section-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SectionCommon extends Component {
children: PropTypes.array
}),
testNameFilter: PropTypes.string,
strictMatchFilter: PropTypes.bool,
filteredBrowsers: PropTypes.array,
errorGroupTests: PropTypes.object,
shouldBeOpened: PropTypes.func,
Expand Down Expand Up @@ -56,7 +57,7 @@ class SectionCommon extends Component {
}

render() {
const {suite, testNameFilter, filteredBrowsers, sectionStatusResolver, errorGroupTests} = this.props;
const {suite, testNameFilter, strictMatchFilter, filteredBrowsers, sectionStatusResolver, errorGroupTests} = this.props;
const {opened} = this.state;
const {
name,
Expand All @@ -75,11 +76,11 @@ class SectionCommon extends Component {
);
}

const visibleChildren = children.filter(child => shouldSuiteBeShown({suite: child, testNameFilter, filteredBrowsers, errorGroupTests}));
const visibleChildren = children.filter(child => shouldSuiteBeShown({suite: child, testNameFilter, strictMatchFilter, filteredBrowsers, errorGroupTests}));
const childrenTmpl = visibleChildren.map((child) => {
const key = uniqueId(`${suite.suitePath}-${child.name}`);

return <SectionCommonWrapper key={key} suite={child} testNameFilter={testNameFilter} filteredBrowsers={filteredBrowsers} errorGroupTests={errorGroupTests} />;
return <SectionCommonWrapper key={key} suite={child} testNameFilter={testNameFilter} strictMatchFilter={strictMatchFilter} filteredBrowsers={filteredBrowsers} errorGroupTests={errorGroupTests} />;
});

const browserTmpl = browsers
Expand Down
1 change: 1 addition & 0 deletions lib/static/components/section/title/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class BrowserTitle extends Component {
return appendQuery(window.location.href, {
browser: browser.name,
testNameFilter: suite.suitePath.join(' '),
strictMatchFilter: true,
retryIndex: browser.state.retryIndex,
viewMode: 'all',
expand: 'all',
Expand Down
8 changes: 5 additions & 3 deletions lib/static/components/suites.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class Suites extends Component {
}

render() {
const {suites, suiteIds, testNameFilter, filteredBrowsers, lazyLoadOffset, errorGroupTests} = this.props;
const {suites, suiteIds, testNameFilter, strictMatchFilter, filteredBrowsers, lazyLoadOffset, errorGroupTests} = this.props;

const visibleSuiteIds = suiteIds.filter(id =>
shouldSuiteBeShown({suite: suites[id], testNameFilter, filteredBrowsers, errorGroupTests})
shouldSuiteBeShown({suite: suites[id], testNameFilter, strictMatchFilter, filteredBrowsers, errorGroupTests})
);

return (
Expand All @@ -30,6 +30,7 @@ class Suites extends Component {
key: suiteId,
suite: suites[suiteId],
testNameFilter,
strictMatchFilter,
filteredBrowsers,
errorGroupTests
};
Expand All @@ -51,12 +52,13 @@ class Suites extends Component {

export default connect(
(state) => {
const {testNameFilter, filteredBrowsers, lazyLoadOffset} = state.view;
const {testNameFilter, strictMatchFilter, filteredBrowsers, lazyLoadOffset} = state.view;

return ({
suiteIds: state.suiteIds[state.view.viewMode],
testNameFilter,
filteredBrowsers,
strictMatchFilter,
lazyLoadOffset,
suites: state.suites
});
Expand Down
1 change: 1 addition & 0 deletions lib/static/modules/action-names.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
VIEW_TOGGLE_ONLY_DIFF: 'VIEW_TOGGLE_ONLY_DIFF',
VIEW_UPDATE_BASE_HOST: 'VIEW_UPDATE_BASE_HOST',
VIEW_UPDATE_FILTER_BY_NAME: 'VIEW_UPDATE_FILTER_BY_NAME',
VIEW_SET_STRICT_MATCH_FILTER: 'VIEW_SET_STRICT_MATCH_FILTER',
VIEW_TOGGLE_GROUP_BY_ERROR: 'VIEW_TOGGLE_GROUP_BY_ERROR',
VIEW_TOGGLE_SCALE_IMAGES: 'VIEW_TOGGLE_SCALE_IMAGES',
VIEW_TOGGLE_LAZY_LOAD_IMAGES: 'VIEW_TOGGLE_LAZY_LOAD_IMAGES',
Expand Down
4 changes: 4 additions & 0 deletions lib/static/modules/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ export const updateTestNameFilter = (testNameFilter) => {
return triggerViewChanges({type: actionNames.VIEW_UPDATE_FILTER_BY_NAME, testNameFilter});
};

export const setStrictMatchFilter = (strictMatchFilter) => {
return triggerViewChanges({type: actionNames.VIEW_SET_STRICT_MATCH_FILTER, strictMatchFilter});
};

export function changeViewMode(mode) {
window.dispatchEvent(new Event(VIEW_CHANGED));

Expand Down
1 change: 1 addition & 0 deletions lib/static/modules/custom-queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function getViewQuery(queryString) {
return pick(query, [
'filteredBrowsers',
'testNameFilter',
'strictMatchFilter',
'retryIndex',
'viewMode',
'expand',
Expand Down
1 change: 1 addition & 0 deletions lib/static/modules/default-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default Object.assign(defaults, {
scaleImages: false,
baseHost: '',
testNameFilter: '',
strictMatchFilter: false,
filteredBrowsers: [],
groupByError: false
},
Expand Down
11 changes: 6 additions & 5 deletions lib/static/modules/group-errors.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

import {get, filter} from 'lodash';
import {isSuiteFailed} from './utils';
import {isSuiteFailed, isTestNameMatchFilters} from './utils';
import {isFailStatus, isErroredStatus} from '../../common-utils';

const imageComparisonErrorMessage = 'image comparison failed';
Expand All @@ -12,14 +12,15 @@ const imageComparisonErrorMessage = 'image comparison failed';
* @param {array} errorPatterns
* @param {array} filteredBrowsers
* @param {string} [testNameFilter]
* @param {boolean} [strictMatchFilter]
* @return {array}
*/
function groupErrors({suites = {}, viewMode = 'all', errorPatterns = [], filteredBrowsers = [], testNameFilter = ''}) {
function groupErrors({suites = {}, viewMode = 'all', errorPatterns = [], filteredBrowsers = [], testNameFilter = '', strictMatchFilter = false}) {
const showOnlyFailed = viewMode !== 'all';
const filteredSuites = showOnlyFailed ? filter(suites, isSuiteFailed) : suites;
const testWithErrors = extractErrors(filteredSuites, showOnlyFailed);

const errorGroupsList = getErrorGroupList(testWithErrors, errorPatterns, filteredBrowsers, testNameFilter);
const errorGroupsList = getErrorGroupList(testWithErrors, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter);

errorGroupsList.sort((a, b) => {
const result = b.count - a.count;
Expand Down Expand Up @@ -83,12 +84,12 @@ function extractErrorsFromRetries(retries) {
return [...errorsInRetry];
}

function getErrorGroupList(testWithErrors, errorPatterns, filteredBrowsers, testNameFilter) {
function getErrorGroupList(testWithErrors, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter) {
const errorGroups = {};
const errorPatternsWithRegExp = addRegExpToErrorPatterns(errorPatterns);

for (const [testName, browsers] of Object.entries(testWithErrors)) {
if (testNameFilter && !testName.includes(testNameFilter)) {
if (!isTestNameMatchFilters(testName, testNameFilter, strictMatchFilter)) {
continue;
}

Expand Down
34 changes: 27 additions & 7 deletions lib/static/modules/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ function reducer(state = getInitialState(compiledData), action) {
const {
suites,
config: {errorPatterns},
view: {viewMode, filteredBrowsers}
view: {viewMode, filteredBrowsers, strictMatchFilter}
} = state;

const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter});
const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter});

return {
...state,
Expand All @@ -198,6 +198,25 @@ function reducer(state = getInitialState(compiledData), action) {
}
};
}
case actionNames.VIEW_SET_STRICT_MATCH_FILTER: {
const {strictMatchFilter} = action;
const {
suites,
config: {errorPatterns},
view: {viewMode, filteredBrowsers, testNameFilter}
} = state;

const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter});

return {
...state,
groupedErrors,
view: {
...state.view,
strictMatchFilter
}
};
}
case actionNames.CLOSE_SECTIONS: {
const closeIds = action.payload;
return assign(clone(state), {closeIds});
Expand Down Expand Up @@ -372,7 +391,7 @@ function closeDb(state) {
function addTestResult(state, action) {
const {
config: {errorPatterns},
view: {viewMode, filteredBrowsers, testNameFilter}
view: {viewMode, filteredBrowsers, testNameFilter, strictMatchFilter}
} = state;
const suites = clone(state.suites);

Expand All @@ -396,7 +415,7 @@ function addTestResult(state, action) {
const suiteIds = clone(state.suiteIds);
assign(suiteIds, {failed: getFailedSuiteIds(suites)});

const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter});
const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter});

return assign({}, state, {suiteIds, suites, groupedErrors});
}
Expand Down Expand Up @@ -453,9 +472,9 @@ function _mutateViewMode(state, viewMode) {
const {
suites,
config: {errorPatterns},
view: {filteredBrowsers, testNameFilter}
view: {filteredBrowsers, testNameFilter, strictMatchFilter}
} = state;
const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter});
const groupedErrors = groupErrors({suites, viewMode, errorPatterns, filteredBrowsers, testNameFilter, strictMatchFilter});

return {
...state,
Expand Down Expand Up @@ -537,7 +556,8 @@ export function withBrowserStorage(reducer) {
// TODO: Uncomment when issues with rendering speed will fixed
// lazyLoadOffset: view.lazyLoadOffset,
groupByError: view.groupByError,
testNameFilter: view.testNameFilter
testNameFilter: view.testNameFilter,
strictMatchFilter: view.strictMatchFilter
});
}

Expand Down
18 changes: 15 additions & 3 deletions lib/static/modules/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ function dateToLocaleString(date) {
return new Date(date).toLocaleString(lang);
}

function shouldSuiteBeShown({suite, testNameFilter = '', filteredBrowsers = [], errorGroupTests = {}}) {
function shouldSuiteBeShown({suite, testNameFilter = '', strictMatchFilter = false, filteredBrowsers = [], errorGroupTests = {}}) {
const strictTestNameFilters = Object.keys(errorGroupTests);

// suite may contain children and browsers
Expand All @@ -179,6 +179,7 @@ function shouldSuiteBeShown({suite, testNameFilter = '', filteredBrowsers = [],
shouldSuiteBeShown({
suite: child,
testNameFilter,
strictMatchFilter,
errorGroupTests,
filteredBrowsers
})
Expand All @@ -195,7 +196,7 @@ function shouldSuiteBeShown({suite, testNameFilter = '', filteredBrowsers = [],

const suiteFullPath = suite.suitePath.join(' ');

const matchName = !testNameFilter || suiteFullPath.includes(testNameFilter);
const matchName = isTestNameMatchFilters(suiteFullPath, testNameFilter, strictMatchFilter);

const strictMatchNames = strictTestNameFilters.length === 0
|| strictTestNameFilters.includes(suiteFullPath);
Expand Down Expand Up @@ -335,6 +336,16 @@ function updateSuitesStats(stats, status, attemptInfo) {
}
}

function isTestNameMatchFilters(testName, testNameFilter, strictMatchFilter) {
if (!testNameFilter) {
return true;
}

return strictMatchFilter
? testName === testNameFilter
: testName.includes(testNameFilter);
}

module.exports = {
isNoRefImageError,
hasNoRefImageErrors,
Expand All @@ -355,5 +366,6 @@ module.exports = {
isUrl,
sortByTimeStamp,
updateSuitesStats,
filterSuites
filterSuites,
isTestNameMatchFilters
};
4 changes: 4 additions & 0 deletions lib/static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ a:active {
border-radius: 2px;
}

.checkbox-label {
font-size: 12px;
}

.overlay {
background: rgba(0, 0, 0, 0.3);
left: 0;
Expand Down
Loading

0 comments on commit 7148df2

Please sign in to comment.