diff --git a/lib/static/new-ui/app/App.tsx b/lib/static/new-ui/app/App.tsx index f196616fe..3caa1f850 100644 --- a/lib/static/new-ui/app/App.tsx +++ b/lib/static/new-ui/app/App.tsx @@ -1,4 +1,4 @@ -import {Eye, ListCheck} from '@gravity-ui/icons'; +import {Picture, ListCheck} from '@gravity-ui/icons'; import {ThemeProvider, Toaster, ToasterComponent, ToasterProvider} from '@gravity-ui/uikit'; import '@gravity-ui/uikit/styles/fonts.css'; import '@gravity-ui/uikit/styles/styles.css'; @@ -35,7 +35,7 @@ const pages = [ { title: 'Visual Checks', url: PathNames.visualChecks, - icon: Eye, + icon: Picture, element: , children: [} />] } diff --git a/lib/static/new-ui/components/IconButton/index.tsx b/lib/static/new-ui/components/IconButton/index.tsx index e7c7a582a..d1381b6f7 100644 --- a/lib/static/new-ui/components/IconButton/index.tsx +++ b/lib/static/new-ui/components/IconButton/index.tsx @@ -3,7 +3,7 @@ import React, {KeyboardEventHandler, MouseEventHandler, ReactNode} from 'react'; interface IconButtonProps { icon: ReactNode; - tooltip: ReactNode; + tooltip?: ReactNode; onClick?: MouseEventHandler; onKeyDown?: KeyboardEventHandler; view?: ButtonView; diff --git a/lib/static/new-ui/components/SettingsPanel/index.tsx b/lib/static/new-ui/components/SettingsPanel/index.tsx index f803ce26d..2dfd02026 100644 --- a/lib/static/new-ui/components/SettingsPanel/index.tsx +++ b/lib/static/new-ui/components/SettingsPanel/index.tsx @@ -63,7 +63,7 @@ export function SettingsPanel(): ReactNode { sections.push( URLs in Meta and in test steps' commands are affected by this.}> - + ); diff --git a/lib/static/new-ui/components/TreeViewItemTitle/index.tsx b/lib/static/new-ui/components/TreeViewItemTitle/index.tsx index 8b9a6464e..287457dd0 100644 --- a/lib/static/new-ui/components/TreeViewItemTitle/index.tsx +++ b/lib/static/new-ui/components/TreeViewItemTitle/index.tsx @@ -1,10 +1,11 @@ -import {ArrowRotateLeft, ChevronRight} from '@gravity-ui/icons'; +import _ from 'lodash'; +import {ArrowRotateLeft, ChevronRight, Eye} from '@gravity-ui/icons'; import {Button, Checkbox, Icon} from '@gravity-ui/uikit'; import classNames from 'classnames'; import React from 'react'; import {useDispatch, useSelector} from 'react-redux'; -import {getToggledCheckboxState, isCheckboxChecked, isCheckboxIndeterminate} from '@/common-utils'; +import {getToggledCheckboxState, getUrlWithBase, isCheckboxChecked, isCheckboxIndeterminate} from '@/common-utils'; import {EntityType, TreeViewItemData} from '@/static/new-ui/features/suites/components/SuitesPage/types'; import {toggleBrowserCheckbox, toggleGroupCheckbox, toggleSuiteCheckbox, thunkRunSuite} from '@/static/modules/actions'; import {getAreCheckboxesNeeded, getBrowsers, getBrowsersState, getSuites} from '@/static/new-ui/store/selectors'; @@ -14,6 +15,7 @@ import {RunTestsFeature} from '@/constants'; import {TestSpec} from '@/adapters/tool/types'; import styles from './index.module.css'; import {useIsRunning} from '@/static/new-ui/hooks/useIsRunning'; +import {State} from '@/static/new-ui/types/store'; interface TreeViewItemTitleProps { className?: string; @@ -50,7 +52,25 @@ const getVisibleSuiteBrowsers = ( export function TreeViewItemTitle({item}: TreeViewItemTitleProps): React.JSX.Element { const dispatch = useDispatch(); const areCheckboxesNeeded = useSelector(getAreCheckboxesNeeded); + + const suiteUrl = useSelector((state): string | undefined => { + if (!state.tree.browsers.byId[item.entityId]) { + return; + } + + const lastResult = _.last(state.tree.browsers.byId[item.entityId].resultIds); + + if (lastResult) { + const result = state.tree.results.byId[lastResult]; + + return result.metaInfo?.url ?? result.suiteUrl; + } + + return; + }); + const groups = useSelector(state => state.tree.groups.byId); + const baseHost = useSelector(state => state.view.baseHost); const checkStatus = useSelector(state => getItemCheckStatus(state, item)); const isVisualChecksPage = /\/visual-checks/.test(location.hash); // @todo: remove after implement search on visual checks page @@ -169,6 +189,20 @@ export function TreeViewItemTitle({item}: TreeViewItemTitleProps): React.JSX.Ele
+ {item.entityType === EntityType.Browser && suiteUrl && ( + + )} - Go to Visual Checks + Go to Visual Checks {isEditScreensAvailable && ( <> diff --git a/lib/static/new-ui/features/suites/components/TestStatusBar/index.tsx b/lib/static/new-ui/features/suites/components/TestStatusBar/index.tsx index f792f7d42..0b505729d 100644 --- a/lib/static/new-ui/features/suites/components/TestStatusBar/index.tsx +++ b/lib/static/new-ui/features/suites/components/TestStatusBar/index.tsx @@ -1,8 +1,9 @@ -import React, {ReactNode} from 'react'; +import React, {ReactNode, useMemo} from 'react'; import _ from 'lodash'; import * as icons from '@gravity-ui/icons'; import {useSelector} from 'react-redux'; +import {getUrlWithBase} from '@/common-utils'; import {ResultEntityCommon} from '@/static/new-ui/types/store'; import {getCurrentResult} from '@/static/new-ui/features/suites/selectors'; import {getIconByStatus} from '@/static/new-ui/utils'; @@ -24,12 +25,25 @@ const getSuiteDuration = (suite: ResultEntityCommon): string | undefined => { export const TestStatusBar = (): ReactNode => { const suite = useSelector(getCurrentResult); + const baseHost = useSelector(state => state.view.baseHost); if (!suite) { return null; } - const badges = suite.attachments?.find(({type}) => type === AttachmentType.Badges) as BadgesAttachment; + const badges = useMemo(() => { + const list = [...(suite.attachments?.find(({type}) => type === AttachmentType.Badges) as BadgesAttachment)?.list || []]; + + if (suite?.suiteUrl) { + list.unshift({ + title: 'View in browser', + icon: 'Eye', + url: getUrlWithBase(suite.metaInfo?.url ?? suite.suiteUrl, baseHost) + }); + } + + return list; + }, [suite.metaInfo?.url, suite?.suiteUrl, baseHost]); return (
@@ -43,9 +57,9 @@ export const TestStatusBar = (): ReactNode => { {getSuiteDuration(suite)}
- {(badges?.list && badges.list.length > 0) && ( + {(badges && badges.length > 0) && (
- {badges.list.map((badge: BadgeType) => ( + {badges.map((badge: BadgeType) => ( { 'html-reporter-tester': { enabled: true, path: fixturesPath, + baseHost: 'https://example.com:123', generateBadges: () => [ { title: 'TASK-128', diff --git a/test/func/fixtures/plugins/.testplane.conf.js b/test/func/fixtures/plugins/.testplane.conf.js index b818a1c76..6057e37bc 100644 --- a/test/func/fixtures/plugins/.testplane.conf.js +++ b/test/func/fixtures/plugins/.testplane.conf.js @@ -7,6 +7,7 @@ const {getFixturesConfig} = require('../fixtures.testplane.conf'); module.exports = _.merge(getFixturesConfig(__dirname, 'plugins'), { plugins: { 'html-reporter-tester': { + baseHost: 'https://example.com:123', pluginsEnabled: true, plugins: [ { diff --git a/test/func/fixtures/testplane/.testplane.conf.js b/test/func/fixtures/testplane/.testplane.conf.js index 87ce60190..aa2681a70 100644 --- a/test/func/fixtures/testplane/.testplane.conf.js +++ b/test/func/fixtures/testplane/.testplane.conf.js @@ -12,6 +12,7 @@ module.exports = _.merge(getFixturesConfig(__dirname, 'testplane'), { }, 'html-reporter-tester': { enabled: true, + baseHost: 'https://example.com:123', path: 'report', diffMode: '3-up-scaled-to-fit', generateBadges: () => [ diff --git a/test/func/tests/.testplane.conf.js b/test/func/tests/.testplane.conf.js index 160f6533b..28ea69d70 100644 --- a/test/func/tests/.testplane.conf.js +++ b/test/func/tests/.testplane.conf.js @@ -59,6 +59,7 @@ const config = _.merge(commonConfig, { }, 'html-reporter-tester': { enabled: true, + baseHost: 'https://example.com:123', path: `reports/${projectUnderTest}`, diffMode: '3-up', yandexMetrika: { diff --git a/test/func/tests/common/new-ui/suites-page/view-in-browser.testplane.js b/test/func/tests/common/new-ui/suites-page/view-in-browser.testplane.js new file mode 100644 index 000000000..ca6f20c99 --- /dev/null +++ b/test/func/tests/common/new-ui/suites-page/view-in-browser.testplane.js @@ -0,0 +1,48 @@ +if (process.env.TOOL === 'testplane') { + describe(process.env.TOOL || 'Default', () => { + describe('New UI', () => { + describe('View in browser button behavior', () => { + it('should exist and have correct link on startup', async ({browser}) => { + const treeItem = await browser.$('[data-list-item*="test with image comparison diff/chrom"]'); + await treeItem.moveTo(); + + const eyeElement = await treeItem.$('a[data-qa="view-in-browser-tree"]'); + const link = await eyeElement.getAttribute('href'); + + await expect(eyeElement).toBeClickable(); + expect(link).toBe('https://example.com:123/fixtures/testplane/index.html'); + }); + + it('should change in accordance to the baseHost in header', async ({browser}) => { + const settings = await browser.$('[data-qa="footer-item-settings"]'); + await settings.click(); + + const baseHostInput = await browser.$('[data-qa="base-host"] input'); + await baseHostInput.setValue('http://some-host.dev:33'); + + await settings.click(); + + const treeItem = await browser.$('[data-list-item*="test with image comparison diff/chrom"]'); + await treeItem.moveTo(); + + const eyeElement = await treeItem.$('a[data-qa="view-in-browser-tree"]'); + const link = await eyeElement.getAttribute('href'); + + expect(link).toBe('http://some-host.dev:33/fixtures/testplane/index.html'); + }); + + it('should exist in suite page', async ({browser}) => { + const treeItem = await browser.$('[data-list-item*="test with image comparison diff/chrom"]'); + await treeItem.click(); + + const eyeElement = await browser.$('[data-qa="suite-badges"] a'); + const link = await eyeElement.getAttribute('href'); + + await expect(eyeElement).toBeClickable(); + + expect(link).toBe('https://example.com:123/fixtures/testplane/index.html'); + }); + }); + }); + }); +} diff --git a/test/func/tests/screens/3144090/chrome/menu bar plugins clicked.png b/test/func/tests/screens/3144090/chrome/menu bar plugins clicked.png index df0412441..ba5ac00bf 100644 Binary files a/test/func/tests/screens/3144090/chrome/menu bar plugins clicked.png and b/test/func/tests/screens/3144090/chrome/menu bar plugins clicked.png differ diff --git a/test/func/tests/screens/7407957/chrome/badges.png b/test/func/tests/screens/7407957/chrome/badges.png index 21e8d8208..bf678a77f 100644 Binary files a/test/func/tests/screens/7407957/chrome/badges.png and b/test/func/tests/screens/7407957/chrome/badges.png differ diff --git a/test/func/tests/screens/e219988/chrome/section.png b/test/func/tests/screens/e219988/chrome/section.png index 5c2d3a46c..24837ed9a 100644 Binary files a/test/func/tests/screens/e219988/chrome/section.png and b/test/func/tests/screens/e219988/chrome/section.png differ