Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ tmp
**/playwright-report
**/html-report/*
examples/**
wt/**
Comment thread
shadowusr marked this conversation as resolved.
12 changes: 12 additions & 0 deletions lib/static/modules/query-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ export function decodeBrowsers(browsers) {
.map(decode);
}

export function expandBrowserVersions(filteredBrowsers, availableBrowsers) {
return filteredBrowsers.map(filteredBrowser => {
if (isEmpty(filteredBrowser.versions)) {
const availableBrowser = availableBrowsers.find(b => b.id === filteredBrowser.id);
if (availableBrowser) {
return {id: filteredBrowser.id, versions: [...availableBrowser.versions]};
}
}
return filteredBrowser;
});
}

export function setFilteredBrowsers(browsers) {
const urlExtendedWithBrowsers = appendQuery(
window.location.href,
Expand Down
3 changes: 3 additions & 0 deletions lib/static/modules/reducers/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {DiffModeId, DiffModes, ViewMode} from '@/constants';
import {BrowserItem} from '@/types';
import * as localStorageWrapper from '@/static/modules/local-storage-wrapper';
import {getViewQuery} from '@/static/modules/custom-queries';
import {expandBrowserVersions} from '@/static/modules/query-params';
import {isEmpty} from 'lodash';
import {applyStateUpdate} from '@/static/modules/utils/state';

Expand Down Expand Up @@ -33,6 +34,8 @@ export default (state: State, action: FiltersAction | InitGuiReportAction | Init

if (isEmpty(viewQuery.filteredBrowsers)) {
viewQuery.filteredBrowsers = state.browsers;
} else {
viewQuery.filteredBrowsers = expandBrowserVersions(viewQuery.filteredBrowsers as BrowserItem[], state.browsers);
}

const newState = applyStateUpdate(
Expand Down
42 changes: 41 additions & 1 deletion lib/static/new-ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,44 @@ a:hover {

b {
font-weight: 500;
}
}


.toaster {
border: 1px solid rgb(229, 231, 235);
box-shadow: rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px !important;
margin-right: 10px;
margin-bottom: 20px !important;
}

@keyframes toast-appear {
from {
opacity: 0;
scale: 0.95;
}

to {
opacity: 1;
scale: 1;
}
}

.toaster:global(.g-toast-animation-desktop_enter_active) {
animation: toast-appear .15s forwards ease;
}

.toaster:global(.g-toast-animation-desktop_exit_active) {
animation: toast-appear .15s forwards ease reverse;
}

.toaster :global(.g-toast__title) {
font-weight: 450;
}

.toaster :global(.g-toast__content) {
color: var(--g-color-private-black-400);
}

.toaster__icon--error {
color: var(--g-color-private-red-600-solid);
}
73 changes: 32 additions & 41 deletions lib/static/new-ui/components/BrowsersSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {PlanetEarth} from '@gravity-ui/icons';
import {Button, Flex, Icon, Select, SelectRenderControlProps, SelectRenderOption} from '@gravity-ui/uikit';
import React, {ReactNode, Ref, useEffect, useState} from 'react';
import {Button, Flex, Icon, Select, SelectRenderControlProps, SelectRenderOption, useSelectOptions} from '@gravity-ui/uikit';
import React, {ReactNode, Ref, useEffect, useMemo, useState} from 'react';
import {useDispatch, useSelector} from 'react-redux';

import {selectBrowsers} from '@/static/modules/actions';
Expand Down Expand Up @@ -75,48 +75,40 @@ export function BrowsersSelect(): ReactNode {
setSelectedBrowsers(selectedItems);
};

const renderOptions = (): React.JSX.Element | React.JSX.Element[] => {
const getOptionData = (browser: BrowserItem, version: string, content: string): {value: string; content: string; data: {id: string; version: string}} => ({
value: serializeBrowserData(browser.id, version),
content,
data: {id: browser.id, version}
});

const rawOptions = useMemo(() => {
const browsersWithMultipleVersions = browsers.filter(browser => browser.versions.length > 1);
const browsersWithSingleVersion = browsers.filter(browser => browser.versions.length === 1);

const getOptionProps = (browser: BrowserItem, version: string): {value: string; content: string; data: Record<string, unknown>} => ({
value: serializeBrowserData(browser.id, version),
content: browser.id,
data: {id: browser.id, version}
});

if (browsersWithMultipleVersions.length === 0) {
// If there are no browsers with multiple versions, we want to render a simple plain list
return browsers.map(browser => <Select.Option
key={browser.id}
{...getOptionProps(browser, browser.versions[0])}
/>);
// If there are no browsers with multiple versions, we want to render a simple flat list
return browsers.map(browser => getOptionData(browser, browser.versions[0], browser.id));
} else {
// Otherwise render browser version groups and place all browsers with single version into "Other" group
return (
<>
{browsersWithMultipleVersions.map(browser => (
<Select.OptionGroup key={browser.id} label={browser.id}>
{browser.versions.map(version => (
<Select.Option
key={version}
{...getOptionProps(browser, version)}
/>
))}
</Select.OptionGroup>
))}
<Select.OptionGroup label="Other">
{browsersWithSingleVersion.map(browser => (
<Select.Option
key={browser.id}
{...getOptionProps(browser, browser.versions[0])}
/>
))}
</Select.OptionGroup>
</>
);
// Otherwise render browser version groups and place all browsers with a single version in the "Other" group
const groups: {label: string; options: ReturnType<typeof getOptionData>[]}[] = [];

browsersWithMultipleVersions.forEach(browser => {
groups.push({
label: browser.id,
options: browser.versions.map(version => getOptionData(browser, version, version))
});
});

groups.push({
label: 'Other',
options: browsersWithSingleVersion.map(browser => getOptionData(browser, browser.versions[0], browser.id))
});

return groups;
}
};
}, [browsers]);

const options = useSelectOptions({options: rawOptions});

const isInitialized = useSelector(getIsInitialized);

Expand Down Expand Up @@ -171,6 +163,7 @@ export function BrowsersSelect(): ReactNode {
<Select
disablePortal
value={selected}
options={options}
multiple={true}
hasCounter
filterable
Expand All @@ -182,9 +175,7 @@ export function BrowsersSelect(): ReactNode {
onUpdate={onUpdate}
onFocus={onFocus}
onClose={onClose}
>
{renderOptions()}
</Select>
/>
</>
);
}
39 changes: 0 additions & 39 deletions lib/static/new-ui/components/GuiniToolbarOverlay/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,42 +65,3 @@
.modal-button-primary {
composes: regular-button from global, action-button from global;
}

.error-toaster {
border: 1px solid rgb(229, 231, 235);
box-shadow: rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px !important;
margin-right: 10px;
margin-bottom: 20px !important;
}

@keyframes toast-appear {
from {
opacity: 0;
scale: 0.95;
}

to {
opacity: 1;
scale: 1;
}
}

.error-toaster:global(.g-toast-animation-desktop_enter_active) {
animation: toast-appear .15s forwards ease;
}

.error-toaster:global(.g-toast-animation-desktop_exit_active) {
animation: toast-appear .15s forwards ease reverse;
}

.error-toaster :global(.g-toast__title) {
font-weight: 450;
}

.error-toaster :global(.g-toast__content) {
color: var(--g-color-private-black-400);
}

.error-toaster-icon {
color: var(--g-color-private-red-600-solid);
}
4 changes: 2 additions & 2 deletions lib/static/new-ui/components/GuiniToolbarOverlay/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ export function GuiniToolbarOverlay(): ReactNode {
content: result.error.message + '. See console for details.',
isClosable: true,
autoHiding: 5000,
renderIcon: () => <TriangleExclamation className={styles.errorToasterIcon} width={20} height={20} />,
className: styles.errorToaster
renderIcon: () => <TriangleExclamation className='toaster__icon--error' width={20} height={20} />,
className: 'toaster'
});
}
};
Expand Down
2 changes: 1 addition & 1 deletion lib/static/new-ui/components/SuiteTitle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function SuiteTitle(props: SuiteTitleProps): ReactNode {
))}
</div>}
<div className={styles.titleContainer}>
<h2 className={classNames('text-display-1')}>
<h2 className={classNames('text-display-1')} data-qa="suite-title">
{suiteName ?? 'Unknown Suite'}
</h2>
<div className={styles.labelsContainer}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ import {getIconByStatus} from '@/static/new-ui/utils';
import {Page} from '@/constants';
import {usePage} from '@/static/new-ui/hooks/usePage';
import {useHotkey} from '@/static/new-ui/hooks/useHotkey';
import {useLegacyUrlMigration} from '@/static/new-ui/hooks/useLegacyUrlMigration';
import {changeTestRetry, setCurrentTreeNode, setStrictMatchFilter} from '@/static/modules/actions';
import {getUrl} from '@/static/new-ui/utils/getUrl';

export function SuitesPage(): ReactNode {
const page = usePage();

useLegacyUrlMigration();

const currentResult = useSelector(getCurrentResult);
const treeData = useSelector(getSuitesTreeViewData);
const resultImages = useSelector(getCurrentResultImages);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {createSelector} from 'reselect';
import {
getAllRootGroupIds,
getBrowsers,
getBrowsersList,
getBrowsersState,
getGroups,
getImages,
Expand All @@ -18,14 +19,14 @@ import {State} from '@/static/new-ui/types/store';

// Converts the existing store structure to the one that can be consumed by GravityUI
export const getSuitesTreeViewData = createSelector(
[getGroups, getSuites, getAllRootGroupIds, getBrowsers, getBrowsersState, getResults, getImages, getTreeViewMode, getSortTestsData],
(groups, suites, rootGroupIds, browsers, browsersState, results, images, treeViewMode, sortTestsData): TreeViewData => {
[getGroups, getSuites, getAllRootGroupIds, getBrowsers, getBrowsersState, getResults, getImages, getTreeViewMode, getSortTestsData, getBrowsersList],
(groups, suites, rootGroupIds, browsers, browsersState, results, images, treeViewMode, sortTestsData, browsersList): TreeViewData => {
const currentSortDirection = sortTestsData.currentDirection;
const currentSortExpression = sortTestsData.availableExpressions
.find(expr => expr.id === sortTestsData.currentExpressionIds[0])
?? sortTestsData.availableExpressions[0];

const entitiesContext = {results, images, suites, treeViewMode, browsersState, browsers, groups, currentSortDirection, currentSortExpression};
const entitiesContext = {results, images, suites, treeViewMode, browsersState, browsers, groups, currentSortDirection, currentSortExpression, browsersList};

const isGroupingEnabled = rootGroupIds.length > 0;
if (isGroupingEnabled) {
Expand Down
16 changes: 14 additions & 2 deletions lib/static/new-ui/features/suites/components/SuitesPage/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import {EntityType, TreeNode, TreeRoot} from '@/static/new-ui/features/suites/components/SuitesPage/types';
import {getEntityType, getGroupId} from '@/static/new-ui/features/suites/utils';
import {isAcceptable} from '@/static/modules/utils';
import {BrowserItem} from '@/types';

export const getTitlePath = (suites: Record<string, SuiteEntity>, entity: SuiteEntity | BrowserEntity | undefined): string[] => {
if (!entity) {
Expand All @@ -44,9 +45,10 @@ export interface EntitiesContext {
treeViewMode: TreeViewMode;
currentSortDirection: SortDirection;
currentSortExpression: SortByExpression;
browsersList: BrowserItem[];
}

export const formatEntityToTreeNodeData = ({results, images, suites, treeViewMode}: EntitiesContext, entity: SuiteEntity | BrowserEntity | GroupEntity, id: string, parentData?: TreeNode['data']): TreeNode['data'] => {
export const formatEntityToTreeNodeData = ({results, images, suites, treeViewMode, browsersList}: EntitiesContext, entity: SuiteEntity | BrowserEntity | GroupEntity, id: string, parentData?: TreeNode['data']): TreeNode['data'] => {
if (isSuiteEntity(entity)) {
return {
id,
Expand Down Expand Up @@ -86,6 +88,16 @@ export const formatEntityToTreeNodeData = ({results, images, suites, treeViewMod
errorStack = stackLines.slice(0, 3).join('\n');
}

// Add version tag for browsers with multiple versions
const tags: string[] = [];
const browserItem = browsersList.find(b => b.id === entity.name);
if (browserItem && browserItem.versions.length > 1) {
const version = lastResult.metaInfo?.browserVersion;
if (version) {
tags.push(version);
}
}

return {
id,
entityType: getEntityType(entity),
Expand All @@ -97,7 +109,7 @@ export const formatEntityToTreeNodeData = ({results, images, suites, treeViewMod
errorStack,
parentData,
skipReason: lastResult.skipReason,
tags: []
tags
};
};

Expand Down
Loading
Loading