Skip to content

Commit

Permalink
feat: add static image accepter
Browse files Browse the repository at this point in the history
  • Loading branch information
KuznetsovRoman committed Jul 18, 2024
1 parent c63919e commit 0eb2c82
Show file tree
Hide file tree
Showing 50 changed files with 1,682 additions and 226 deletions.
8 changes: 6 additions & 2 deletions lib/common-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
SKIPPED,
SUCCESS,
TestStatus,
UPDATED
UPDATED,
STAGED,
COMMITED
} from './constants';

import {CHECKED, INDETERMINATE, UNCHECKED} from './constants/checked-statuses';
Expand All @@ -36,7 +38,7 @@ const statusPriority: TestStatus[] = [
RUNNING, QUEUED,

// final
ERROR, FAIL, UPDATED, SUCCESS, IDLE, SKIPPED
ERROR, FAIL, STAGED, COMMITED, UPDATED, SUCCESS, IDLE, SKIPPED
];

export const logger = pick(console, ['log', 'warn', 'error']);
Expand All @@ -48,6 +50,8 @@ export const isRunningStatus = (status: TestStatus): boolean => status === RUNNI
export const isErrorStatus = (status: TestStatus): boolean => status === ERROR;
export const isSkippedStatus = (status: TestStatus): boolean => status === SKIPPED;
export const isUpdatedStatus = (status: TestStatus): boolean => status === UPDATED;
export const isStagedStatus = (status: TestStatus): boolean => status === STAGED;
export const isCommitedStatus = (status: TestStatus): boolean => status === COMMITED;

