Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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 @@ -15,3 +15,4 @@ hot
/testplane-report
tmp
**/playwright-report
**/html-report/*
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ module.exports = {
files: ['test/**'],
rules: {
// For convenient casting of test objects
'@typescript-eslint/no-explicit-any': 'off'
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-restricted-imports': 'off'
}
}
]
Expand Down
98 changes: 98 additions & 0 deletions .github/workflows/component-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Testplane Component Tests

on:
pull_request:
branches: [ master ]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
testplane-component:
runs-on: ubuntu-latest

permissions:
contents: read
pull-requests: write

env:
DOCKER_IMAGE_NAME: html-reporter-browsers

steps:
- uses: actions/checkout@v4

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build the package
run: npm run build

- name: 'Prepare component tests: Cache browser docker image'
uses: actions/cache@v3
with:
path: ~/.docker/cache
key: docker-browser-image-${{ hashFiles('test/func/docker/Dockerfile') }}

- name: 'Prepare component tests: Pull browser docker image'
run: |
mkdir -p ~/.docker/cache
if [ -f ~/.docker/cache/image.tar ]; then
docker load -i ~/.docker/cache/image.tar
else
docker pull yinfra/html-reporter-browsers
docker save yinfra/html-reporter-browsers -o ~/.docker/cache/image.tar
fi

- name: 'Prepare component tests: Run browser docker image'
run: docker run -d --name ${{ env.DOCKER_IMAGE_NAME }} -it --rm --network=host $(which colima >/dev/null || echo --add-host=host.docker.internal:0.0.0.0) yinfra/html-reporter-browsers

- name: 'component-tests: Run Testplane'
id: 'testplane'
continue-on-error: true
run: npm run component-tests

- name: 'component-tests: Stop browser docker image'
run: |
docker kill ${{ env.DOCKER_IMAGE_NAME }} || true
docker rm ${{ env.DOCKER_IMAGE_NAME }} || true

- name: Upload Testplane html-reporter reports to S3
uses: jakejarvis/s3-sync-action@v0.5.1
with:
args: --acl public-read --follow-symlinks
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://s3.yandexcloud.net/
SOURCE_DIR: "test/component/html-report"
DEST_DIR: "testplane-ci/component-tests-reports/${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}/"

- name: Construct PR comment
run: |
link="https://${{ secrets.AWS_S3_BUCKET }}.s3.yandexcloud.net/testplane-ci/component-tests-reports/${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}/index.html"
if [ "${{ steps.testplane.outcome }}" != "success" ]; then
comment="### ❌ Component tests failed<br><br>[Report](${link})"
echo "PR_COMMENT=${comment}" >> $GITHUB_ENV
else
comment="### ✅ Component tests succeed<br><br>[Report](${link})"
echo "PR_COMMENT=${comment}" >> $GITHUB_ENV
fi

- name: Leave comment to PR with link to Testplane HTML reports
if: github.event.pull_request
uses: thollander/actions-comment-pull-request@v3
with:
message: ${{ env.PR_COMMENT }}
comment-tag: testplane_component_results

- name: Fail the job if any Testplane job is failed
if: ${{ steps.testplane.outcome != 'success' }}
run: exit 1
34 changes: 16 additions & 18 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ jobs:
- name: 'Prepare e2e tests: Generate fixtures'
run: npm run e2e:generate-fixtures || true

- name: 'Prepare e2e tests: Setup env'
run: |
REPORT_PREFIX=testplane-reports
REPORT_DATE=$(date '+%Y-%m-%d')
echo "DEST_REPORTS_DIR=$REPORT_PREFIX/$REPORT_DATE/${{ github.run_id }}/${{ github.run_attempt }}" >> $GITHUB_ENV

- name: 'e2e: Run Testplane'
id: 'testplane'
continue-on-error: true
Expand All @@ -84,25 +78,29 @@ jobs:
- name: Merge Testplane html-reporter reports
working-directory: 'test/func/tests'
run: |
mkdir -p ../../../${{ env.DEST_REPORTS_DIR }}
npx testplane merge-reports reports/*/sqlite.db -d ../../../${{ env.DEST_REPORTS_DIR }}
mkdir -p ../../../e2e-report
npx testplane merge-reports reports/*/sqlite.db -d ../../../e2e-report

- name: Deploy Testplane html-reporter reports
uses: peaceiris/actions-gh-pages@v4
- name: Upload Testplane html-reporter reports to S3
uses: jakejarvis/s3-sync-action@v0.5.1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ${{ env.DEST_REPORTS_DIR }}
destination_dir: ${{ env.DEST_REPORTS_DIR }}
keep_files: true
args: --acl public-read --follow-symlinks
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://s3.yandexcloud.net/
SOURCE_DIR: "e2e-report"
DEST_DIR: "testplane-ci/e2e-tests-reports/${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}/"

- name: Construct PR comment
run: |
link="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ env.DEST_REPORTS_DIR }}"
link="https://${{ secrets.AWS_S3_BUCKET }}.s3.yandexcloud.net/testplane-ci/e2e-tests-reports/${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}/index.html"
if [ "${{ steps.testplane.outcome }}" != "success" ]; then
comment="### ❌ Testplane run failed<br><br>[Report](${link})"
comment="### ❌ E2E tests failed<br><br>[Report](${link})"
echo "PR_COMMENT=${comment}" >> $GITHUB_ENV
else
comment="### ✅ Testplane run succeed<br><br>[Report](${link})"
comment="### ✅ E2E tests succeed<br><br>[Report](${link})"
echo "PR_COMMENT=${comment}" >> $GITHUB_ENV
fi

Expand All @@ -111,7 +109,7 @@ jobs:
uses: thollander/actions-comment-pull-request@v3
with:
message: ${{ env.PR_COMMENT }}
comment-tag: testplane_results
comment-tag: testplane_e2e_results

- name: Fail the job if any Testplane job is failed
if: ${{ steps.testplane.outcome != 'success' }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ html-reporter-*.tgz

**/playwright-report
hermione-report
html-report
testplane-report
test/func/**/report
test/func/**/report-backup
Expand Down
5 changes: 5 additions & 0 deletions lib/constants/diff-modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export const DiffModes = {
id: 'onion-skin',
title: 'Onion skin',
description: 'Onion Skin. Change the image opacity to compare expected and actual images.'
},
TWO_UP_INTERACTIVE: {
id: '2-up-interactive',
title: '2-up Interactive',
description: '2-up Interactive. Compare expected and actual images side by side with synchronized pan and zoom.'
}
} as const;

