From 153b67a9d53066e299b7d91fb8f645013f8f2950 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Wed, 21 Aug 2024 14:36:19 +0800 Subject: [PATCH 1/8] improve swaplists drop area, add visual test doc and command --- docs/TESTING.md | 77 +++++++++++++++++++++- package.json | 1 + src/components/swaplist/_swaplist-new.scss | 2 +- src/components/swaplist/_swaplist.scss | 15 ++++- src/components/swaplist/swaplist.js | 58 ++++++++++------ 5 files changed, 129 insertions(+), 24 deletions(-) diff --git a/docs/TESTING.md b/docs/TESTING.md index 1310964b60..17e2b1c69d 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -44,10 +44,79 @@ npm run test For development purposes you may just want to run one test your focusing on. ```sh -npm run test +npm run test -- component_name +``` + +## Visual Testing with Percy and Playwright + +This project demonstrates how to perform visual testing using Percy and Playwright. Visual testing helps ensure that UI changes do not introduce unexpected visual regressions. The provided example captures visual snapshots of different UI states to verify consistent rendering. + +### Table of Contents + +- [Introduction](#introduction) +- [Example Test](#example-test) +- [Usage](#usage) +- [Best Practices](#best-practices) + +### Introduction + +Visual testing is a crucial part of maintaining a consistent user interface. By comparing the appearance of web pages or components against known good baselines, visual testing tools like Percy can automatically detect unintended visual changes. + +### Example Test + +```javascript +test.describe('snapshot tests', () => { + test('should match the visual snapshot in percy', async ({ page, browserName }) => { + if (browserName !== 'chromium') return; + + // Function to handle the actions and snapshot for specific row option + const captureSnapshot = async (option, snapshotName) => { + await page.locator('#custom-id-actions').click(); + await page.locator(`a[data-option="row-${option}"]`).click(); + + // Capture a Percy snapshot with the specified name + await percySnapshot(page, snapshotName); + }; + + // Capture snapshot for "extra-small" row height + await captureSnapshot('extra-small', 'datagrid-expandable-row-extra-small-padding'); + + // Capture snapshot for "small" row height + await captureSnapshot('small', 'datagrid-expandable-row-small-padding'); + + // Capture snapshot for "medium" row height + await captureSnapshot('medium', 'datagrid-expandable-row-medium-padding'); + + // Capture snapshot for "large" / "Normal" row height + await captureSnapshot('large', 'datagrid-expandable-row-large-padding'); + }); +}); +``` + +### Usage + +To run the visual tests locally, you can use the following command: + +Run all visual tests: + +```sh +PERCY_TOKEN=your-percy-token npm run test:visual ``` -## Visual Regression testing +Run specific tests: + +```sh +PERCY_TOKEN=your-percy-token npm run test:visual -- component_name +``` + +For the visual tests to work, you need to set the `PERCY_TOKEN` environment variable to your Percy token. You can find your Percy token in your Percy project settings. + +### Best Practices for Visual Testing + +- Run Visual Tests in a Stable Environment: Ensure that tests are run in a consistent and stable environment to avoid flaky results. +- Test Across Browsers: Consider capturing snapshots in multiple browsers to catch cross-browser inconsistencies. +- Review Snapshots Regularly: Regularly review and approve or reject snapshot changes to keep the baseline up-to-date. +- Use Percy's Review Workflow: Use Percy's review workflow to collaborate with your team and ensure that visual changes are intentional. ## Debugging Functional Tests @@ -74,6 +143,10 @@ Each component should have a passing test with Axe. This tool will verify a few If your having an issue with one of these tests you can either debug and follow the above steps for debugging a test or you can install the [Axe Chrome Dev Tools Plugin](https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US). This tool should give you the same output as the test when you run the page on port 4000 instead of 3000 as the tests do. +## Contributing + + Contributions are welcome! If you have suggestions or improvements, please submit a pull request. + ## Reusing Tests Across Repos Listing some common differences in reusing the tests. diff --git a/package.json b/package.json index 8d2ecd91c6..b22b33e782 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "test:start-server": "node app/server.js --test-port", "test": "PERCY_LOGLEVEL=silent npx playwright test --reporter=list", "test:build": "npm run build:demoapp && npm run build", + "test:visual": "PERCY_LOGLEVEL=silent npx percy exec -- npx playwright test --reporter=list", "test:coverage": "npx rimraf .nyc_output && npm run build:coverage && npm run test && npx nyc report && open coverage/index.html", "test:coverage:no-build": "npx rimraf .nyc_output && npm run test && npx nyc report && open coverage/index.html", "test:ci": "PERCY_LOGLEVEL=silent npx rimraf .nyc_output && npm run build:coverage && npm run test && npx nyc report", diff --git a/src/components/swaplist/_swaplist-new.scss b/src/components/swaplist/_swaplist-new.scss index 27445bb6ef..ce82a34b2e 100644 --- a/src/components/swaplist/_swaplist-new.scss +++ b/src/components/swaplist/_swaplist-new.scss @@ -25,7 +25,7 @@ .card-content .listview, .widget-content .listview { - li:first-child { + li:first-child:not(.over) { border-top-color: transparent; } } diff --git a/src/components/swaplist/_swaplist.scss b/src/components/swaplist/_swaplist.scss index 7fee91f6c5..a8c5c0d4d9 100755 --- a/src/components/swaplist/_swaplist.scss +++ b/src/components/swaplist/_swaplist.scss @@ -37,6 +37,18 @@ .card-content { width: 100%; + + .listview { + li { + border-radius: 0; + &:last-child { + &.over { + border: 1px dashed $swaplist-border-color !important; + border-bottom-color: inherit; + } + } + } + } } .card-header { @@ -326,7 +338,8 @@ } .over { - border: 1px dashed $swaplist-border-color; + border: 1px dashed $swaplist-border-color !important; + min-height: 40px; } } diff --git a/src/components/swaplist/swaplist.js b/src/components/swaplist/swaplist.js index 9536d5be6f..99a201096a 100644 --- a/src/components/swaplist/swaplist.js +++ b/src/components/swaplist/swaplist.js @@ -102,9 +102,10 @@ SwapList.prototype = { init() { const s = this.settings; + const additionalClass = `${s.additionalClass} .listview`; s.draggable = $.extend(true, SWAPLIST_DEFAULTS.draggable, s.draggable); this.isTouch = env.features.touch; - this.isAdditional = $(`${s.additionalClass} .listview`, this.element).length > 0; + this.isAdditional = $(additionalClass, this.element).length > 0; if (this.isTouch) { this.element.addClass('is-touch'); @@ -136,10 +137,12 @@ SwapList.prototype = { for (let i = 0, l = containers.length; i < l; i++) { const c = containers[i]; - const lv = $(`${c.class} .listview`, this.element); + const listviewContainerClass = `${c.class} .listview`; + const lv = $(listviewContainerClass, this.element); const list = lv.data('listview'); + const searchfieldContainerClass = `${c.class} .searchfield`; const options = { dataset: c.dataset || [], selectable: 'multiple', showCheckboxes: false }; - const isSearchable = ((s.searchable === true || s.searchable === 'true') && ($(`${c.class} .searchfield`, this.element).length > 0)); + const isSearchable = ((s.searchable === true || s.searchable === 'true') && ($(searchfieldContainerClass, this.element).length > 0)); if (isSearchable) { options.searchable = true; @@ -219,17 +222,23 @@ SwapList.prototype = { this.offset = null; - this.containers = $(`${s.availableClass},${ - s.selectedClass},${ - s.additionalClass}`, this.element); + const { availableClass, selectedClass, additionalClass } = s; + const { availableBtn, additionalBtn, selectedBtnLeft, selectedBtnRight } = s; - this.actionButtons = $(`${s.availableBtn},${ - s.additionalBtn},${ - s.selectedBtnLeft},${ - s.selectedBtnRight}`, this.element); + this.containers = $( + `${availableClass}, ${selectedClass}, ${additionalClass}`, + this.element + ); - this.selectedButtons = $(`${s.selectedBtnLeft},${ - s.selectedBtnRight}`, this.element); + this.actionButtons = $( + `${availableBtn},${additionalBtn},${selectedBtnLeft},${selectedBtnRight}`, + this.element + ); + + this.selectedButtons = $( + `${selectedBtnLeft},${selectedBtnRight}`, + this.element + ); this.tabButtonsStr = `${ s.availableBtn}, ${ @@ -672,7 +681,8 @@ SwapList.prototype = { for (let i = 0, l = containers.length; i < l; i++) { const c = containers[i]; - const nodes = $(`${c.class} .listview li`, this.element); + const classSelector = `${c.class} .listview li`; + const nodes = $(classSelector, this.element); for (let nodeIndex = 0, l2 = nodes.length; nodeIndex < l2; nodeIndex++) { let data; @@ -961,7 +971,8 @@ SwapList.prototype = { for (let i = 0, l = containers.length; i < l; i++) { const c = containers[i]; - const lv = $(`${c.class} .listview`, this.element); + const classSelector = `${c.class} .listview`; + const lv = $(classSelector, this.element); const api = lv.data('listview'); if (api) { @@ -1187,8 +1198,11 @@ SwapList.prototype = { return; } - $(`.${settings.numOfSelectionsClass}`, settings.itemContentTempl).html(selections.items.length); - $(`.${settings.numOfSelectionsClass}-text`, settings.itemContentTempl).text(Locale.translate('ItemsSelected')); + const selectionClass = `.${settings.numOfSelectionsClass}`; + const selectionClassText = `${selectionClass}-text`; + + $(selectionClass, settings.itemContentTempl).html(selections.items.length); + $(selectionClassText, settings.itemContentTempl).text(Locale.translate('ItemsSelected')); self.addDropeffects(); if (!self.isTouch) { @@ -1196,7 +1210,8 @@ SwapList.prototype = { e.originalEvent.dataTransfer.setData('text', ''); if (selections.items.length > 1) { - $(`.${settings.itemContentClass}`, selections.dragged).html(settings.itemContentTempl.html()); + const itemContentClass = `.${settings.itemContentClass}`; + $(itemContentClass, selections.dragged).html(settings.itemContentTempl.html()); } } else { rect = target[0].getBoundingClientRect(); @@ -1265,7 +1280,8 @@ SwapList.prototype = { if (!selections.isInSelection) { self.draggedMakeSelected(list, selections.dragged); selections.items = list.selectedItems; - $(`.${settings.numOfSelectionsClass}`, settings.itemContentTempl).html(selections.items.length); + const selectionClass = `.${settings.numOfSelectionsClass}`; + $(selectionClass, settings.itemContentTempl).html(selections.items.length); } touch = e.originalEvent.touches[0]; @@ -1282,7 +1298,8 @@ SwapList.prototype = { .slideUp(); if (selections.items.length > 1) { - $(`.${settings.itemContentClass}`, (selections.placeholderTouch.add('#sl-placeholder-touch2'))) + const itemContentClass = `.${settings.itemContentClass}`; + $(itemContentClass, (selections.placeholderTouch.add('#sl-placeholder-touch2'))) .html(settings.itemContentTempl.html()); $('#sl-placeholder-touch2').show(); @@ -1331,7 +1348,8 @@ SwapList.prototype = { }); if (selections.items.length > 1) { - $(`.${settings.itemContentClass}`, selections.dragged).html($(`.${settings.itemContentClass}`, selections.placeholder).html()); + const itemContentClass = `.${settings.itemContentClass}`; + $(itemContentClass, selections.dragged).html($(itemContentClass, selections.placeholder).html()); if (self.isTouch) { selections.dragged.show(); } From 919840bc49b5d65fc2533a89b0f8b8c31d8e2d5a Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Wed, 21 Aug 2024 15:19:59 +0800 Subject: [PATCH 2/8] fix readme link --- docs/TESTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TESTING.md b/docs/TESTING.md index 17e2b1c69d..64b17499dd 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -56,7 +56,7 @@ This project demonstrates how to perform visual testing using Percy and Playwrig - [Introduction](#introduction) - [Example Test](#example-test) - [Usage](#usage) -- [Best Practices](#best-practices) +- [Best Practices](#best-practices-for-visual-testing) ### Introduction From 4c4c907c5bc34f6763e4c0e5f4429320facf88c4 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Wed, 21 Aug 2024 23:48:00 +0800 Subject: [PATCH 3/8] add changelog, fix css lint --- docs/CHANGELOG.md | 1 + src/components/swaplist/_swaplist.scss | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 96b04c1987..48bb5fde9a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -18,6 +18,7 @@ - `[General]` Upgrade dependencies, this involved updating sass and test dependencies with a few css deprecations that were fixed. ([#8947](https://github.com/infor-design/enterprise-ng/issues/8947)) - `[Message]` Updated docs in settings. ([#8839](https://github.com/infor-design/enterprise/issues/8839)) - `[ModuleNav]` Fixed a bug where the tooltip was not showing when collapsed by default. ([NG#1678](https://github.com/infor-design/enterprise-ng/issues/1678)) +- `[Swaplist]` Improved the size of the swaplist's drop area when there is no existing items. ([#8956](https://github.com/infor-design/enterprise/issues/8956)) - `[Toolbar]` Fixed uncaught error when destroying the toolbar. ([#8946](https://github.com/infor-design/enterprise/issues/8946)) - `[Tabs]` Fixed a bug where focus state is undefined when using breadcrumbs startup. ([#8910](https://github.com/infor-design/enterprise/issues/8910)) diff --git a/src/components/swaplist/_swaplist.scss b/src/components/swaplist/_swaplist.scss index a8c5c0d4d9..b0107ed1af 100755 --- a/src/components/swaplist/_swaplist.scss +++ b/src/components/swaplist/_swaplist.scss @@ -41,6 +41,7 @@ .listview { li { border-radius: 0; + &:last-child { &.over { border: 1px dashed $swaplist-border-color !important; From a62aceef2806c4045b404b4cefe7644a41339117 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Thu, 22 Aug 2024 00:25:23 +0800 Subject: [PATCH 4/8] fix the drop area more draggable not just the look --- src/components/swaplist/_swaplist.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/swaplist/_swaplist.scss b/src/components/swaplist/_swaplist.scss index b0107ed1af..3196008983 100755 --- a/src/components/swaplist/_swaplist.scss +++ b/src/components/swaplist/_swaplist.scss @@ -259,7 +259,7 @@ border-top: thin solid $swaplist-border-color-card; ul { - min-height: 100%; + min-height: 40px; padding: 0 0 5px; &.is-not-droppable { From 402133329173f3f15291b50cae08fdb2cb5c2438 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Tue, 27 Aug 2024 14:35:20 +0800 Subject: [PATCH 5/8] fix card border radius in rtl --- src/components/swaplist/_swaplist-new.scss | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/components/swaplist/_swaplist-new.scss b/src/components/swaplist/_swaplist-new.scss index ce82a34b2e..bbd261317f 100644 --- a/src/components/swaplist/_swaplist-new.scss +++ b/src/components/swaplist/_swaplist-new.scss @@ -58,3 +58,23 @@ } } } + +html[dir=rtl] { + .swaplist { + .card, + .widget { + &:nth-child(1) { + border-radius: 0 6px 0 0; + } + } + + &.one-third { + .card, + .widget { + &:nth-child(3) { + border-radius: 6px 0 0 0; + } + } + } + } +} From 5bf62454b104e05e0fd005645d0cf0c2026174d0 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Tue, 27 Aug 2024 14:44:27 +0800 Subject: [PATCH 6/8] fix css lint --- src/components/swaplist/_swaplist-new.scss | 2 +- src/components/swaplist/swaplist.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/swaplist/_swaplist-new.scss b/src/components/swaplist/_swaplist-new.scss index bbd261317f..9ae005b17c 100644 --- a/src/components/swaplist/_swaplist-new.scss +++ b/src/components/swaplist/_swaplist-new.scss @@ -72,7 +72,7 @@ html[dir=rtl] { .card, .widget { &:nth-child(3) { - border-radius: 6px 0 0 0; + border-radius: 6px 0 0; } } } diff --git a/src/components/swaplist/swaplist.js b/src/components/swaplist/swaplist.js index 99a201096a..528a4b15fc 100644 --- a/src/components/swaplist/swaplist.js +++ b/src/components/swaplist/swaplist.js @@ -1319,6 +1319,7 @@ SwapList.prototype = { // Dragend - implement items being validly dropped into targets .on(self.dragEnd, self.dragElements, (e) => { + debugger; if (!selections.dragged || !selections.droptarget) { return; } From 3a04a0bc6ff0ac404233d50caae0c0d6b23b3672 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Tue, 27 Aug 2024 19:28:33 +0800 Subject: [PATCH 7/8] made a drop area a full height when there's an li element in the target area --- src/components/swaplist/_swaplist.scss | 3 +++ src/components/swaplist/swaplist.js | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/swaplist/_swaplist.scss b/src/components/swaplist/_swaplist.scss index 3196008983..3344103fc6 100755 --- a/src/components/swaplist/_swaplist.scss +++ b/src/components/swaplist/_swaplist.scss @@ -37,6 +37,8 @@ .card-content { width: 100%; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; .listview { li { @@ -257,6 +259,7 @@ .is-multiselect { background-color: $listview-bg-color; border-top: thin solid $swaplist-border-color-card; + height: 100%; ul { min-height: 40px; diff --git a/src/components/swaplist/swaplist.js b/src/components/swaplist/swaplist.js index 528a4b15fc..c0f02a8c2a 100644 --- a/src/components/swaplist/swaplist.js +++ b/src/components/swaplist/swaplist.js @@ -1256,8 +1256,17 @@ SwapList.prototype = { } self.element.triggerHandler('draggingswap', [selections.move]); selections.related = e.target; + const $target = $(selections.related); + $('ul, li', self.element).removeClass('over'); - $(e.target).closest('ul, li').addClass('over'); + $target.closest('ul, li').addClass('over'); + + // Set the height to 100% if the target element has any
  • children + // to cover the entire card content area. + if ($target.find('li').length > 0) { + $target.closest('ul').css('height', '100%'); + } + selections.droptarget = $(selections.related).closest('.card'); $('[aria-grabbed="true"]', self.element).not(selections.dragged).slideUp(); e.stopPropagation(); @@ -1319,7 +1328,6 @@ SwapList.prototype = { // Dragend - implement items being validly dropped into targets .on(self.dragEnd, self.dragElements, (e) => { - debugger; if (!selections.dragged || !selections.droptarget) { return; } From 50b05959081787aa7606b91ebc45981cbd2a7521 Mon Sep 17 00:00:00 2001 From: Eric Angeles Date: Tue, 27 Aug 2024 19:32:53 +0800 Subject: [PATCH 8/8] fix css lint --- src/components/swaplist/_swaplist-new.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/swaplist/_swaplist-new.scss b/src/components/swaplist/_swaplist-new.scss index 9ae005b17c..3c41c07c3b 100644 --- a/src/components/swaplist/_swaplist-new.scss +++ b/src/components/swaplist/_swaplist-new.scss @@ -59,7 +59,7 @@ } } -html[dir=rtl] { +html[dir='rtl'] { .swaplist { .card, .widget {