export const determineFinalStatus = (statuses: TestStatus[]): TestStatus | null => {
if (!statuses.length) {
Expand Down
37 changes: 37 additions & 0 deletions lib/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const ALLOWED_PLUGIN_DESCRIPTION_FIELDS = new Set(['name', 'component', 'point',
type TypePredicateFn<T> = (value: unknown) => value is T;
type AssertionFn<T> = (value: unknown) => asserts value is T;

const isPlainObject = (value: unknown): value is Record<string, unknown> => {
return _.isPlainObject(value);
};

const assertType = <T>(name: string, validationFn: (value: unknown) => value is T, type: string): AssertionFn<T> => {
return (v: unknown): asserts v is T => {
if (!validationFn(v)) {
Expand All @@ -25,6 +29,7 @@ const assertType = <T>(name: string, validationFn: (value: unknown) => value is
const assertString = (name: string): AssertionFn<string> => assertType(name, _.isString, 'string');
const assertBoolean = (name: string): AssertionFn<boolean> => assertType(name, _.isBoolean, 'boolean');
const assertNumber = (name: string): AssertionFn<number> => assertType(name, _.isNumber, 'number');
const assertPlainObject = (name: string): AssertionFn<Record<string, unknown>> => assertType(name, isPlainObject, 'plain object');

const assertSaveFormat = (saveFormat: unknown): asserts saveFormat is SaveFormat => {
const formats = Object.values(SaveFormat);
Expand Down Expand Up @@ -219,6 +224,38 @@ const getParser = (): ReturnType<typeof root<ReporterConfig>> => {
parseEnv: JSON.parse,
parseCli: JSON.parse,
validate: assertArrayOf('plugin descriptions', 'plugins', assertPluginDescription)
}),
staticImageAccepter: section({
enabled: option({
defaultValue: configDefaults.staticImageAccepter.enabled,
parseEnv: JSON.parse,
parseCli: JSON.parse,
validate: assertBoolean('staticImageAccepter.enabled')
}),
repositoryUrl: option({
defaultValue: configDefaults.staticImageAccepter.repositoryUrl,
validate: assertString('staticImageAccepter.repositoryUrl')
}),
pullRequestUrl: option({
defaultValue: configDefaults.staticImageAccepter.pullRequestUrl,
validate: assertString('staticImageAccepter.pullRequestUrl')
}),
serviceUrl: option({
defaultValue: configDefaults.staticImageAccepter.serviceUrl,
validate: assertString('staticImageAccepter.serviceUrl')
}),
meta: option({
defaultValue: configDefaults.staticImageAccepter.meta,
parseEnv: JSON.parse,
parseCli: JSON.parse,
validate: assertPlainObject('staticImageAccepter.meta')
}),
axiosRequestOptions: option({
defaultValue: configDefaults.staticImageAccepter.axiosRequestOptions,
parseEnv: JSON.parse,
parseCli: JSON.parse,
validate: assertPlainObject('staticImageAccepter.axiosRequestOptions')
})
})
}), {envPrefix: ENV_PREFIX, cliPrefix: CLI_PREFIX});
};
Expand Down
5 changes: 0 additions & 5 deletions lib/constants/checked-statuses.js

This file was deleted.

11 changes: 11 additions & 0 deletions lib/constants/checked-statuses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const UNCHECKED = 0;
export const INDETERMINATE = 0.5;
export const CHECKED = 1;

export default {
UNCHECKED,
INDETERMINATE,
CHECKED
};

export type CheckStatus = typeof UNCHECKED | typeof INDETERMINATE | typeof CHECKED;
8 changes: 8 additions & 0 deletions lib/constants/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,13 @@ export const configDefaults: ReporterConfig = {
saveFormat: SaveFormat.SQLITE,
yandexMetrika: {
counterNumber: null
},
staticImageAccepter: {
enabled: false,
repositoryUrl: '',
pullRequestUrl: '',
serviceUrl: '',
meta: {},
axiosRequestOptions: {}
}
};
16 changes: 16 additions & 0 deletions lib/constants/test-statuses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ export enum TestStatus {
ERROR = 'error',
SKIPPED = 'skipped',
UPDATED = 'updated',
/**
* @note used by staticImageAccepter only
*/
STAGED = 'staged',
/**
* @note used by staticImageAccepter only
*/
COMMITED = 'commited',
}

export const IDLE = TestStatus.IDLE;
Expand All @@ -17,3 +25,11 @@ export const FAIL = TestStatus.FAIL;
export const ERROR = TestStatus.ERROR;
export const SKIPPED = TestStatus.SKIPPED;
export const UPDATED = TestStatus.UPDATED;
/**
* @note used by staticImageAccepter only
*/
export const STAGED = TestStatus.STAGED;
/**
* @note used by staticImageAccepter only
*/
export const COMMITED = TestStatus.COMMITED;
2 changes: 2 additions & 0 deletions lib/constants/view-modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export enum ViewMode {
FAILED = 'failed',
RETRIED = 'retried',
SKIPPED = 'skipped',
STAGED = 'staged',
COMMITED = 'commited',
}
3 changes: 2 additions & 1 deletion lib/server-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ export function getConfigForStaticFile(pluginConfig: ReporterConfig): ConfigForS
'customScripts',
'yandexMetrika',
'pluginsEnabled',
'plugins'
'plugins',
'staticImageAccepter'
]);
}

Expand Down
11 changes: 9 additions & 2 deletions lib/static/components/controls/accept-opened-button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import {getAcceptableOpenedImageIds} from '../../modules/selectors/tree';

class AcceptOpenedButton extends Component {
static propTypes = {
isSuiteContol: PropTypes.bool,
// from store
processing: PropTypes.bool.isRequired,
acceptableOpenedImageIds: PropTypes.arrayOf(PropTypes.string).isRequired
};

_acceptOpened = () => {
this.props.actions.acceptOpened(this.props.acceptableOpenedImageIds);
if (this.props.isStaticImageAccepterEnabled) {
this.props.actions.staticAccepterStageScreenshot(this.props.acceptableOpenedImageIds);
} else {
this.props.actions.acceptOpened(this.props.acceptableOpenedImageIds);
}
};

render() {
Expand All @@ -24,6 +29,7 @@ class AcceptOpenedButton extends Component {
label="Accept opened"
isDisabled={!acceptableOpenedImageIds.length || processing}
handler={this._acceptOpened}
isSuiteControl={this.props.isSuiteContol}
/>;
}
}
Expand All @@ -32,7 +38,8 @@ export default connect(
(state) => {
return {
processing: state.processing,
acceptableOpenedImageIds: getAcceptableOpenedImageIds(state)
acceptableOpenedImageIds: getAcceptableOpenedImageIds(state),
isStaticImageAccepterEnabled: state.staticImageAccepter.enabled,
};
},
(dispatch) => ({actions: bindActionCreators(actions, dispatch)})
Expand Down
14 changes: 11 additions & 3 deletions lib/static/components/controls/common-controls.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {capitalize} from 'lodash';
import {capitalize, pull} from 'lodash';
import * as actions from '../../modules/actions';
import ControlButton from './control-button';
import ControlSelect from './selects/control';
Expand All @@ -26,6 +26,14 @@ class ControlButtons extends Component {
actionsDict[value].call();
}

_getShowTestsOptions() {
const viewModes = Object.values(ViewMode).map(value => ({value, content: capitalize(value)}));

return this.props.isStatisImageAccepterEnabled
? viewModes
: viewModes.filter(viewMode => ![ViewMode.STAGED, ViewMode.COMMITED].includes(viewMode.value));
}

render() {
const {actions, view} = this.props;

Expand All @@ -36,7 +44,7 @@ class ControlButtons extends Component {
label="Show tests"
value={view.viewMode}
handler={actions.changeViewMode}
options = {Object.values(ViewMode).map((value) => ({value, content: capitalize(value)}))}
options = {this._getShowTestsOptions()}
/>
<ControlSelect
size='m'
Expand Down Expand Up @@ -73,6 +81,6 @@ class ControlButtons extends Component {
}

export default connect(
({view}) => ({view}),
({view, staticImageAccepter: {enabled}}) => ({view, isStatisImageAccepterEnabled: enabled}),
(dispatch) => ({actions: bindActionCreators(actions, dispatch)})
)(ControlButtons);
57 changes: 43 additions & 14 deletions lib/static/components/controls/common-filters.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
'use strict';

import React, {Component} from 'react';
import React from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as actions from '../../modules/actions';
import TestNameFilterInput from './test-name-filter-input';
import StrictMatchFilterInput from './strict-match-filter-input';
import ShowCheckboxesInput from './show-checkboxes-input';
import BrowserList from './browser-list';
import ControlButton from './control-button';
import AcceptOpenedButton from './accept-opened-button';

class CommonFilters extends Component {
render() {
const {filteredBrowsers, browsers, gui, actions} = this.props;
const CommonFilters = (props) => {
const onCommitChanges = () => {
props.actions.staticAccepterOpenConfirm();
}

const renderStaticImageAccepterControls = () => {
const {staticImageAccepter} = props;

if (!staticImageAccepter.enabled) {
return null;
}

return (
<div className="control-container control-filters">
<BrowserList
available={browsers}
selected={filteredBrowsers}
onChange={actions.selectBrowsers}
<div className='static-image-accepter'>
<AcceptOpenedButton isSuiteContol={true} />
<ControlButton
label={`Commit ${staticImageAccepter.imagesToCommitCount} images`}
title="Send request with imagesInfo to 'staticImageAccepter.serviceUrl'"
isDisabled={staticImageAccepter.imagesToCommitCount === 0}
isSuiteControl={true}
handler={onCommitChanges}
/>
<TestNameFilterInput/>
<StrictMatchFilterInput/>
{gui && <ShowCheckboxesInput/>}
</div>
);
)
}

return (
<div className="control-container control-filters">
<BrowserList
available={props.browsers}
selected={props.filteredBrowsers}
onChange={props.actions.selectBrowsers}
/>
<TestNameFilterInput/>
<StrictMatchFilterInput/>
{props.gui && <ShowCheckboxesInput/>}
{renderStaticImageAccepterControls()}
</div>
);
}

export default connect(
({view, browsers, gui}) => ({filteredBrowsers: view.filteredBrowsers, browsers, gui}),
({view, browsers, gui, staticImageAccepter}) => ({
filteredBrowsers: view.filteredBrowsers,
browsers,
gui,
staticImageAccepter,
}),
(dispatch) => ({actions: bindActionCreators(actions, dispatch)})
)(CommonFilters);
4 changes: 3 additions & 1 deletion lib/static/components/modals/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const types = {
FIND_SAME_DIFFS: 'FindSameDiffs',
SCREENSHOT_ACCEPTER: 'ScreenshotAccepter'
SCREENSHOT_ACCEPTER: 'ScreenshotAccepter',
STATIC_ACCEPTER_CONFIRM: 'StaticAccepterConfirm'
};
export {default as FindSameDiffs} from './find-same-diffs';
export {default as ScreenshotAccepter} from './screenshot-accepter';
export {default as StaticAccepterConfirm} from './static-accepter-confirm';
Loading

0 comments on commit 0eb2c82

Please sign in to comment.