Expand Down
1 change: 1 addition & 0 deletions lib/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export * from './plugin-events';
export * from './save-formats';
export * from './test-statuses';
export * from './tool-names';
export * from './two-up-modes';
export * from './view-modes';
2 changes: 2 additions & 0 deletions lib/constants/local-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export enum LocalStorageKey {
}

export const TIME_TRAVEL_PLAYER_VISIBILITY_KEY = 'time-travel-player-visibility';
export const TWO_UP_DIFF_VISIBILITY_KEY = '2up-diff-visibility';
export const TWO_UP_FIT_MODE_KEY = '2up-fit-mode';

export enum UiMode {
Old = 'old',
Expand Down
4 changes: 4 additions & 0 deletions lib/constants/two-up-modes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum TwoUpFitMode {
FitToView = 'fit-to-view',
FitToWidth = 'fit-to-width'
}
3 changes: 3 additions & 0 deletions lib/static/modules/action-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export default {
PAGE_SET_SECTION_SIZES: 'PAGE_SET_SECTION_SIZES',
PAGE_SET_BACKUP_SECTION_SIZES: 'PAGE_SET_BACKUP_SECTION_SIZES',
VISUAL_CHECKS_PAGE_SET_CURRENT_NAMED_IMAGE: 'VISUAL_CHECKS_PAGE_SET_CURRENT_NAMED_IMAGE',
VISUAL_CHECKS_TOGGLE_2UP_DIFF_VISIBILITY: 'VISUAL_CHECKS_TOGGLE_2UP_DIFF_VISIBILITY',
VISUAL_CHECKS_SET_2UP_FIT_MODE: 'VISUAL_CHECKS_SET_2UP_FIT_MODE',
VISUAL_CHECKS_SET_DIFF_MODE: 'VISUAL_CHECKS_SET_DIFF_MODE',
UPDATE_LOADING_PROGRESS: 'UPDATE_LOADING_PROGRESS',
UPDATE_LOADING_VISIBILITY: 'UPDATE_LOADING_VISIBILITY',
UPDATE_LOADING_TITLE: 'UPDATE_LOADING_TITLE',
Expand Down
30 changes: 29 additions & 1 deletion lib/static/modules/actions/visual-checks-page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import actionNames from '@/static/modules/action-names';
import {Action} from '@/static/modules/actions/types';
import {DiffModeId, TwoUpFitMode} from '@/constants';

export type VisualChecksPageSetCurrentNamedImageAction = Action<typeof actionNames.VISUAL_CHECKS_PAGE_SET_CURRENT_NAMED_IMAGE, {
namedImageId: string;
Expand All @@ -9,5 +10,32 @@ export const visualChecksPageSetCurrentNamedImage = (namedImageId: string): Visu
return {type: actionNames.VISUAL_CHECKS_PAGE_SET_CURRENT_NAMED_IMAGE, payload: {namedImageId}};
};

export type Toggle2UpDiffVisibilityAction = Action<typeof actionNames.VISUAL_CHECKS_TOGGLE_2UP_DIFF_VISIBILITY, {
isVisible: boolean;
}>;

export const toggle2UpDiffVisibility = (isVisible: boolean): Toggle2UpDiffVisibilityAction => {
return {type: actionNames.VISUAL_CHECKS_TOGGLE_2UP_DIFF_VISIBILITY, payload: {isVisible}};
};

export type Set2UpFitModeAction = Action<typeof actionNames.VISUAL_CHECKS_SET_2UP_FIT_MODE, {
fitMode: TwoUpFitMode;
}>;

export const set2UpFitMode = (fitMode: TwoUpFitMode): Set2UpFitModeAction => {
return {type: actionNames.VISUAL_CHECKS_SET_2UP_FIT_MODE, payload: {fitMode}};
};

export type SetVisualChecksDiffModeAction = Action<typeof actionNames.VISUAL_CHECKS_SET_DIFF_MODE, {
diffModeId: DiffModeId;
}>;

export const setVisualChecksDiffMode = (diffModeId: DiffModeId): SetVisualChecksDiffModeAction => {
return {type: actionNames.VISUAL_CHECKS_SET_DIFF_MODE, payload: {diffModeId}};
};

export type VisualChecksPageAction =
| VisualChecksPageSetCurrentNamedImageAction;
| VisualChecksPageSetCurrentNamedImageAction
| Toggle2UpDiffVisibilityAction
| Set2UpFitModeAction
| SetVisualChecksDiffModeAction;
9 changes: 6 additions & 3 deletions lib/static/modules/default-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {ViewMode} from '../../constants/view-modes';
import {DiffModes} from '../../constants/diff-modes';
import {EXPAND_ERRORS} from '../../constants/expand-modes';
import {RESULT_KEYS} from '../../constants/group-tests';
import {ToolName} from '../../constants';
import {ToolName, TwoUpFitMode} from '../../constants';
import {Page, SortDirection, State, TreeViewMode} from '@/static/new-ui/types/store';
import {MIN_SECTION_SIZE_PERCENT} from '../new-ui/features/suites/constants';

Expand Down Expand Up @@ -119,7 +119,8 @@ export default Object.assign({config: configDefaults}, {
nameFilter: '',
useRegexFilter: false,
useMatchCaseFilter: false,
filteredBrowsers: []
filteredBrowsers: [],
diffMode: DiffModes.TWO_UP_INTERACTIVE.id
},
loading: {
taskTitle: 'Loading Testplane UI',
Expand Down Expand Up @@ -165,7 +166,9 @@ export default Object.assign({config: configDefaults}, {
},
[Page.visualChecksPage]: {
sectionSizes: [MIN_SECTION_SIZE_PERCENT, 100 - MIN_SECTION_SIZE_PERCENT],
backupSectionSizes: [MIN_SECTION_SIZE_PERCENT, 100 - MIN_SECTION_SIZE_PERCENT]
backupSectionSizes: [MIN_SECTION_SIZE_PERCENT, 100 - MIN_SECTION_SIZE_PERCENT],
is2UpDiffVisible: true,
twoUpFitMode: TwoUpFitMode.FitToWidth
},
staticImageAccepterToolbar: {
offset: {x: 0, y: 0}
Expand Down
4 changes: 3 additions & 1 deletion lib/static/modules/middlewares/local-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default store => next => action => {

localStorageWrapper.setItem('app.suitesPage.viewMode', app.suitesPage.viewMode);
localStorageWrapper.setItem('app.visualChecksPage.viewMode', app.visualChecksPage.viewMode);
localStorageWrapper.setItem('app.visualChecksPage.diffMode', app.visualChecksPage.diffMode);
}

return result;
Expand All @@ -28,6 +29,7 @@ function shouldUpdateLocalStorage(actionType) {
actionNames.INIT_GUI_REPORT,
actionNames.INIT_STATIC_REPORT,
actionNames.CHANGE_VIEW_MODE,
actionNames.SET_DIFF_MODE
actionNames.SET_DIFF_MODE,
actionNames.VISUAL_CHECKS_SET_DIFF_MODE
].includes(actionType);
}
6 changes: 4 additions & 2 deletions lib/static/modules/reducers/filters.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Page, State} from '@/static/new-ui/types/store';
import actionNames from '@/static/modules/action-names';
import {FiltersAction, InitGuiReportAction, InitStaticReportAction} from '@/static/modules/actions';
import {ViewMode} from '@/constants';
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';
Expand All @@ -26,6 +26,7 @@ export default (state: State, action: FiltersAction | InitGuiReportAction | Init
case actionNames.INIT_STATIC_REPORT: {
const suitesPageViewMode = localStorageWrapper.getItem('app.suitesPage.viewMode', ViewMode.ALL) as ViewMode;
const visualChecksPageViewMode = localStorageWrapper.getItem('app.visualChecksPage.viewMode', ViewMode.ALL) as ViewMode;
const visualChecksPageDiffMode = localStorageWrapper.getItem('app.visualChecksPage.diffMode', DiffModes.TWO_UP_INTERACTIVE.id) as DiffModeId;

const viewQuery = getViewQuery(window.location.search);

Expand All @@ -41,7 +42,8 @@ export default (state: State, action: FiltersAction | InitGuiReportAction | Init
viewMode: suitesPageViewMode
},
[Page.visualChecksPage]: {
viewMode: visualChecksPageViewMode
viewMode: visualChecksPageViewMode,
diffMode: visualChecksPageDiffMode
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions lib/static/modules/reducers/suites-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {getSuitesTreeViewData} from '@/static/new-ui/features/suites/components/
import {findTreeNodeByBrowserId, findTreeNodeById, getGroupId} from '@/static/new-ui/features/suites/utils';
import * as localStorageWrapper from '../local-storage-wrapper';
import {MIN_SECTION_SIZE_PERCENT} from '@/static/new-ui/features/suites/constants';
import {TIME_TRAVEL_PLAYER_VISIBILITY_KEY} from '@/constants/local-storage';
import {TIME_TRAVEL_PLAYER_VISIBILITY_KEY, TWO_UP_DIFF_VISIBILITY_KEY, TWO_UP_FIT_MODE_KEY} from '@/constants/local-storage';
import {TwoUpFitMode} from '@/constants';

const SECTION_SIZES_LOCAL_STORAGE_KEY = 'suites-page-section-sizes';

Expand Down Expand Up @@ -59,6 +60,8 @@ export default (state: State, action: SomeAction): State => {
) as number[];

const isSnapshotsPlayerVisible = Boolean(localStorageWrapper.getItem(TIME_TRAVEL_PLAYER_VISIBILITY_KEY, true));
const is2UpDiffVisible = Boolean(localStorageWrapper.getItem(TWO_UP_DIFF_VISIBILITY_KEY, true));
const twoUpFitMode = localStorageWrapper.getItem(TWO_UP_FIT_MODE_KEY, TwoUpFitMode.FitToView) as TwoUpFitMode;

return applyStateUpdate(state, {
app: {
Expand All @@ -75,7 +78,9 @@ export default (state: State, action: SomeAction): State => {
isSnapshotsPlayerVisible
},
visualChecksPage: {
sectionSizes: visualChecksSectionSizes
sectionSizes: visualChecksSectionSizes,
is2UpDiffVisible,
twoUpFitMode
}
}
});
Expand Down
Loading
Loading