mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[ACS-5742] Fix Search e2e's (#8902)
* [ACS-5742] added People filter to demo-shell * [ACS-5742] fixed search e2e's * [ACS-5742] linter * [ACS-5742] build fix * [ACS-5742] fixed build * [ACS-5742] removed duplicated unit test
This commit is contained in:
parent
3aa55996bf
commit
0d5e70ebf7
@ -13,13 +13,5 @@
|
||||
"C280063": "https://alfresco.atlassian.net/browse/ACS-4595",
|
||||
"C280064": "https://alfresco.atlassian.net/browse/ACS-4595",
|
||||
"C280407": "https://alfresco.atlassian.net/browse/ACS-4595",
|
||||
"C277288": "https://alfresco.atlassian.net/browse/AAE-15475",
|
||||
"C280054": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C280058": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C286298": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C277146": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C286556": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C291802": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C277280": "https://alfresco.atlassian.net/browse/ACS-5742",
|
||||
"C277281": "https://alfresco.atlassian.net/browse/ACS-5742"
|
||||
"C277288": "https://alfresco.atlassian.net/browse/AAE-15475"
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ describe('Search Sorting Picker', () => {
|
||||
|
||||
it('[C277280] Should be able to sort the search results by "Name" ASC', async () => {
|
||||
await searchFilters.checkSearchFiltersIsDisplayed();
|
||||
await searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchFilters.creatorCheckListFiltersPage().enterFilterInputValue(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchResults.sortByName('ASC');
|
||||
|
||||
await expect(await searchResults.checkListIsOrderedByNameAsc()).toBe(true);
|
||||
@ -179,7 +179,7 @@ describe('Search Sorting Picker', () => {
|
||||
|
||||
it('[C277281] Should be able to sort the search results by "Name" DESC', async () => {
|
||||
await searchFilters.checkSearchFiltersIsDisplayed();
|
||||
await searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchFilters.creatorCheckListFiltersPage().enterFilterInputValue(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchResults.sortByName('DESC');
|
||||
await expect(await searchResults.checkListIsOrderedByNameDesc()).toBe(true);
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ export class SearchFiltersPage {
|
||||
|
||||
searchFilters = $('adf-search-filter');
|
||||
fileTypeFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-SEARCH.FACET_FIELDS.TYPE"]');
|
||||
creatorFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-SEARCH.FACET_FIELDS.CREATOR"]');
|
||||
creatorFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-SEARCH.FILTER.PEOPLE"]');
|
||||
fileSizeFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-SEARCH.FACET_FIELDS.SIZE"]');
|
||||
nameFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-Name"]');
|
||||
checkListFilter = $('mat-expansion-panel[data-automation-id="expansion-panel-Check List"]');
|
||||
|
@ -163,7 +163,7 @@ describe('Search Filters', () => {
|
||||
await searchFiltersPage.checkSearchFiltersIsDisplayed();
|
||||
|
||||
const userOption = `${acsUser.firstName} ${acsUser.lastName}`;
|
||||
const searchCheckListPage = await searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption);
|
||||
const searchCheckListPage = await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(userOption);
|
||||
await searchCheckListPage.checkChipIsDisplayed(userOption);
|
||||
await searchCheckListPage.removeFilterOption(userOption);
|
||||
await searchCheckListPage.checkChipIsNotDisplayed(userOption);
|
||||
@ -172,7 +172,7 @@ describe('Search Filters', () => {
|
||||
it('[C277146] Should Show more/less buttons be hidden when inactive', async () => {
|
||||
await BrowserActions.getUrl(`${browser.baseUrl}/search;q=*`);
|
||||
|
||||
const searchCheckListPage = searchFiltersPage.creatorCheckListFiltersPage();
|
||||
const searchCheckListPage = searchFiltersPage.fileTypeCheckListFiltersPage();
|
||||
|
||||
await searchCheckListPage.checkShowLessButtonIsNotDisplayed();
|
||||
await searchCheckListPage.checkShowMoreButtonIsDisplayed();
|
||||
@ -189,7 +189,7 @@ describe('Search Filters', () => {
|
||||
await searchFiltersPage.clickFileSizeFilterHeader();
|
||||
await searchFiltersPage.checkFileSizeFilterIsCollapsed();
|
||||
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().clickCheckListOption('Administrator');
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue('Administrator');
|
||||
|
||||
await searchFiltersPage.checkFileTypeFilterIsCollapsed();
|
||||
await searchFiltersPage.checkFileSizeFilterIsCollapsed();
|
||||
@ -269,7 +269,7 @@ describe('Search Filters', () => {
|
||||
await searchResults.dataTable.waitTillContentLoaded();
|
||||
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().searchInFilter('dminis');
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().checkCheckListOptionIsDisplayed('Administrator');
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().checkCheckListAutocompleteOptionIsDisplayed('Administrator');
|
||||
});
|
||||
|
||||
it('[C291981] Should group search facets under the default label, by default', async () => {
|
||||
|
@ -86,7 +86,7 @@ describe('Search Component - Multi-Select Facet', () => {
|
||||
userOption = `${acsUser.firstName} ${acsUser.lastName}`;
|
||||
|
||||
await searchFiltersPage.checkSearchFiltersIsDisplayed();
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(userOption);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@ -112,7 +112,7 @@ describe('Search Component - Multi-Select Facet', () => {
|
||||
userOption = `${acsUser.firstName} ${acsUser.lastName}`;
|
||||
|
||||
await searchFiltersPage.checkSearchFiltersIsDisplayed();
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(userOption);
|
||||
await searchFiltersPage.fileTypeCheckListFiltersPage().filterBy('Plain Text');
|
||||
await searchResultsPage.dataTable.waitTillContentLoaded();
|
||||
|
||||
@ -177,8 +177,8 @@ describe('Search Component - Multi-Select Facet', () => {
|
||||
await searchResultsPage.dataTable.waitTillContentLoaded();
|
||||
|
||||
await searchFiltersPage.checkSearchFiltersIsDisplayed();
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${userUploadingTxt.firstName} ${userUploadingTxt.lastName}`);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${userUploadingImg.firstName} ${userUploadingImg.lastName}`);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(`${userUploadingTxt.firstName} ${userUploadingTxt.lastName}`);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(`${userUploadingImg.firstName} ${userUploadingImg.lastName}`);
|
||||
await searchResultsPage.dataTable.waitTillContentLoaded();
|
||||
|
||||
await searchResultsPage.checkContentIsDisplayed(txtFile.entry.name);
|
||||
@ -229,7 +229,7 @@ describe('Search Component - Multi-Select Facet', () => {
|
||||
|
||||
await searchFiltersPage.checkSearchFiltersIsDisplayed();
|
||||
await searchFiltersPage.fileTypeCheckListFiltersPage().filterBy('Plain Text');
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchFiltersPage.creatorCheckListFiltersPage().enterFilterInputValue(`${acsUser.firstName} ${acsUser.lastName}`);
|
||||
await searchResultsPage.dataTable.waitTillContentLoaded();
|
||||
|
||||
await expect(await searchResultsPage.numberOfResultsDisplayed()).toBe(1);
|
||||
|
127
lib/cli/package-lock.json
generated
127
lib/cli/package-lock.json
generated
@ -9,7 +9,7 @@
|
||||
"version": "6.2.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@alfresco/js-api": ">=6.3.0-1031",
|
||||
"@alfresco/js-api": ">=6.3.0-1271",
|
||||
"commander": "^6.2.1",
|
||||
"ejs": "^3.1.9",
|
||||
"license-checker": "^25.0.1",
|
||||
@ -30,13 +30,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@alfresco/js-api": {
|
||||
"version": "6.3.0-1035",
|
||||
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-6.3.0-1035.tgz",
|
||||
"integrity": "sha512-+1xjwpx+/+kTlVfbxT1znlGPEfWYPv6KpSNneIz51OH+sFJ030mtkWeU4OnTbgeypSR72BN+G+RMJia7QT6qfA==",
|
||||
"version": "6.3.0-1280",
|
||||
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-6.3.0-1280.tgz",
|
||||
"integrity": "sha512-xRf7YpSe9F9iNnimQS5DnNqCeb1P3EhBRnx/hOsqn9bC20c5plwjJWt2EIMcPvCz1TBhnw24BP14hUR6oq0pdQ==",
|
||||
"dependencies": {
|
||||
"event-emitter": "^0.3.5",
|
||||
"superagent": "^6.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
"superagent": "^8.0.9",
|
||||
"tslib": "^2.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ejs": {
|
||||
@ -317,9 +317,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dezalgo": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
|
||||
"integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
||||
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
||||
"dependencies": {
|
||||
"asap": "^2.0.0",
|
||||
"wrappy": "1"
|
||||
@ -475,9 +475,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@ -488,10 +488,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/formidable": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
|
||||
"integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
|
||||
"deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
||||
"integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==",
|
||||
"dependencies": {
|
||||
"dezalgo": "^1.0.4",
|
||||
"hexoid": "^1.0.0",
|
||||
"once": "^1.4.0",
|
||||
"qs": "^6.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/tunnckoCore/commissions"
|
||||
}
|
||||
@ -507,12 +512,13 @@
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
|
||||
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
|
||||
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
@ -591,6 +597,17 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/has-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
@ -602,6 +619,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hexoid": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
||||
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
@ -1023,9 +1048,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
|
||||
"integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
|
||||
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
@ -1071,19 +1096,6 @@
|
||||
"npm-normalize-package-bin": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/readdir-scoped-modules": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
|
||||
@ -1347,34 +1359,24 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/superagent": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz",
|
||||
"integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==",
|
||||
"deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at <https://github.com/visionmedia/superagent/releases>.",
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
|
||||
"integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
|
||||
"dependencies": {
|
||||
"component-emitter": "^1.3.0",
|
||||
"cookiejar": "^2.1.2",
|
||||
"debug": "^4.1.1",
|
||||
"fast-safe-stringify": "^2.0.7",
|
||||
"form-data": "^3.0.0",
|
||||
"formidable": "^1.2.2",
|
||||
"cookiejar": "^2.1.4",
|
||||
"debug": "^4.3.4",
|
||||
"fast-safe-stringify": "^2.1.1",
|
||||
"form-data": "^4.0.0",
|
||||
"formidable": "^2.1.2",
|
||||
"methods": "^1.1.2",
|
||||
"mime": "^2.4.6",
|
||||
"qs": "^6.9.4",
|
||||
"readable-stream": "^3.6.0",
|
||||
"semver": "^7.3.2"
|
||||
"mime": "2.6.0",
|
||||
"qs": "^6.11.0",
|
||||
"semver": "^7.3.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 7.0.0"
|
||||
"node": ">=6.4.0 <13 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
@ -1409,9 +1411,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
@ -1455,11 +1457,6 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"node_modules/util-extend": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
|
||||
|
@ -35,6 +35,7 @@
|
||||
[disabled]="option | adfIsIncluded: selectedOptions : compareOption"
|
||||
*ngFor="let option of filteredOptions" [value]="option" [matTooltipShowDelay]="tooltipShowDelay"
|
||||
[matTooltipDisabled]="!option.fullPath" matTooltipPosition="right"
|
||||
[attr.data-automation-id]="'option-' + (option.value)"
|
||||
[matTooltip]="'SEARCH.RESULTS.WILL_CONTAIN' | translate:{searchTerm: option.fullPath || option.value}"
|
||||
[ngClass]="(option | adfIsIncluded: selectedOptions : compareOption) && 'adf-autocomplete-added-option'">
|
||||
{{ option.fullPath || option.value }}
|
||||
|
@ -1,19 +1,19 @@
|
||||
<mat-chip [attr.data-automation-id]="'search-filter-chip-tabbed-' + tabbedFacet.label"
|
||||
disableRipple
|
||||
class="adf-search-filter-chip-tabbed"
|
||||
[class.adf-search-toggle-chip]="(displayValue$ | async) || menuTrigger.menuOpen"
|
||||
[class.adf-search-toggle-chip]="displayValue || menuTrigger.menuOpen"
|
||||
[disabled]="!isPopulated"
|
||||
tabIndex="0"
|
||||
[matMenuTriggerFor]="menu"
|
||||
(onMenuOpen)="onMenuOpen()"
|
||||
(keydown.enter)="onEnterKeydown()"
|
||||
(keydown.escape)="onEscKeydown()"
|
||||
[attr.title]="displayValue$ | async"
|
||||
[attr.title]="displayValue"
|
||||
#menuTrigger="matMenuTrigger">
|
||||
|
||||
<span class="adf-search-filter-placeholder">{{ tabbedFacet.label | translate }}:</span>
|
||||
|
||||
<span class="adf-search-filter-ellipsis adf-filter-value" *ngIf="displayValue$ | async as displayValue; else showAny">
|
||||
<span class="adf-search-filter-ellipsis adf-filter-value" *ngIf="displayValue; else showAny">
|
||||
{{ displayValue | translate }}
|
||||
</span>
|
||||
<ng-template #showAny><span class="adf-search-filter-ellipsis adf-filter-value"> {{ 'SEARCH.FILTER.ANY' | translate }}</span></ng-template>
|
||||
@ -33,18 +33,9 @@
|
||||
{{ tabbedFacet.label | translate }}
|
||||
</ng-container>
|
||||
<ng-container ngProjectAs="filter-content">
|
||||
<adf-search-filter-tabbed>
|
||||
<ng-container *ngFor="let field of tabbedFacet.fields">
|
||||
<adf-search-chip-autocomplete-input
|
||||
*adf-search-filter-tab="tabbedFacet.facets[field]?.label"
|
||||
[autocompleteOptions]="autocompleteOptions[field]"
|
||||
[onReset$]="reset$"
|
||||
[allowOnlyPredefinedValues]="true"
|
||||
[compareOption]="optionComparator"
|
||||
(optionsChanged)="onOptionsChange($event, field)">
|
||||
</adf-search-chip-autocomplete-input>
|
||||
</ng-container>
|
||||
</adf-search-filter-tabbed>
|
||||
<adf-search-facet-tabbed-content [tabbedFacet]="tabbedFacet" (isPopulated)="isPopulated = $event"
|
||||
[onReset$]="reset$" [onApply$]="apply$" (displayValue$)="displayValue = $event">
|
||||
</adf-search-facet-tabbed-content>
|
||||
</ng-container>
|
||||
<ng-container ngProjectAs="filter-actions">
|
||||
<button mat-button class="adf-search-action-button" (click)="onRemove()" id="cancel-filter-button">
|
||||
|
@ -19,28 +19,22 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ContentTestingModule } from '../../../../testing/content.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
|
||||
import { SearchFilterList } from '../../../models/search-filter-list.model';
|
||||
import { SearchFacetChipTabbedComponent } from './search-facet-chip-tabbed.component';
|
||||
import { FacetField } from '../../../models/facet-field.interface';
|
||||
import { SearchFacetFiltersService } from '../../../services/search-facet-filters.service';
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
|
||||
describe('SearchFacetChipTabbedComponent', () => {
|
||||
let component: SearchFacetChipTabbedComponent;
|
||||
let fixture: ComponentFixture<SearchFacetChipTabbedComponent>;
|
||||
let queryBuilder: SearchQueryBuilderService;
|
||||
let searchFacetService: SearchFacetFiltersService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule]
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
fixture = TestBed.createComponent(SearchFacetChipTabbedComponent);
|
||||
component = fixture.componentInstance;
|
||||
queryBuilder = TestBed.inject(SearchQueryBuilderService);
|
||||
searchFacetService = TestBed.inject(SearchFacetFiltersService);
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
|
||||
const facet1: FacetField = { type: 'field', label: 'field', field: 'field', buckets: new SearchFilterList() };
|
||||
const facet2: FacetField = { type: 'field', label: 'field2', field: 'field2', buckets: new SearchFilterList() };
|
||||
@ -66,32 +60,12 @@ describe('SearchFacetChipTabbedComponent', () => {
|
||||
return fixture.debugElement.query(By.css('.adf-search-filter-ellipsis.adf-filter-value')).nativeElement.innerText.trim();
|
||||
}
|
||||
|
||||
function getTabs(): HTMLDivElement[] {
|
||||
return fixture.debugElement.queryAll(By.css('.mat-tab-label-content')).map((element) => element.nativeElement);
|
||||
}
|
||||
|
||||
function changeTab(tabIndex: number) {
|
||||
getTabs()[tabIndex].click();
|
||||
function emitChildEvent(eventName: string, event: any) {
|
||||
const debugElem = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content'));
|
||||
debugElem.triggerEventHandler(eventName, event);
|
||||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
function triggerComponentChanges() {
|
||||
component.ngOnChanges({
|
||||
tabbedFacet: new SimpleChange(null, component.tabbedFacet, false)
|
||||
});
|
||||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
function addBucketItem(field: string, displayValue: string) {
|
||||
component.tabbedFacet.facets[field].buckets.items.push({
|
||||
count: 1,
|
||||
label: displayValue,
|
||||
display: displayValue,
|
||||
filterQuery: ''
|
||||
});
|
||||
triggerComponentChanges();
|
||||
}
|
||||
|
||||
it('should display correct label for tabbed facet', () => {
|
||||
const label = fixture.debugElement.query(By.css('.adf-search-filter-placeholder')).nativeElement.innerText;
|
||||
expect(label).toBe(component.tabbedFacet.label + ':');
|
||||
@ -122,111 +96,54 @@ describe('SearchFacetChipTabbedComponent', () => {
|
||||
expect(title).toBe(component.tabbedFacet.label);
|
||||
});
|
||||
|
||||
it('should display 2 tabs with specific labels', () => {
|
||||
it('should display adf-search-facet-tabbed-content component', () => {
|
||||
openFacet();
|
||||
const tabLabels = getTabs();
|
||||
expect(tabLabels.length).toBe(2);
|
||||
expect(tabLabels[0].innerText).toBe(component.tabbedFacet.facets['field'].label);
|
||||
expect(tabLabels[1].innerText).toBe(component.tabbedFacet.facets['field2'].label);
|
||||
});
|
||||
|
||||
it('should display creator tab as active initially and allow navigation', () => {
|
||||
openFacet();
|
||||
let activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
|
||||
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field'].label);
|
||||
|
||||
changeTab(1);
|
||||
activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
|
||||
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field2'].label);
|
||||
let activeTabLabel = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content'));
|
||||
expect(activeTabLabel).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display arrow down icon and not disable the chip when items are loaded', () => {
|
||||
addBucketItem('field', 'test');
|
||||
component.isPopulated = true;
|
||||
fixture.detectChanges();
|
||||
const chip = fixture.debugElement.query(By.css('mat-chip'));
|
||||
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
|
||||
expect(chip.classes['mat-chip-disabled']).toBeUndefined();
|
||||
expect(icon).toEqual('keyboard_arrow_down');
|
||||
});
|
||||
|
||||
it('should display arrow up icon when menu is opened', () => {
|
||||
addBucketItem('field', 'test');
|
||||
it('should display arrow up icon when menu is opened', async () => {
|
||||
openFacet();
|
||||
emitChildEvent('isPopulated', true);
|
||||
await fixture.whenStable();
|
||||
const icon = fixture.debugElement.query(By.css('mat-chip mat-icon')).nativeElement.innerText;
|
||||
expect(icon).toEqual('keyboard_arrow_up');
|
||||
});
|
||||
|
||||
it('should create empty selected options for each tab initially', () => {
|
||||
expect(component.selectedOptions['field']).toEqual([]);
|
||||
expect(component.selectedOptions['field2']).toEqual([]);
|
||||
});
|
||||
|
||||
it('should update autocomplete options when buckets change', () => {
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
expect(component.autocompleteOptions['field'].length).toBe(1);
|
||||
expect(component.autocompleteOptions['field'][0]).toEqual({value: 'test'});
|
||||
expect(component.autocompleteOptions['field2'].length).toBe(1);
|
||||
expect(component.autocompleteOptions['field2'][0]).toEqual({value: 'test2'});
|
||||
});
|
||||
|
||||
it('should add buckets when items are selected', () => {
|
||||
spyOn(queryBuilder, 'addUserFacetBucket');
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
component.onOptionsChange([{ value: 'test' }], 'field');
|
||||
expect(queryBuilder.addUserFacetBucket).toHaveBeenCalledWith('field',component.tabbedFacet.facets['field'].buckets.items[0]);
|
||||
});
|
||||
|
||||
it('should remove buckets when items are unselected', () => {
|
||||
spyOn(queryBuilder, 'removeUserFacetBucket');
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
component.onOptionsChange([], 'field');
|
||||
expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith('field',component.tabbedFacet.facets['field'].buckets.items[0]);
|
||||
});
|
||||
|
||||
it('should update display value when next elements are selected', () => {
|
||||
const selectedOption1 = 'test';
|
||||
const selectedOption2 = 'test2';
|
||||
addBucketItem('field', selectedOption1);
|
||||
addBucketItem('field', selectedOption2);
|
||||
component.onOptionsChange([{ value: selectedOption1 }, { value: selectedOption2 }],'field');
|
||||
it('should update display value when new displayValue$ emitted', () => {
|
||||
const displayValue = 'field_LABEL: test, test2';
|
||||
openFacet();
|
||||
emitChildEvent('displayValue$', displayValue);
|
||||
fixture.detectChanges();
|
||||
expect(getDisplayValue()).toBe(`${component.tabbedFacet.facets['field'].label}_LABEL: ${selectedOption1}, ${selectedOption2}`);
|
||||
expect(getDisplayValue()).toBe(displayValue);
|
||||
});
|
||||
|
||||
it('should update display value when elements from both tabs are selected', () => {
|
||||
const selectedOption1 = 'test';
|
||||
const selectedOption2 = 'test2';
|
||||
addBucketItem('field', selectedOption1);
|
||||
addBucketItem('field2', selectedOption2);
|
||||
component.onOptionsChange([{ value: selectedOption1 }], 'field');
|
||||
component.onOptionsChange([{ value: selectedOption2 }], 'field2');
|
||||
fixture.detectChanges();
|
||||
expect(getDisplayValue()).toBe(`${component.tabbedFacet.facets['field'].label}_LABEL: ${selectedOption1} ${component.tabbedFacet.facets['field2'].label}_LABEL: ${selectedOption2}`);
|
||||
});
|
||||
|
||||
it('should update search query and display value when apply btn is clicked', () => {
|
||||
it('should call onApply and close modal when apply btn is clicked', () => {
|
||||
spyOn(component.menuTrigger, 'closeMenu').and.callThrough();
|
||||
spyOn(component, 'updateDisplayValue').and.callThrough();
|
||||
spyOn(searchFacetService, 'updateSelectedBuckets').and.callThrough();
|
||||
spyOn(component, 'onApply').and.callThrough();
|
||||
openFacet();
|
||||
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
|
||||
applyButton.triggerEventHandler('click', {});
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
expect(component.menuTrigger.closeMenu).toHaveBeenCalled();
|
||||
expect(component.updateDisplayValue).toHaveBeenCalled();
|
||||
expect(searchFacetService.updateSelectedBuckets).toHaveBeenCalled();
|
||||
expect(component.onApply).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update search query and display value when cancel btn is clicked', () => {
|
||||
it('should call onRemove and close modal when cancel btn is clicked', () => {
|
||||
spyOn(component.menuTrigger, 'closeMenu').and.callThrough();
|
||||
spyOn(component, 'updateDisplayValue').and.callThrough();
|
||||
spyOn(component, 'onRemove').and.callThrough();
|
||||
openFacet();
|
||||
const applyButton = fixture.debugElement.query(By.css('#cancel-filter-button'));
|
||||
applyButton.triggerEventHandler('click', {});
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
expect(component.menuTrigger.closeMenu).toHaveBeenCalled();
|
||||
expect(component.updateDisplayValue).toHaveBeenCalled();
|
||||
expect(component.onRemove).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -15,17 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, ElementRef, Inject, Input, OnChanges, OnInit, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, ElementRef, Input, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { TabbedFacetField } from '../../../models/tabbed-facet-field.interface';
|
||||
import { Subject } from 'rxjs';
|
||||
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
|
||||
import { SEARCH_QUERY_SERVICE_TOKEN } from '../../../search-query-service.token';
|
||||
import { FacetWidget } from '../../../models/facet-widget.interface';
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { SearchFacetFiltersService } from '../../../services/search-facet-filters.service';
|
||||
import { AutocompleteOption } from '../../../models/autocomplete-option.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-facet-chip-tabbed',
|
||||
@ -33,7 +27,7 @@ import { AutocompleteOption } from '../../../models/autocomplete-option.interfac
|
||||
styleUrls: ['./search-facet-chip-tabbed.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class SearchFacetChipTabbedComponent implements OnInit, OnChanges, FacetWidget {
|
||||
export class SearchFacetChipTabbedComponent {
|
||||
@Input()
|
||||
tabbedFacet: TabbedFacetField;
|
||||
|
||||
@ -44,42 +38,16 @@ export class SearchFacetChipTabbedComponent implements OnInit, OnChanges, FacetW
|
||||
menuTrigger: MatMenuTrigger;
|
||||
|
||||
private resetSubject$ = new Subject<void>();
|
||||
private applySubject$ = new Subject<void>();
|
||||
|
||||
displayValue$ = new Subject<string>();
|
||||
displayValue = '';
|
||||
reset$ = this.resetSubject$.asObservable();
|
||||
apply$ = this.applySubject$.asObservable();
|
||||
focusTrap: ConfigurableFocusTrap;
|
||||
chipIcon = 'keyboard_arrow_down';
|
||||
autocompleteOptions = {};
|
||||
selectedOptions = {};
|
||||
isPopulated = false;
|
||||
|
||||
constructor(@Inject(SEARCH_QUERY_SERVICE_TOKEN) private queryBuilder: SearchQueryBuilderService,
|
||||
private translationService: TranslationService,
|
||||
private searchFacetFiltersService: SearchFacetFiltersService,
|
||||
private focusTrapFactory: ConfigurableFocusTrapFactory) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
Object.defineProperty(this.selectedOptions, field, {
|
||||
value: [],
|
||||
writable: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.tabbedFacet) {
|
||||
this.isPopulated = this.tabbedFacet.fields.some((field) => this.tabbedFacet.facets[field]?.buckets.items.length > 0);
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
const options: AutocompleteOption[] = this.tabbedFacet.facets[field].buckets.items.map((item) => ({ value: item.display }));
|
||||
Object.defineProperty(this.autocompleteOptions, field, {
|
||||
value: options,
|
||||
writable: true
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
constructor(private focusTrapFactory: ConfigurableFocusTrapFactory) {}
|
||||
|
||||
onMenuOpen() {
|
||||
if (this.menuContainer && !this.focusTrap) {
|
||||
@ -95,12 +63,12 @@ export class SearchFacetChipTabbedComponent implements OnInit, OnChanges, FacetW
|
||||
}
|
||||
|
||||
onRemove() {
|
||||
this.reset();
|
||||
this.resetSubject$.next();
|
||||
this.menuTrigger.closeMenu();
|
||||
}
|
||||
|
||||
onApply() {
|
||||
this.submitValues();
|
||||
this.applySubject$.next();
|
||||
this.menuTrigger.closeMenu();
|
||||
}
|
||||
|
||||
@ -119,56 +87,4 @@ export class SearchFacetChipTabbedComponent implements OnInit, OnChanges, FacetW
|
||||
this.menuTrigger.closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
onOptionsChange(selectedOptions: AutocompleteOption[], field: string) {
|
||||
this.selectedOptions[field] = selectedOptions.map((selectedOption) => selectedOption.value);
|
||||
this.isPopulated = this.tabbedFacet.fields.some((facetField) => this.selectedOptions[facetField].length > 0);
|
||||
this.updateDisplayValue();
|
||||
this.updateUserFacetBuckets();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
updateDisplayValue() {
|
||||
let displayValue = '';
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
if (this.selectedOptions[field].length > 0) {
|
||||
const stackedOptions = this.selectedOptions[field].join(', ');
|
||||
displayValue += `${this.translationService.instant(this.tabbedFacet.facets[field].label + '_LABEL')}: ${stackedOptions} `;
|
||||
}
|
||||
});
|
||||
this.displayValue$.next(displayValue);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.resetSubject$.next();
|
||||
this.updateUserFacetBuckets();
|
||||
this.updateDisplayValue();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
submitValues() {
|
||||
this.updateUserFacetBuckets();
|
||||
this.searchFacetFiltersService.updateSelectedBuckets();
|
||||
this.updateDisplayValue();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
optionComparator(option1: AutocompleteOption, option2: AutocompleteOption): boolean {
|
||||
return option1.value.toUpperCase() === option2.value.toUpperCase();
|
||||
}
|
||||
|
||||
private updateUserFacetBuckets() {
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
this.tabbedFacet.facets[field].buckets.items.forEach((item) => {
|
||||
const matchedOption = this.selectedOptions[field].find((option) => option === item.display);
|
||||
if (matchedOption) {
|
||||
item.checked = true;
|
||||
this.queryBuilder.addUserFacetBucket(field, item);
|
||||
} else {
|
||||
item.checked = false;
|
||||
this.queryBuilder.removeUserFacetBucket(field, item);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
<adf-search-filter-tabbed>
|
||||
<ng-container *ngFor="let field of tabbedFacet.fields">
|
||||
<adf-search-chip-autocomplete-input
|
||||
*adf-search-filter-tab="tabbedFacet.facets[field]?.label"
|
||||
[autocompleteOptions]="autocompleteOptions[field]"
|
||||
[onReset$]="reset$"
|
||||
[allowOnlyPredefinedValues]="true"
|
||||
[compareOption]="optionComparator"
|
||||
(optionsChanged)="onOptionsChange($event, field)">
|
||||
</adf-search-chip-autocomplete-input>
|
||||
</ng-container>
|
||||
</adf-search-filter-tabbed>
|
@ -0,0 +1,183 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ContentTestingModule } from '../../../../testing/content.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
|
||||
import { SearchFilterList } from '../../../models/search-filter-list.model';
|
||||
import { FacetField } from '../../../models/facet-field.interface';
|
||||
import { SearchFacetFiltersService } from '../../../services/search-facet-filters.service';
|
||||
import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
|
||||
import { SearchFacetTabbedContentComponent } from './search-facet-tabbed-content.component';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('SearchFacetTabbedContentComponent', () => {
|
||||
let component: SearchFacetTabbedContentComponent;
|
||||
let fixture: ComponentFixture<SearchFacetTabbedContentComponent>;
|
||||
let queryBuilder: SearchQueryBuilderService;
|
||||
let searchFacetService: SearchFacetFiltersService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
fixture = TestBed.createComponent(SearchFacetTabbedContentComponent);
|
||||
component = fixture.componentInstance;
|
||||
queryBuilder = TestBed.inject(SearchQueryBuilderService);
|
||||
searchFacetService = TestBed.inject(SearchFacetFiltersService);
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
|
||||
const facet1: FacetField = { type: 'field', label: 'field', field: 'field', buckets: new SearchFilterList() };
|
||||
const facet2: FacetField = { type: 'field', label: 'field2', field: 'field2', buckets: new SearchFilterList() };
|
||||
|
||||
component.tabbedFacet = {
|
||||
fields: ['field', 'field2'],
|
||||
label: 'LABEL',
|
||||
facets: {
|
||||
field: facet1,
|
||||
field2: facet2
|
||||
}
|
||||
};
|
||||
|
||||
component.onReset$ = of(void 0);
|
||||
component.onApply$ = of(void 0);
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
function getTabs(): HTMLDivElement[] {
|
||||
return fixture.debugElement.queryAll(By.css('.mat-tab-label-content')).map((element) => element.nativeElement);
|
||||
}
|
||||
|
||||
function changeTab(tabIndex: number) {
|
||||
getTabs()[tabIndex].click();
|
||||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
function triggerComponentChanges() {
|
||||
component.ngOnChanges({
|
||||
tabbedFacet: new SimpleChange(null, component.tabbedFacet, false)
|
||||
});
|
||||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
function addBucketItem(field: string, displayValue: string) {
|
||||
component.tabbedFacet.facets[field].buckets.items.push({
|
||||
count: 1,
|
||||
label: displayValue,
|
||||
display: displayValue,
|
||||
filterQuery: ''
|
||||
});
|
||||
triggerComponentChanges();
|
||||
}
|
||||
|
||||
it('should display 2 tabs with specific labels', () => {
|
||||
const tabLabels = getTabs();
|
||||
expect(tabLabels.length).toBe(2);
|
||||
expect(tabLabels[0].innerText).toBe(component.tabbedFacet.facets['field'].label);
|
||||
expect(tabLabels[1].innerText).toBe(component.tabbedFacet.facets['field2'].label);
|
||||
});
|
||||
|
||||
it('should display creator tab as active initially and allow navigation', () => {
|
||||
let activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
|
||||
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field'].label);
|
||||
|
||||
changeTab(1);
|
||||
activeTabLabel = fixture.debugElement.query(By.css('.mat-tab-label-active .mat-tab-label-content')).nativeElement.innerText;
|
||||
expect(activeTabLabel).toBe(component.tabbedFacet.facets['field2'].label);
|
||||
});
|
||||
|
||||
it('should create empty selected options for each tab initially', () => {
|
||||
expect(component.selectedOptions['field']).toEqual([]);
|
||||
expect(component.selectedOptions['field2']).toEqual([]);
|
||||
});
|
||||
|
||||
it('should update autocomplete options when buckets change', () => {
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
expect(component.autocompleteOptions['field'].length).toBe(1);
|
||||
expect(component.autocompleteOptions['field'][0]).toEqual({value: 'test'});
|
||||
expect(component.autocompleteOptions['field2'].length).toBe(1);
|
||||
expect(component.autocompleteOptions['field2'][0]).toEqual({value: 'test2'});
|
||||
});
|
||||
|
||||
it('should add buckets when items are selected', () => {
|
||||
spyOn(queryBuilder, 'addUserFacetBucket');
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
component.onOptionsChange([{ value: 'test' }], 'field');
|
||||
expect(queryBuilder.addUserFacetBucket).toHaveBeenCalledWith('field',component.tabbedFacet.facets['field'].buckets.items[0]);
|
||||
});
|
||||
|
||||
it('should remove buckets when items are unselected', () => {
|
||||
spyOn(queryBuilder, 'removeUserFacetBucket');
|
||||
addBucketItem('field', 'test');
|
||||
addBucketItem('field2', 'test2');
|
||||
component.onOptionsChange([], 'field');
|
||||
expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith('field',component.tabbedFacet.facets['field'].buckets.items[0]);
|
||||
});
|
||||
|
||||
it('should update emit new display value when next elements are selected', () => {
|
||||
const selectedOption1 = 'test';
|
||||
const selectedOption2 = 'test2';
|
||||
spyOn(component.displayValue$, 'emit');
|
||||
addBucketItem('field', selectedOption1);
|
||||
addBucketItem('field', selectedOption2);
|
||||
component.onOptionsChange([{ value: selectedOption1 }, { value: selectedOption2 }],'field');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.displayValue$.emit).toHaveBeenCalledWith(`${component.tabbedFacet.facets['field'].label}_LABEL: ${selectedOption1}, ${selectedOption2} `);
|
||||
});
|
||||
|
||||
it('should update display value when elements from both tabs are selected', () => {
|
||||
const selectedOption1 = 'test';
|
||||
const selectedOption2 = 'test2';
|
||||
const displayValueEmitterSpy = spyOn(component.displayValue$, 'emit');
|
||||
addBucketItem('field', selectedOption1);
|
||||
addBucketItem('field2', selectedOption2);
|
||||
component.onOptionsChange([{value: selectedOption1}], 'field');
|
||||
component.onOptionsChange([{value: selectedOption2}], 'field2');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(displayValueEmitterSpy).toHaveBeenCalledTimes(2);
|
||||
expect(displayValueEmitterSpy.calls.allArgs()).toEqual([
|
||||
[`${component.tabbedFacet.facets['field'].label}_LABEL: ${selectedOption1} `],
|
||||
[`${component.tabbedFacet.facets['field'].label}_LABEL: ${selectedOption1} ${component.tabbedFacet.facets['field2'].label}_LABEL: ${selectedOption2} `]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should update search query and display value on submit',() => {
|
||||
spyOn(component, 'updateDisplayValue').and.callThrough();
|
||||
spyOn(component, 'submitValues').and.callThrough();
|
||||
spyOn(searchFacetService, 'updateSelectedBuckets').and.callThrough();
|
||||
component.submitValues();
|
||||
expect(component.submitValues).toHaveBeenCalled();
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
expect(component.updateDisplayValue).toHaveBeenCalled();
|
||||
expect(searchFacetService.updateSelectedBuckets).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update search query and display value on reset', () => {
|
||||
spyOn(component, 'updateDisplayValue').and.callThrough();
|
||||
component.reset();
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
expect(component.updateDisplayValue).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -0,0 +1,144 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { SearchQueryBuilderService } from '../../../services/search-query-builder.service';
|
||||
import { SEARCH_QUERY_SERVICE_TOKEN } from '../../../search-query-service.token';
|
||||
import { FacetWidget } from '../../../models/facet-widget.interface';
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { AutocompleteOption } from '../../../models/autocomplete-option.interface';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { TabbedFacetField } from '../../../models/tabbed-facet-field.interface';
|
||||
import { SearchFacetFiltersService } from '../../../services/search-facet-filters.service';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-facet-tabbed-content',
|
||||
templateUrl: './search-facet-tabbed-content.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class SearchFacetTabbedContentComponent implements OnInit, OnDestroy, OnChanges, FacetWidget {
|
||||
@Input()
|
||||
tabbedFacet: TabbedFacetField;
|
||||
|
||||
@Input()
|
||||
onReset$: Observable<void>;
|
||||
|
||||
@Input()
|
||||
onApply$: Observable<void>;
|
||||
|
||||
@Output()
|
||||
isPopulated = new EventEmitter<boolean>();
|
||||
|
||||
@Output()
|
||||
displayValue$ = new EventEmitter<string>();
|
||||
|
||||
private resetSubject$ = new Subject<void>();
|
||||
private onDestroy$ = new Subject<void>();
|
||||
|
||||
reset$ = this.resetSubject$.asObservable();
|
||||
chipIcon = 'keyboard_arrow_down';
|
||||
autocompleteOptions = {};
|
||||
selectedOptions = {};
|
||||
|
||||
constructor(@Inject(SEARCH_QUERY_SERVICE_TOKEN) private queryBuilder: SearchQueryBuilderService,
|
||||
private translationService: TranslationService,
|
||||
private searchFacetFiltersService: SearchFacetFiltersService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
Object.defineProperty(this.selectedOptions, field, {
|
||||
value: [],
|
||||
writable: true
|
||||
});
|
||||
});
|
||||
|
||||
this.onReset$?.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.reset());
|
||||
this.onApply$?.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.submitValues());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next();
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.tabbedFacet) {
|
||||
this.isPopulated.emit(this.tabbedFacet.fields.some((field) => this.tabbedFacet.facets[field]?.buckets.items.length > 0));
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
const options: AutocompleteOption[] = this.tabbedFacet.facets[field].buckets.items.map((item) => ({ value: item.display }));
|
||||
Object.defineProperty(this.autocompleteOptions, field, {
|
||||
value: options,
|
||||
writable: true
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onOptionsChange(selectedOptions: AutocompleteOption[], field: string) {
|
||||
this.selectedOptions[field] = selectedOptions.map((selectedOption) => selectedOption.value);
|
||||
this.isPopulated.emit(this.tabbedFacet.fields.some((facetField) => this.selectedOptions[facetField].length > 0));
|
||||
this.updateDisplayValue();
|
||||
this.updateUserFacetBuckets();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
updateDisplayValue() {
|
||||
let displayValue = '';
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
if (this.selectedOptions[field].length > 0) {
|
||||
const stackedOptions = this.selectedOptions[field].join(', ');
|
||||
displayValue += `${this.translationService.instant(this.tabbedFacet.facets[field].label + '_LABEL')}: ${stackedOptions} `;
|
||||
}
|
||||
});
|
||||
this.displayValue$.emit(displayValue);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.resetSubject$.next();
|
||||
this.updateUserFacetBuckets();
|
||||
this.updateDisplayValue();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
submitValues() {
|
||||
this.updateUserFacetBuckets();
|
||||
this.searchFacetFiltersService.updateSelectedBuckets();
|
||||
this.updateDisplayValue();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
optionComparator(option1: AutocompleteOption, option2: AutocompleteOption): boolean {
|
||||
return option1.value.toUpperCase() === option2.value.toUpperCase();
|
||||
}
|
||||
|
||||
private updateUserFacetBuckets() {
|
||||
this.tabbedFacet.fields.forEach((field) => {
|
||||
this.tabbedFacet.facets[field].buckets.items.forEach((item) => {
|
||||
const matchedOption = this.selectedOptions[field].find((option) => option === item.display);
|
||||
if (matchedOption) {
|
||||
item.checked = true;
|
||||
this.queryBuilder.addUserFacetBucket(field, item);
|
||||
} else {
|
||||
item.checked = false;
|
||||
this.queryBuilder.removeUserFacetBucket(field, item);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -24,6 +24,18 @@
|
||||
</adf-search-widget-container>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<ng-container *ngIf="facetFiltersService.tabbedFacet && showContextFacets">
|
||||
<mat-expansion-panel [attr.data-automation-id]="'expansion-panel-'+facetFiltersService.tabbedFacet.label" [expanded]="true">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ facetFiltersService.tabbedFacet.label | translate }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<adf-search-facet-tabbed-content
|
||||
[tabbedFacet]="facetFiltersService.tabbedFacet"
|
||||
[attr.data-automation-id]="'expansion-panel-'+facetFiltersService.tabbedFacet.label">
|
||||
</adf-search-facet-tabbed-content>
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="facetFiltersService.responseFacets && showContextFacets">
|
||||
<mat-expansion-panel [attr.data-automation-id]="'expansion-panel-'+field.label" *ngFor="let field of facetFiltersService.responseFacets"
|
||||
[expanded]="shouldExpand(field)">
|
||||
|
@ -69,5 +69,6 @@ export * from './components/reset-search.directive';
|
||||
export * from './components/search-chip-autocomplete-input/search-chip-autocomplete-input.component';
|
||||
export * from './components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component';
|
||||
export * from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-chip-tabbed.component';
|
||||
export * from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-tabbed-content.component';
|
||||
|
||||
export * from './search.module';
|
||||
|
@ -57,6 +57,7 @@ import { SearchDateRangeAdvancedComponent } from './components/search-date-range
|
||||
import { SearchDateRangeAdvancedTabbedComponent } from './components/search-date-range-advanced-tabbed/search-date-range-advanced-tabbed.component';
|
||||
import { SearchFilterTabDirective } from './components/search-filter-tabbed/search-filter-tab.directive';
|
||||
import { SearchFacetChipTabbedComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-chip-tabbed.component';
|
||||
import { SearchFacetTabbedContentComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-tabbed-content.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -100,7 +101,8 @@ import { SearchFacetChipTabbedComponent } from './components/search-filter-chips
|
||||
SearchDateRangeAdvancedComponent,
|
||||
SearchDateRangeAdvancedTabbedComponent,
|
||||
SearchFilterTabDirective,
|
||||
SearchFacetChipTabbedComponent
|
||||
SearchFacetChipTabbedComponent,
|
||||
SearchFacetTabbedContentComponent
|
||||
],
|
||||
exports: [
|
||||
SearchComponent,
|
||||
@ -129,7 +131,8 @@ import { SearchFacetChipTabbedComponent } from './components/search-filter-chips
|
||||
SearchFilterTabbedComponent,
|
||||
SearchDateRangeAdvancedComponent,
|
||||
ResetSearchDirective,
|
||||
SearchFacetChipTabbedComponent
|
||||
SearchFacetChipTabbedComponent,
|
||||
SearchFacetTabbedContentComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: SEARCH_QUERY_SERVICE_TOKEN, useExisting: SearchQueryBuilderService }
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { element, by, ElementFinder, browser } from 'protractor';
|
||||
import { element, by, ElementFinder, browser, protractor, By } from 'protractor';
|
||||
import { BrowserActions } from '../../../core/utils/browser-actions';
|
||||
import { BrowserVisibility } from '../../../core/utils/browser-visibility';
|
||||
|
||||
@ -58,6 +58,17 @@ export class SearchCheckListPage {
|
||||
return this;
|
||||
}
|
||||
|
||||
async enterFilterInputValue(option: string): Promise<SearchCheckListPage> {
|
||||
await this.checkSearchFilterInputIsDisplayed();
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.filter);
|
||||
const inputElement = this.filter.$$(this.inputBy).first();
|
||||
await BrowserVisibility.waitUntilElementIsClickable(inputElement);
|
||||
await BrowserActions.clearSendKeys(inputElement, option);
|
||||
await inputElement.sendKeys(protractor.Key.ENTER);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
async checkSearchFilterInputIsDisplayed(): Promise<void> {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.filter.$$(this.inputBy).first());
|
||||
}
|
||||
@ -116,6 +127,12 @@ export class SearchCheckListPage {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(result);
|
||||
}
|
||||
|
||||
async checkCheckListAutocompleteOptionIsDisplayed(option: string): Promise<void> {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
|
||||
const result = element(By.css(`mat-option[data-automation-id='option-${option}']`));
|
||||
await BrowserVisibility.waitUntilElementIsVisible(result);
|
||||
}
|
||||
|
||||
async checkCheckListOptionIsNotSelected(option: string): Promise<void> {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
|
||||
const result = this.filter.$(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`);
|
||||
|
Loading…
x
Reference in New Issue
Block a user