-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add grouping by error type #213
Conversation
9d6eaad
to
06431d1
Compare
06431d1
to
299788f
Compare
README.md
Outdated
@@ -24,6 +24,10 @@ directory. | |||
* **baseHost** (optional) - `String` - it changes original host for view in the browser; by default original host does not change | |||
* **scaleImages** (optional) – `Boolean` – fit images into page width; `false` by default | |||
* **lazyLoadOffset** (optional) - `Number` - allows you to specify how far above and below the viewport you want to begin loading images. Lazy loading would be disabled if you specify 0. `800` by default. | |||
* **errorPatterns** (optional) - `Array` - error message patterns for 'Group by error' mode. | |||
Array element must be `Object` ({'*name*': `String`, '*pattern*': `String`}) or `String` (interpret as *name* and *pattern*). | |||
Test will be associated with group if `errorTest.message.match(new RegExp(pattern))`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Давай как-то так - Test will be associated with group if test error matches on group error pattern
, чтобы в доку куски кода не вставлять.
lib/static/components/error-group.js
Outdated
|
||
constructor(props) { | ||
super(props); | ||
this._toggleState = this._toggleState.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А чего не через стрелочную функцию, чтобы без биндинга?
https://medium.com/silesis/handle-events-in-react-with-arrow-functions-ede88184bbb
lib/static/components/error-group.js
Outdated
|
||
const body = this.state.collapsed | ||
? null | ||
: <div className="error_group__body error_group__body_guided"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error-group__body_guided
- го по БЭМ-у
lib/static/components/error-group.js
Outdated
<div className={className}> | ||
<div className="error_group__title" onClick={this._toggleState} title={group.pattern}> | ||
<div className="error_group__name">{group.name}</div> | ||
<div className="error_group__count"> ({group.count})</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Кажется, здесь перебор с дивами. italic можно сделать с помощью тега <i>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diveloper жи есть
export default connect( | ||
(state) => ({ | ||
groupedErrors: state.groupedErrors | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
го в 1 строчку
lib/static/modules/utils.js
Outdated
* @param {string} [filterByName] | ||
* @return {array} | ||
*/ | ||
function groupErrors(suites, errorPatterns, filteredBrowsers, filterByName = '') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filterByName - звучит, как название функции
Я бы nameFilterPattern назвал
lib/static/modules/utils.js
Outdated
group.tests[testName].push(browserName); | ||
group.count++; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Давай этот for перепишем через reduce и в функцию вынесем. groupErrors
занимает 52 строчки - ее точно рефакторить нужно.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
функцию вынес. не понял, чем поможет reduce читаемости
lib/static/modules/utils.js
Outdated
} | ||
if (!group.tests[testName].includes(browserName)) { | ||
group.tests[testName].push(browserName); | ||
group.count++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Этот каунтер точно нужен?
Нельзя потом взять length от Object.keys(group.tests)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Нужно брать количество упавших тестов по браузерам, чтобы числа были в соответствии со статистикой сверху
lib/static/modules/utils.js
Outdated
if (!group.tests.hasOwnProperty(testName)) { | ||
group.tests[testName] = []; | ||
} | ||
if (!group.tests[testName].includes(browserName)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если group.tests[testName] сделать set-ом, а не массивом, эта проверка уйдет
lib/static/modules/utils.js
Outdated
} | ||
return { | ||
pattern: errorText | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
в одну строчку
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
зачем?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 за одну строчку, в читаемости код не потеряет, но будет короче. В этом и плюс.
a9f9734
to
6d136fe
Compare
fixed. |
6d136fe
to
bbb9d4c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
section-common сейчас слишком умный. Он ничего не должен знать про группировку по ошибкам
@@ -24,6 +24,10 @@ directory. | |||
* **baseHost** (optional) - `String` - it changes original host for view in the browser; by default original host does not change | |||
* **scaleImages** (optional) – `Boolean` – fit images into page width; `false` by default | |||
* **lazyLoadOffset** (optional) - `Number` - allows you to specify how far above and below the viewport you want to begin loading images. Lazy loading would be disabled if you specify 0. `800` by default. | |||
* **errorPatterns** (optional) - `Array` - error message patterns for 'Group by error' mode. | |||
Array element must be `Object` ({'*name*': `String`, '*pattern*': `String`}) or `String` (interpret as *name* and *pattern*). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не понял как в данном случае будет выглядеть элемент массива переданный строкой. Чем я должен имя от паттерна отделить? Пробелом?
Я бы еще ниже добавил пример.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
если значение строка - то она интерпретируется и как шаблон и как название группы.
никаких разделителей.
пример добавлю
lib/config.js
Outdated
errorPatterns: option({ | ||
defaultValue: configDefaults.errorPatterns, | ||
parseEnv: JSON.parse, | ||
validate: assertArray('errorPatterns') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
я бы еще проверил, что элементы массива являются объектами или строками
@@ -4,30 +4,30 @@ import React, {Component} from 'react'; | |||
import PropTypes from 'prop-types'; | |||
import {bindActionCreators} from 'redux'; | |||
import {connect} from 'react-redux'; | |||
import _ from 'lodash'; | |||
import {debounce} from 'lodash'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
(dispatch) => ({actions: bindActionCreators(actions, dispatch)}) | ||
)(FilterByNameInput); | ||
)(TestNameFilterInput); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
это можно было бы отдельным коммитом сделать
lib/static/components/error-group.js
Outdated
this.state = { | ||
collapsed: true | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
красивее будет вот так:
state = {
collapsed: true
}
В этом случае конструктор определять не нужно
lib/static/modules/utils.js
Outdated
} else if (typeof patternInfo === 'object') { | ||
return { | ||
pattern: patternInfo.pattern, | ||
name: patternInfo.name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
почему у тебя в итоге в зависимости от типа получаются объекты с разными полями? Давай сделаем, чтобы поля у них были одинаковые. Тебе же так в коде удобнее будет.
lib/static/modules/utils.js
Outdated
errorPatterns = normalizeErrorPatterns(errorPatterns); | ||
const testWithErrors = {}; | ||
|
||
extractErrors(suites, testWithErrors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
такая конструкция выглядет очень странной.
Почему так не написать:
const errors = extractErrors(suites);
lib/static/modules/utils.js
Outdated
if (suite.children) { | ||
extractErrors(suite.children, testWithErrors); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можно же проще написать.
function extractErrors(suites) {
const extract = (node) => {
if (node.children) {
return flatMap(node.children, extract);
}
if (node.browsers) {
return flatMap(node.browsers, extract);
}
if (isSuccessStatus(node.result.status)) {
return [];
}
const broResults = browser.retries.concat(browser.result);
const errors = extractErrorsFromRetries(broResults);
return {[node.name]: errors};
});
return flatMap(suites, extract);
}
lib/static/modules/utils.js
Outdated
} | ||
if (retry.error && retry.error.message) { | ||
errorsInRetry.add(retry.error.message); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[retry].concat(retry.imagesInfo).forEach(({error}) => {
if (_.get(error, 'message')) {
errorsInRetry.add(error.message);
}
});
lib/static/modules/utils.js
Outdated
} | ||
return { | ||
pattern: errorText | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 за одну строчку, в читаемости код не потеряет, но будет короче. В этом и плюс.
e44d18d
to
3e066d4
Compare
fixed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
в остальном /ok
name: 'Cannot read property of undefined', | ||
pattern: 'Cannot read property .* of undefined' | ||
} | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
pattern: patternInfo | ||
}; | ||
} | ||
return patternInfo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Я бы так написал:
return _.isString(pattern) ? {name: pattern, pattern} : pattern;
} | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
}), | ||
errorPatterns: option({ | ||
defaultValue: configDefaults.errorPatterns, | ||
parseEnv: JSON.parse, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а почему ты тут parseCli
не указал?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ты думаешь, кто-нибудь захочет передать список шаблонов ошибок через cli?
actions: PropTypes.object.isRequired | ||
} | ||
|
||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
filterByName: this.props.filterByName | ||
testNameFilter: this.props.testNameFilter | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Чего не захотел от конструктора избавиться? Тебе запись такая не нравиться?
mkSuiteTree({ | ||
browsers: [ | ||
mkBrowserResult({ | ||
result: mkTestResult({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
выглядит так, что нужен хелпер который строит дерево только по переданному testResult
и testRetry
. Без явного определения всего дерева
}) | ||
] | ||
}) | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
У тебя тут стрела смерти получилась ) Тебя такое количество данных не смущает? Может нужен еще один уровень абстракции?
Я бы наверно попробовал написать хелпер, который бы на вход принимал стейт, а по suitePath
определял сколько над ним должно быть сьютов. За счет этого код самого теста сильно бы упростился
count: 1, | ||
name: 'message stub', | ||
pattern: 'message stub', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
лишняя пустая строка
name: 'message stub', | ||
pattern: 'message stub', | ||
tests: { | ||
'default-suite default-state': ['browserOne', 'browserTwo'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
опять поля которые указаны только в недрах хелперов
} | ||
]); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
сложные тесты получилось. Возможно стоило юзать какие-то фикстуры или попробовать спрятать часть данных внутри дополнительных хелперов
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Договорились c @sipayRT, что оформлю отдельный PR по тестам
3e066d4
to
7a566a3
Compare
Аdded a button "Group by error" that groups tests by error messages. Patterns for grouping can be specified in the configuration.
I will write more unit tests after approving main code.