Skip to content
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: retry tests with checkboxes #453

Merged
merged 1 commit into from
Jul 3, 2023

Conversation

KuznetsovRoman
Copy link
Member

No description provided.

@KuznetsovRoman KuznetsovRoman changed the title feat: retry tests with checkboxes [WIP] feat: retry tests with checkboxes Dec 30, 2022
@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 10 times, most recently from 0786350 to fb59b5e Compare January 13, 2023 10:57
@KuznetsovRoman KuznetsovRoman changed the title [WIP] feat: retry tests with checkboxes feat: retry tests with checkboxes Jan 13, 2023
@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 5 times, most recently from ce3b443 to 8e8ad44 Compare January 13, 2023 12:49
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что сделано

Добавил чекбоксы на:

  • браузеры
  • сьюты
  • группы

У чекбоксов три состояния: "Выбрано", "Не выбрано", "Выбрано частично"

Чекбоксы отжимаются, когда изменяется режим просмотра (фильтр по имени теста, по браузеру, по статусу, группировка), также обновляется статус чекбоксов (ex: полу-выбранный может стать выбранным, если в текущем режиме просмотра все его дети выбраны)

Также изменил кнопку запуска, теперь в ней совмещены три режима: "Запустить (все|выбранные|проваленные) тесты"

Принятые решения

Отключил чекбоксы пока в статике, так как там они не делают ничего.

Скриншоты

image

image

image

image

@@ -21,12 +22,13 @@ class CommonFilters extends Component {
/>
<TestNameFilterInput/>
<StrictMatchFilterInput/>
{gui && <ShowCheckboxesInput/>}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Затычка, чтобы убрать чекбоксы из статического отчета.

Добавил, потому что пока от этих чекбоксов в статическом отчете никакого толку нет.

Чтобы чекбоксы в статике заработали, достаточно просто убрать вот это вот условие

Comment on lines -20 to -34
processing: PropTypes.bool.isRequired,
stopping: PropTypes.bool.isRequired,
autoRun: PropTypes.bool.isRequired,
allRootSuiteIds: PropTypes.arrayOf(PropTypes.string).isRequired,
failedRootSuiteIds: PropTypes.arrayOf(PropTypes.string).isRequired,
failedTests: PropTypes.arrayOf(PropTypes.shape({
testName: PropTypes.string,
browserName: PropTypes.string
})).isRequired
}

