diff --git a/lib/adapters/test-result/testplane.ts b/lib/adapters/test-result/testplane.ts index 2b43f38c2..457703bec 100644 --- a/lib/adapters/test-result/testplane.ts +++ b/lib/adapters/test-result/testplane.ts @@ -5,7 +5,14 @@ import type {Test as TestplaneTest} from 'testplane'; import {ValueOf} from 'type-fest'; import {ERROR, FAIL, SUCCESS, TestStatus, UNKNOWN_SESSION_ID, UPDATED} from '../../constants'; -import {getError, hasUnrelatedToScreenshotsErrors, isImageDiffError, isNoRefImageError, wrapLinkByTag} from '../../common-utils'; +import { + getError, + hasUnrelatedToScreenshotsErrors, + isImageDiffError, + isInvalidRefImageError, + isNoRefImageError, + wrapLinkByTag +} from '../../common-utils'; import { ErrorDetails, TestplaneSuite, @@ -146,6 +153,14 @@ export class TestplaneTestResultAdapter implements ReporterTestResult { refImg: assertResult.refImg, actualImg: assertResult.currImg } satisfies ImageInfoNoRef; + } else if (isInvalidRefImageError(assertResult)) { + return { + status: ERROR, + stateName: assertResult.stateName, + error: _.pick(assertResult, ['message', 'name', 'stack']), + refImg: assertResult.refImg, + actualImg: assertResult.currImg + } satisfies ImageInfoNoRef; } else if ((assertResult as {isUpdated?: boolean}).isUpdated) { return { status: UPDATED, diff --git a/lib/common-utils.ts b/lib/common-utils.ts index 2fe6b0c07..6b96ac1f8 100644 --- a/lib/common-utils.ts +++ b/lib/common-utils.ts @@ -26,7 +26,7 @@ import { ImageInfoWithState, TestError } from './types'; -import {ErrorName, ImageDiffError, NoRefImageError} from './errors'; +import {ErrorName, ImageDiffError, InvalidRefImageError, NoRefImageError} from './errors'; import type {ReporterTestResult} from './adapters/test-result'; export const getShortMD5 = (str: string): string => { @@ -129,6 +129,10 @@ export const isNoRefImageError = (error?: unknown): error is NoRefImageError => return (error as {name?: string})?.name === ErrorName.NO_REF_IMAGE; }; +export const isInvalidRefImageError = (error?: unknown): error is InvalidRefImageError => { + return (error as {name?: string})?.name === ErrorName.INVALID_REF_IMAGE; +}; + export const isImageError = (error?: unknown): boolean => { return isAssertViewError(error) || isImageDiffError(error) || isNoRefImageError(error); }; diff --git a/lib/errors/index.ts b/lib/errors/index.ts index 3cad41efb..48a00c2d7 100644 --- a/lib/errors/index.ts +++ b/lib/errors/index.ts @@ -6,6 +6,7 @@ export const ErrorName = { GENERAL_ERROR: 'Error', IMAGE_DIFF: 'ImageDiffError', NO_REF_IMAGE: 'NoRefImageError', + INVALID_REF_IMAGE: 'InvalidRefImageError', ASSERT_VIEW: 'AssertViewError' } as const; export type ErrorName = ValueOf; @@ -34,3 +35,13 @@ export interface NoRefImageError { currImg: ImageFile; refImg: ImageFile; } + +/** @note Can be thrown by Testplane after version 8.20.7 */ +export interface InvalidRefImageError { + name: ErrorNames['INVALID_REF_IMAGE']; + stateName: string; + message: string; + stack?: string; + currImg: ImageFile; + refImg: ImageFile; +} diff --git a/lib/static/components/state/state-error.jsx b/lib/static/components/state/state-error.jsx index 8e67d6832..ed202aaae 100644 --- a/lib/static/components/state/state-error.jsx +++ b/lib/static/components/state/state-error.jsx @@ -13,7 +13,14 @@ import * as actions from '../../modules/actions'; import ErrorDetails from './error-details'; import Details from '../details'; import {ERROR_TITLE_TEXT_LENGTH} from '../../../constants/errors'; -import {isAssertViewError, isImageDiffError, isNoRefImageError, mergeSnippetIntoErrorStack, trimArray} from '../../../common-utils'; +import { + isAssertViewError, + isImageDiffError, + isInvalidRefImageError, + isNoRefImageError, + mergeSnippetIntoErrorStack, + trimArray +} from '../../../common-utils'; import {Card} from '@gravity-ui/uikit'; import {Screenshot} from '@/static/new-ui/components/Screenshot'; @@ -51,7 +58,7 @@ class StateError extends Component { _drawImage() { const {image, error} = this.props; - if (image.actualImg && isNoRefImageError(error)) { + if (image.actualImg && (isNoRefImageError(error) || isInvalidRefImageError(error))) { return ; } diff --git a/lib/static/modules/utils/index.js b/lib/static/modules/utils/index.js index 602318579..ce8b3ca4f 100644 --- a/lib/static/modules/utils/index.js +++ b/lib/static/modules/utils/index.js @@ -1,7 +1,18 @@ 'use strict'; import {isEmpty, find, isFunction, flatMap} from 'lodash'; -import {isIdleStatus, isSuccessStatus, isUpdatedStatus, isFailStatus, isErrorStatus, isSkippedStatus, isNoRefImageError, isStagedStatus, isCommitedStatus} from '../../../common-utils'; +import { + isIdleStatus, + isSuccessStatus, + isUpdatedStatus, + isFailStatus, + isErrorStatus, + isSkippedStatus, + isNoRefImageError, + isStagedStatus, + isCommitedStatus, + isInvalidRefImageError +} from '../../../common-utils'; import {ViewMode, SECTIONS, RESULT_KEYS, KEY_DELIMITER} from '../../../constants'; import default_ from './state'; const {applyStateUpdate, ensureDiffProperty, getUpdatedProperty} = default_; @@ -37,7 +48,7 @@ export function isNodeSuccessful(node) { * @returns {boolean} */ export function isAcceptable({status, error}) { - return isErrorStatus(status) && isNoRefImageError(error) || isFailStatus(status) || isSkippedStatus(status); + return isErrorStatus(status) && isNoRefImageError(error) || isFailStatus(status) || isSkippedStatus(status) || isInvalidRefImageError(error); } function isScreenGuiRevertable({gui, image, isLastResult}) { diff --git a/lib/static/new-ui/components/AssertViewStatus/index.tsx b/lib/static/new-ui/components/AssertViewStatus/index.tsx index 4fa582abb..b8dcdb4b1 100644 --- a/lib/static/new-ui/components/AssertViewStatus/index.tsx +++ b/lib/static/new-ui/components/AssertViewStatus/index.tsx @@ -2,8 +2,8 @@ import React, {ReactNode} from 'react'; import {ImageEntity, ImageEntityError} from '@/static/new-ui/types/store'; import {TestStatus} from '@/constants'; import {Icon} from '@gravity-ui/uikit'; -import {FileCheck, CircleCheck, SquareExclamation, SquareXmark, FileLetterX, ArrowRightArrowLeft} from '@gravity-ui/icons'; -import {isNoRefImageError} from '@/common-utils'; +import {FileCheck, CircleCheck, SquareExclamation, SquareXmark, FileLetterX, FileExclamation, ArrowRightArrowLeft} from '@gravity-ui/icons'; +import {isInvalidRefImageError, isNoRefImageError} from '@/common-utils'; import styles from './index.module.css'; interface AssertViewStatusProps { @@ -19,6 +19,8 @@ export function AssertViewStatus({image}: AssertViewStatusProps): ReactNode { status = <>Images match; } else if (isNoRefImageError((image as ImageEntityError).error)) { status = <>Reference not found; + } else if (isInvalidRefImageError((image as ImageEntityError).error)) { + status = <>Reference is broken; } else if (image.status === TestStatus.FAIL) { status = <>Difference detected; } else if (image.status === TestStatus.UPDATED) {