Skip to content

Commit

Permalink
refactor: re-write actions to typescript and implement new analytics API
Browse files Browse the repository at this point in the history
  • Loading branch information
shadowusr committed Dec 27, 2024
1 parent b9da48a commit 64e09eb
Show file tree
Hide file tree
Showing 74 changed files with 1,294 additions and 1,252 deletions.
4 changes: 2 additions & 2 deletions lib/common-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
COMMITED
} from './constants';

import {CHECKED, INDETERMINATE, UNCHECKED} from './constants/checked-statuses';
import {CHECKED, CheckStatus, INDETERMINATE, UNCHECKED} from './constants/checked-statuses';
import {
ImageBase64,
ImageBuffer,
Expand Down Expand Up @@ -247,7 +247,7 @@ export const normalizeUrls = (urls: string[] = [], baseUrl: string): string[] =>
export const isCheckboxChecked = (status: number): boolean => Number(status) === CHECKED;
export const isCheckboxIndeterminate = (status: number): boolean => Number(status) === INDETERMINATE;
export const isCheckboxUnchecked = (status: number): boolean => Number(status) === UNCHECKED;
export const getToggledCheckboxState = (status: number): number => isCheckboxChecked(status) ? UNCHECKED : CHECKED;
export const getToggledCheckboxState = (status: number): CheckStatus => isCheckboxChecked(status) ? UNCHECKED : CHECKED;

export function getDetailsFileName(testId: string, browserId: string, attempt: number): string {
return `${testId}-${browserId}_${Number(attempt) + 1}_${Date.now()}.json`;
Expand Down
10 changes: 8 additions & 2 deletions lib/static/components/controls/accept-opened-button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import PropTypes from 'prop-types';
import * as actions from '../../modules/actions';
import ControlButton from './control-button';
import {getAcceptableOpenedImageIds} from '../../modules/selectors/tree';
import {AnalyticsContext} from '@/static/new-ui/providers/analytics';

class AcceptOpenedButton extends Component {
static contextType = AnalyticsContext;

static propTypes = {
isSuiteContol: PropTypes.bool,
// from store
Expand All @@ -16,11 +19,14 @@ class AcceptOpenedButton extends Component {
actions: PropTypes.object.isRequired
};

_acceptOpened = () => {
_acceptOpened = async () => {
const analytics = this.context;
await analytics?.trackOpenedScreenshotsAccept({acceptedImagesCount: this.props.acceptableOpenedImageIds.length});

if (this.props.isStaticImageAccepterEnabled) {
this.props.actions.staticAccepterStageScreenshot(this.props.acceptableOpenedImageIds);
} else {
this.props.actions.acceptOpened(this.props.acceptableOpenedImageIds);
this.props.actions.thunkAcceptImages({imageIds: this.props.acceptableOpenedImageIds});
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/controls/custom-gui-controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class CustomGuiControls extends PureComponent {
const onClickHandler = (event, {value}) => {
const controlIndex = controls.findIndex((control) => control.value === value);

actions.runCustomGuiAction({sectionName, groupIndex, controlIndex});
actions.thunkRunCustomGuiAction({sectionName, groupIndex, controlIndex});
};

return map(controls, ({label, value, active}, i) =>
Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/controls/find-same-diffs-button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class FindSameDiffsButton extends Component {
_findSameDiffs = () => {
const {actions, imageId, failedOpenedImageIds, browserName} = this.props;

actions.findSameDiffs(imageId, failedOpenedImageIds, browserName);
actions.thunkFindSameDiffs(imageId, failedOpenedImageIds, browserName);
};

render() {
Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/controls/gui-controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class GuiControls extends Component {
<ControlButton
label="Stop tests"
isDisabled={!running || stopping}
handler={actions.stopTests}
handler={actions.thunkStopTests}
/>
<AcceptOpenedButton />
<CommonControls/>
Expand Down
6 changes: 3 additions & 3 deletions lib/static/components/controls/run-button/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const RunButton = ({actions, autoRun, isDisabled, isRunning, failedTests, checke
const selectFailedTests = () => !shouldDisableFailed && setMode(RunMode.FAILED);
const selectCheckedTests = () => !shouldDisableChecked && setMode(RunMode.CHECKED);

const runAllTests = () => actions.runAllTests();
const runFailedTests = () => actions.runFailedTests(failedTests);
const runCheckedTests = () => actions.retrySuite(checkedTests);
const runAllTests = () => actions.thunkRunAllTests();
const runFailedTests = () => actions.thunkRunFailedTests({tests: failedTests});
const runCheckedTests = () => actions.thunkRunSuite({tests: checkedTests});

const handleRunClick = () => {
const action = {
Expand Down
4 changes: 2 additions & 2 deletions lib/static/components/gui.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import StickyHeader from './sticky-header/gui';
import Loading from './loading';
import ModalContainer from '../containers/modal';
import MainTree from './main-tree';
import CustomScripts from './custom-scripts';
import {CustomScripts} from '../new-ui/components/CustomScripts';
import {ClientEvents} from '../../gui/constants/client-events';
import FaviconChanger from './favicon-changer';
import ExtensionPoint from './extension-point';
Expand Down Expand Up @@ -60,7 +60,7 @@ class Gui extends Component {
});

eventSource.addEventListener(ClientEvents.END, () => {
actions.testsEnd();
actions.thunkTestsEnd();
});
}

Expand Down
12 changes: 9 additions & 3 deletions lib/static/components/modals/screenshot-accepter/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ import {staticImageAccepterPropType} from '../../../modules/static-image-accepte
import {preloadImage} from '../../../modules/utils';

import './style.css';
import {AnalyticsContext} from '@/static/new-ui/providers/analytics';

const PRELOAD_IMAGE_COUNT = 3;

class ScreenshotAccepter extends Component {
static contextType = AnalyticsContext;

static propTypes = {
view: PropTypes.shape({
diffMode: PropTypes.string.isRequired
Expand Down Expand Up @@ -58,6 +61,8 @@ class ScreenshotAccepter extends Component {
for (let i = 1; i <= PRELOAD_IMAGE_COUNT; i++) {
this._preloadAdjacentImages(activeImageIndex, stateNameImageIds, i);
}

this.analytics = this.context;
}

componentDidUpdate() {
Expand Down Expand Up @@ -138,7 +143,7 @@ class ScreenshotAccepter extends Component {
if (this.props.staticImageAccepter.enabled) {
this.props.actions.staticAccepterUndoDelayScreenshot();
} else {
await this.props.actions.undoAcceptImage(imageId, {skipTreeUpdate: true});
await this.props.actions.thunkRevertImages({imageIds: [imageId], shouldCommitUpdatesToTree: false});
this.delayedTestResults.pop();
}

Expand All @@ -164,7 +169,7 @@ class ScreenshotAccepter extends Component {

this.props.actions.staticAccepterStageScreenshot(imageIdsToStage);
} else {
this.props.actions.applyDelayedTestResults(this.delayedTestResults);
this.props.actions.commitAcceptedImagesToTree(this.delayedTestResults);
}

this.props.onClose();
Expand All @@ -184,7 +189,8 @@ class ScreenshotAccepter extends Component {
}

async _acceptScreenshot(imageId, stateName) {
const updatedData = await this.props.actions.screenshotAccepterAccept(imageId);
const updatedData = await this.props.actions.thunkAcceptImages({imageIds: [imageId], shouldCommitUpdatesToTree: false});
this.analytics?.trackScreenshotsAccept();

if (updatedData === null) {
return null;
Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/report.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Loading from './loading';
import StickyHeader from './sticky-header/report';
import ModalContainer from '../containers/modal';
import MainTree from './main-tree';
import CustomScripts from './custom-scripts';
import {CustomScripts} from '../new-ui/components/CustomScripts';
import FaviconChanger from './favicon-changer';
import ExtensionPoint from './extension-point';
import BottomProgressBar from './bottom-progress-bar';
Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/section/body/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function Body(props) {
const onTestRetry = () => {
const {testName, browserName} = props;

props.actions.retryTest({testName, browserName});
props.actions.thunkRunTest({test: {testName, browserName}});
};

const addRetrySwitcher = () => {
Expand Down
2 changes: 1 addition & 1 deletion lib/static/components/section/title/simple.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const SectionTitle = ({name, suiteId, handler, gui, checkStatus, suiteTests, act
const onSuiteRetry = (e) => {
e.stopPropagation();

actions.retrySuite(suiteTests);
actions.thunkRunSuite({tests: suiteTests});
};

const onToggleCheckbox = (e) => {
Expand Down
15 changes: 13 additions & 2 deletions lib/static/components/state/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ import {isSuccessStatus, isFailStatus, isErrorStatus, isUpdatedStatus, isIdleSta
import {Disclosure} from '@gravity-ui/uikit';
import {ChevronsExpandUpRight, Check, ArrowUturnCcwDown} from '@gravity-ui/icons';
import {getDisplayedDiffPercentValue} from '@/static/new-ui/components/DiffViewer/utils';
import {AnalyticsContext} from '@/static/new-ui/providers/analytics';

class State extends Component {
static contextType = AnalyticsContext;

static propTypes = {
result: PropTypes.shape({
status: PropTypes.string.isRequired,
Expand Down Expand Up @@ -49,6 +52,12 @@ class State extends Component {
actions: PropTypes.object.isRequired
};

constructor(props) {
super(props);

this.analytics = this.context;
}

toggleModal = () => {
const {actions, image} = this.props;

Expand All @@ -71,18 +80,20 @@ class State extends Component {
};

onTestAccept = () => {
this.analytics?.trackScreenshotsAccept();

if (this.props.isStaticImageAccepterEnabled) {
this.props.actions.staticAccepterStageScreenshot([this.props.imageId]);
} else {
this.props.actions.acceptTest(this.props.imageId);
this.props.actions.thunkAcceptImages({imageIds: [this.props.imageId]});
}
};

onScreenshotUndo = () => {
if (this.props.isStaticImageAccepterEnabled) {
this.props.actions.staticAccepterUnstageScreenshot([this.props.imageId]);
} else {
this.props.actions.undoAcceptImage(this.props.imageId);
this.props.actions.thunkRevertImages({imageIds: [this.props.imageId]});
}
};

Expand Down
5 changes: 4 additions & 1 deletion lib/static/gui.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import {ThemeProvider} from '@gravity-ui/uikit';

import '@gravity-ui/uikit/styles/fonts.css';
import '@gravity-ui/uikit/styles/styles.css';
import {AnalyticsProvider} from '@/static/new-ui/providers/analytics';

const rootEl = document.getElementById('app');
const root = createRoot(rootEl);

root.render(
<ThemeProvider theme='light'>
<Provider store={store}>
<Gui/>
<AnalyticsProvider>
<Gui/>
</AnalyticsProvider>
</Provider>
</ThemeProvider>
);
5 changes: 4 additions & 1 deletion lib/static/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import {ThemeProvider} from '@gravity-ui/uikit';

import '@gravity-ui/uikit/styles/fonts.css';
import '@gravity-ui/uikit/styles/styles.css';
import {AnalyticsProvider} from '@/static/new-ui/providers/analytics';

const rootEl = document.getElementById('app');
const root = createRoot(rootEl);

root.render(
<ThemeProvider theme='light'>
<Provider store={store}>
<Report/>
<AnalyticsProvider>
<Report/>
</AnalyticsProvider>
</Provider>
</ThemeProvider>
);
20 changes: 3 additions & 17 deletions lib/static/modules/action-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ export default {
TEST_BEGIN: 'TEST_BEGIN',
TEST_RESULT: 'TEST_RESULT',
TESTS_END: 'TESTS_END',
ACCEPT_SCREENSHOT: 'ACCEPT_SCREENSHOT',
ACCEPT_OPENED_SCREENSHOTS: 'ACCEPT_OPENED_SCREENSHOTS',
SCREENSHOT_ACCEPTER_ACCEPT: 'SCREENSHOT_ACCEPTER/ACCEPT',
APPLY_DELAYED_TEST_RESULTS: 'APPLY_DELAYED_TEST_RESULTS',
UNDO_ACCEPT_IMAGES: 'UNDO_ACCEPT_IMAGES',
COMMIT_ACCEPTED_IMAGES_TO_TREE: 'COMMIT_ACCEPTED_IMAGES_TO_TREE',
COMMIT_REVERTED_IMAGES_TO_TREE: 'COMMIT_REVERTED_IMAGES_TO_TREE',
STATIC_ACCEPTER_DELAY_SCREENSHOT: 'STATIC_ACCEPTER_DELAY_SCREENSHOT',
STATIC_ACCEPTER_UNDO_DELAY_SCREENSHOT: 'STATIC_ACCEPTER_UNDO_DELAY_SCREENSHOT',
STATIC_ACCEPTER_STAGE_SCREENSHOT: 'STATIC_ACCEPTER_STAGE_SCREENSHOT',
Expand All @@ -38,24 +35,13 @@ export default {
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_THREE_UP_DIFF: 'VIEW_THREE_UP_DIFF',
VIEW_THREE_UP_SCALED_DIFF: 'VIEW_THREE_UP_SCALED_DIFF',
VIEW_THREE_UP_SCALED_TO_FIT_DIFF: 'VIEW_THREE_UP_SCALED_TO_FIT_DIFF',
VIEW_ONLY_DIFF: 'VIEW_ONLY_DIFF',
VIEW_SWITCH_DIFF: 'VIEW_SWITCH_DIFF',
VIEW_SWIPE_DIFF: 'VIEW_SWIPE_DIFF',
VIEW_ONION_SKIN_DIFF: 'VIEW_ONION_SKIN_DIFF',
SET_DIFF_MODE: 'SET_DIFF_MODE',
PROCESS_BEGIN: 'PROCESS_BEGIN',
PROCESS_END: 'PROCESS_END',
RUN_CUSTOM_GUI_ACTION: 'RUN_CUSTOM_GUI_ACTION',
BROWSERS_SELECTED: 'BROWSERS_SELECTED',
COPY_SUITE_NAME: 'COPY_SUITE_NAME',
VIEW_IN_BROWSER: 'VIEW_IN_BROWSER',
COPY_TEST_LINK: 'COPY_TEST_LINK',
TOGGLE_SUITE_SECTION: 'TOGGLE_SUITE_SECTION',
TOGGLE_BROWSER_SECTION: 'TOGGLE_BROWSER_SECTION',
TOGGLE_META_INFO: 'TOGGLE_META_INFO',
TOGGLE_PAGE_SCREENSHOT: 'TOGGLE_PAGE_SCREENSHOT',
TOGGLE_TESTS_GROUP: 'TOGGLE_TESTS_GROUP',
TOGGLE_SUITE_CHECKBOX: 'TOGGLE_SUITE_CHECKBOX',
TOGGLE_GROUP_CHECKBOX: 'TOGGLE_GROUP_CHECKBOX',
Expand Down
25 changes: 25 additions & 0 deletions lib/static/modules/actions/custom-gui.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import axios from 'axios';
import actionNames from '@/static/modules/action-names';
import {type Action, AppThunk} from '@/static/modules/actions/types';
import {createNotificationError} from '@/static/modules/actions/notifications';
import {CustomGuiActionPayload} from '@/adapters/tool/types';

export type RunCustomGuiAction = Action<typeof actionNames.RUN_CUSTOM_GUI_ACTION, CustomGuiActionPayload>;
export const runCustomGui = (payload: RunCustomGuiAction['payload']): RunCustomGuiAction => ({type: actionNames.RUN_CUSTOM_GUI_ACTION, payload});

export const thunkRunCustomGuiAction = (payload: CustomGuiActionPayload): AppThunk => {
return async (dispatch) => {
try {
const {sectionName, groupIndex, controlIndex} = payload;

await axios.post('/run-custom-gui-action', {sectionName, groupIndex, controlIndex});

dispatch(runCustomGui(payload));
} catch (e: unknown) {
dispatch(createNotificationError('runCustomGuiAction', e as Error));
}
};
};

export type CustomGuiAction =
| RunCustomGuiAction;
36 changes: 36 additions & 0 deletions lib/static/modules/actions/filter-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import actionNames from '@/static/modules/action-names';
import type {Action} from '@/static/modules/actions/types';
import {setFilteredBrowsers} from '@/static/modules/query-params';
import {BrowserItem} from '@/types';
import {ViewMode} from '@/constants';

export type UpdateTestNameFilterAction = Action<typeof actionNames.VIEW_UPDATE_FILTER_BY_NAME, string>;
export const updateTestNameFilter = (testNameFilter: UpdateTestNameFilterAction['payload']): UpdateTestNameFilterAction => {
return {type: actionNames.VIEW_UPDATE_FILTER_BY_NAME, payload: testNameFilter};
};

export type SetStrictMatchFilterAction = Action<typeof actionNames.VIEW_SET_STRICT_MATCH_FILTER, boolean>;
export const setStrictMatchFilter = (strictMatchFilter: SetStrictMatchFilterAction['payload']): SetStrictMatchFilterAction => {
return {type: actionNames.VIEW_SET_STRICT_MATCH_FILTER, payload: strictMatchFilter};
};

export type SelectBrowsersAction = Action<typeof actionNames.BROWSERS_SELECTED, {
browsers: BrowserItem[];
}>;
export const selectBrowsers = (browsers: BrowserItem[]): SelectBrowsersAction => {
setFilteredBrowsers(browsers);

return {
type: actionNames.BROWSERS_SELECTED,
payload: {browsers}
};
};

export type ChangeViewModeAction = Action<typeof actionNames.CHANGE_VIEW_MODE, ViewMode>;
export const changeViewMode = (payload: ChangeViewModeAction['payload']): ChangeViewModeAction => ({type: actionNames.CHANGE_VIEW_MODE, payload});

export type FilterTestsAction =
| UpdateTestNameFilterAction
| SetStrictMatchFilterAction
| SelectBrowsersAction
| ChangeViewModeAction;
Loading

0 comments on commit 64e09eb

Please sign in to comment.