_runFailedTests = () => {
const {actions, failedTests} = this.props;

return actions.runFailedTests(failedTests);
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот это вот все унес под кнопку <RunButton />

Comment on lines +15 to +20
const RunMode = Object.freeze({
ALL: 'All',
FAILED: 'Failed',
CHECKED: 'Checked'
});
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что-то типа Enum

Comment on lines 27 to 29
const shouldShowFailed = !!failedTests.length;
const shouldShowChecked = showCheckboxes && !!checkedTests.length;
const shouldShowPopup = !isDisabled && (shouldShowFailed || shouldShowChecked);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Отображаем:

  • вариант Failed если упавшие тесты есть
  • вариант Checked если выбран соответствующий режим и есть выбранные тесты
  • сам попап, если помимо All доступен хоть один вариант выше

Comment on lines 55 to 62
useEffect(() => {
const pickedEmptyFailed = mode === RunMode.FAILED && !shouldShowFailed;
const pickedEmptyChecked = mode === RunMode.CHECKED && !shouldShowChecked;

if (pickedEmptyFailed || pickedEmptyChecked) {
setMode(RunMode.ALL);
}
}, [shouldShowFailed, shouldShowChecked]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Скидываем режим до All, если текущий выбранный вариант пропал. Такое бывает, если:

  • Перезапустили упавшие тесты, и они прошли
  • Отключили чекбоксы
  • Анчекнули все тесты

Comment on lines 38 to 52
export function updateParentsChecked(tree, parentIds) {
const youngerSuites = [].concat(parentIds)
.filter(parentId => parentId)
.map((suiteId) => tree.suites.byId[suiteId]);

const changeParentSuiteCb = (parentSuite) => {
changeSuiteState(tree, parentSuite.id, {shouldBeChecked: shouldSuiteBeChecked(parentSuite, tree)});
};

youngerSuites.forEach(changeParentSuiteCb);

calcParentSuitesState(youngerSuites, tree, changeParentSuiteCb);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Заиспользовал имеющуюся функцию calcParentSuitesState, но первый слой сьютов, который имеет браузеры, оно не обрабатывает, поэтому по ним проходимся вручную

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPD: shouldBeChecked -> checkStatus

@@ -33,6 +35,20 @@ export function updateSuitesStatus(tree, suites) {
});
}

export function updateParentsChecked(tree, parentIds) {
const youngerSuites = [].concat(parentIds)
.filter(parentId => parentId)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

До этого фильтра тут еще могут оказаться null

Comment on lines 194 to 196
return checkedChildCount && checkedChildCount < childCount
? undefined
: checkedChildCount === childCount;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если выбрано не нулевое количество детей, но не все, то ставим сьюту undefined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPD:

return Number((checkedChildCount === childCount) || (checkedChildCount && INDETERMINATE));

Comment on lines -290 to +322
width: 16px;
width: 18px;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чекбоксы изначально 17х17. Чтобы не дергалось при их включении/выключании, поставил всем ширину в 18 пикселей.

Comment on lines 40 to 54
describe('skipped test', () => {
it('should render "[skipped]" tag in title', () => {
it('should pass "[skipped]" tag in title', () => {
const browsersById = mkBrowser({id: 'yabro-1', name: 'yabro', resultIds: ['res'], parentId: 'test'});
const browsersStateById = {'yabro-1': {shouldBeShown: true, shouldBeOpened: false}};
const resultsById = mkResult({id: 'res', status: SKIPPED});
const tree = mkStateTree({browsersById, browsersStateById, resultsById});

const component = mkSectionBrowserComponent({browserId: 'yabro-1'}, {tree});
mkSectionBrowserComponent({browserId: 'yabro-1'}, {tree});

assert.equal(component.find('.section__title_skipped').first().text(), `[${SKIPPED}] yabro`);
assert.calledWithMatch(
BrowserSkippedTitle,
set({}, 'title.props.children', [`[${SKIPPED}] `, 'yabro', undefined, undefined])
);
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В этом файле тестировался по сути <BrowserTitle/> компонент.
Это мешало, потому что <BrowserTitle/> теперь обращается к localStorage по хуку useLocalStorage, и тут нужно было либо перестать тестировать ребенка, либо передавать сюда в proxyquire <BrowserTitle/> с застабанным useLocalStorage. Выбрал первый вариант, кажется, так правильнее. Тесты ребенка перенес в отдельный файл, а тут застабал и проверяю, с каким тайтлом он вызывается.

Там в качестве title - React.Fragment, поэтому через массив:
['[skipped]', <browser>, ' reason ', <reason>]

Comment on lines +3 to +7
module.exports = {
UNCHECKED: 0,
INDETERMINATE: 0.5,
CHECKED: 1
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сначала были checked / unchecked - true / false, соответственно. Потом появились indeterminate. Булевых значений всего два, поэтому и есть этот enum. Тип - число, потому что так удобнее считать.

@KuznetsovRoman
Copy link
Member Author

Подвинул линию у неопределенных чекбоксов на пол пикселя вниз

image

Copy link
Member

@sipayRT sipayRT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

последние тесты на редьюсеры получились прям сложными (но я сходу не придумал как их упростить)

Еще режет глаз постоянные Number(!checkStatus). очень легко запутаться

в остальном норм (но я еще в живую потыкаю)

upd: в попапе не хватает разделителей между режимами. сейчас слова как будто подвешены в воздухе

}

.run-button__dropdown {
font-family: Dropdown;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

что это за ff такой?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это специальный шрифт из semantic-ui-react для отображения этой стрелочки у Dropdown:
image

Заиспользовал его, чтобы не плодить лишних svg

{shouldShowPopup && <Popup
action='hover'
hideOnClick={true}
target={<span className='run-button__dropdown' />}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

для чего это делается span-ом?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

span по своей натуре строчный элемент, в то время как div - блочный. Может с div отображалось бы так же, но как будто семантически ближе именно span

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

span как раз больше для выделения конкретных частей текста (например, подсветить слово)

div будет вести себя так же. Но не критично

lib/static/components/controls/run-button/index.styl Outdated Show resolved Hide resolved
checkedTests: PropTypes.arrayOf(PropTypes.shape({
testName: PropTypes.string,
browserName: PropTypes.string
})).isRequired
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

но ведь если у нас не включен режим чекбокса, то этого значения не будет. Или будет просто пустой массив?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image Слайдер на чекбокс только переключает его отображение, и по сути выполняет чисто визуальную функцию. Если чекнуть какой-то тест, потом выключить чекбоксы, а потом включить обратно, то `checkedTests` сохранится. Так что тут если чекбоксы выключены, это просто будет пустым массивом

(state) => {
const autoRun = state.autoRun;
const allRootSuiteIds = state.tree.suites.allRootIds;
const processing = state.processing;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

чем у нас processing отличается от running?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

processing не обязательно running. processing может быть принятие скриншота

useLocalStorageStub = sandbox.stub().returns([true]);
actionsStub = {
runAllTests: sandbox.stub().returns({type: 'some-type'}),
runFailedTests: sandbox.stub().returns({type: 'some-type'}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зачем возвращать одинаковые значения для разных экшенов?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нам абсолютно нет никакой разницы, что там за тип, главное, чтобы он был

В тестах нет никакой завязки на эти type, проверяется именно, что вызывается сама функция runAllTests, runFailedTests. Ну и такое возвращаемое значение застабано для всех экшенов в тестах: https://github.com/search?q=repo%3Agemini-testing%2Fhtml-reporter%20type%3A%20%27some-type%27&type=code

const state = mkState({initialState: {tree: {suites: {allRootIds: ['suite']}}, processing: false}});
selectorsStub.getFailedTests.withArgs(state).returns(failedTests);
const component = mkConnectedComponent(<RunButton />, {state});
component.findWhere(node => node.type() === 'li' && node.text() === 'Failed').simulate('click');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а че, по value нельзя проще найти? или добавить data-атрибут в разметку

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не знал, что так можно. Заменил на component.find({children: 'Failed'}).simulate('click');


const component = mkGroupTestsItemComponent();

assert.equal(component.find(Checkbox).exists(), +show);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

чет я не понял. exists же булевое значение вернет

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем я тогда show к числу привел? Пофиксил

}).default;
});

describe('<Checkbox/>', () => {
[true, false].forEach(show => {
it(`should ${show ? '' : 'not '}exist if "showCheckboxes" is ${show ? '' : 'not '}set`, () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

выше уже писал, что стОит вынести логику в общий компонент. у тебя и тесты дублируются теперь

@sipayRT
Copy link
Member

sipayRT commented Jun 22, 2023

Попробовал запустить упавшие тесты. Выбрал по одному тесту в разных сьютах. В итоге, тесты прошли (из попапа удалился пункт про упавшие тесты), а визуально выглядит как будто тесты еще выполняются

image

@sipayRT
Copy link
Member

sipayRT commented Jun 22, 2023

Я бы еще в попапе не удалял пункты, которых не может быть, а дизхейблил. Так будет сильно проще пользователю, т.к. он привыкает, что вторая строчка - это перезапуск упавших тестов, а там, вдруг, уже перезапуск выделенных тестов. Интерфейс должен оставаться постоянным

@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 3 times, most recently from 50341a0 to a9b50e3 Compare June 23, 2023 09:18
@KuznetsovRoman
Copy link
Member Author

KuznetsovRoman commented Jun 23, 2023

Попробовал запустить упавшие тесты. Выбрал по одному тесту в разных сьютах. В итоге, тесты прошли (из попапа удалился пункт про упавшие тесты), а визуально выглядит как будто тесты еще выполняются

Попробуй в development режиме, если получится воспроизвести, то в консоли должен быть лог редакса.

Визуально оно так выглядит, потому что tree.suites.byId[suiteId].status === "running"

Устанавливается он как раз через clientEvents эвентом TEST_BEGIN, после чего эвентом TEST_PASS после прохождения теста статус должен меняться

@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 2 times, most recently from 233cc01 to 4af63cd Compare June 23, 2023 15:44
@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 3 times, most recently from c0e184e to a3cb944 Compare June 27, 2023 17:50
@@ -53,28 +53,47 @@ const RunButton = ({actions, autoRun, isDisabled, isRunning, failedTests, checke
}, []);

useEffect(() => {
const pickedEmptyFailed = mode === RunMode.FAILED && !shouldShowFailed;
const pickedEmptyChecked = mode === RunMode.CHECKED && !shouldShowChecked;
if (!shouldDisableChecked) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

у тебя здесь получается двойная проверка на shouldDisableChecked - сначала здесь, а потом и внутри функции selectCheckedTests

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убрал внутри useEffect, потому что disabled опции все равно могут получить клик

lib/static/components/controls/run-button/index.js Outdated Show resolved Hide resolved
{shouldShowPopup && <Popup
action='hover'
hideOnClick={true}
target={<span className='run-button__dropdown' />}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

span как раз больше для выделения конкретных частей текста (например, подсветить слово)

div будет вести себя так же. Но не критично

lib/static/components/controls/run-button/index.js Outdated Show resolved Hide resolved
lib/static/components/bullet.js Outdated Show resolved Hide resolved
test/unit/lib/static/components/bullet.js Outdated Show resolved Hide resolved
lib/static/components/bullet.js Show resolved Hide resolved
test/unit/lib/static/components/bullet.js Outdated Show resolved Hide resolved
test/unit/lib/static/components/controls/run-button.js Outdated Show resolved Hide resolved
@KuznetsovRoman KuznetsovRoman force-pushed the HERMIONE-290.gui_checkbox branch 2 times, most recently from 91b28e8 to 9264ff0 Compare July 3, 2023 13:52
@KuznetsovRoman KuznetsovRoman merged commit 665b80a into master Jul 3, 2023
4 checks passed
@KuznetsovRoman KuznetsovRoman deleted the HERMIONE-290.gui_checkbox branch July 3, 2023 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants