From 44563fd244db1aabd64dc1bc9539642362963b04 Mon Sep 17 00:00:00 2001
From: mmitiche <86681870+mmitiche@users.noreply.github.com>
Date: Tue, 29 Oct 2024 11:04:51 -0400
Subject: [PATCH] feat(quantic): added support to the custom sort property in
the quantic facet component (#4600)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## [SFINT-5316](https://coveord.atlassian.net/browse/SFINT-5316)
- Exposed the property `customSort` in the Quantic Facet, this property
allows the end user to specify a custom order of the facet values.
#### Example: with `customSort` set to `[]`:
#### Example: with `customSort` set to `['HTML', 'incident']`:
- This new logic is being unit tested. the unit tests of remaining logic
of the component will be added in a later PR after doing the migration
to the E2E Playwright tests.
[SFINT-5316]:
https://coveord.atlassian.net/browse/SFINT-5316?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
---------
Co-authored-by: Simon Milord
Co-authored-by: Etienne Rocheleau
---
.../__tests__/quanticFacet.test.js | 102 ++++++++++++++++++
.../default/lwc/quanticFacet/quanticFacet.js | 14 +++
.../templates/disabledDynamicNavigation.html | 1 +
.../templates/dynamicNavigation.html | 1 +
packages/quantic/jest.config.js | 2 +
5 files changed, 120 insertions(+)
create mode 100644 packages/quantic/force-app/main/default/lwc/quanticFacet/__tests__/quanticFacet.test.js
diff --git a/packages/quantic/force-app/main/default/lwc/quanticFacet/__tests__/quanticFacet.test.js b/packages/quantic/force-app/main/default/lwc/quanticFacet/__tests__/quanticFacet.test.js
new file mode 100644
index 00000000000..04ed94b5425
--- /dev/null
+++ b/packages/quantic/force-app/main/default/lwc/quanticFacet/__tests__/quanticFacet.test.js
@@ -0,0 +1,102 @@
+/* eslint-disable no-import-assign */
+// @ts-ignore
+import {createElement} from 'lwc';
+import QuanticFacet from 'c/quanticFacet';
+import * as mockHeadlessLoader from 'c/quanticHeadlessLoader';
+
+jest.mock('c/quanticHeadlessLoader');
+
+function createTestComponent(options = {}) {
+ prepareHeadlessState();
+
+ const element = createElement('c-quantic-facet', {
+ is: QuanticFacet,
+ });
+ for (const [key, value] of Object.entries(options)) {
+ element[key] = value;
+ }
+
+ document.body.appendChild(element);
+ return element;
+}
+
+const functionsMocks = {
+ buildFacet: jest.fn(() => ({
+ subscribe: jest.fn((callback) => callback()),
+ state: {
+ values: [],
+ },
+ })),
+ buildSearchStatus: jest.fn(() => ({
+ subscribe: jest.fn((callback) => callback()),
+ state: {},
+ })),
+};
+
+function prepareHeadlessState() {
+ // @ts-ignore
+ mockHeadlessLoader.getHeadlessBundle = () => {
+ return {
+ buildFacet: functionsMocks.buildFacet,
+ buildSearchStatus: functionsMocks.buildSearchStatus,
+ };
+ };
+}
+
+// Helper function to wait until the microtask queue is empty.
+function flushPromises() {
+ // eslint-disable-next-line @lwc/lwc/no-async-operation
+ return new Promise((resolve) => setTimeout(resolve, 0));
+}
+
+const exampleEngine = {
+ id: 'dummy engine',
+};
+let isInitialized = false;
+
+function mockSuccessfulHeadlessInitialization() {
+ // @ts-ignore
+ mockHeadlessLoader.initializeWithHeadless = (element, _, initialize) => {
+ if (element instanceof QuanticFacet && !isInitialized) {
+ isInitialized = true;
+ initialize(exampleEngine);
+ }
+ };
+}
+
+function cleanup() {
+ // The jsdom instance is shared across test cases in a single file so reset the DOM
+ while (document.body.firstChild) {
+ document.body.removeChild(document.body.firstChild);
+ }
+ jest.clearAllMocks();
+ isInitialized = false;
+}
+
+describe('c-quantic-facet', () => {
+ beforeAll(() => {
+ mockSuccessfulHeadlessInitialization();
+ });
+
+ afterEach(() => {
+ cleanup();
+ });
+
+ describe('controller initialization', () => {
+ it('should initialize the controller with the correct customSort value', async () => {
+ const exampleCustomSortValues = ['test'];
+ createTestComponent({customSort: exampleCustomSortValues});
+ await flushPromises();
+
+ expect(functionsMocks.buildFacet).toHaveBeenCalledTimes(1);
+ expect(functionsMocks.buildFacet).toHaveBeenCalledWith(
+ exampleEngine,
+ expect.objectContaining({
+ options: expect.objectContaining({
+ customSort: exampleCustomSortValues,
+ }),
+ })
+ );
+ });
+ });
+});
diff --git a/packages/quantic/force-app/main/default/lwc/quanticFacet/quanticFacet.js b/packages/quantic/force-app/main/default/lwc/quanticFacet/quanticFacet.js
index 7994301b74d..2443cb6dbca 100644
--- a/packages/quantic/force-app/main/default/lwc/quanticFacet/quanticFacet.js
+++ b/packages/quantic/force-app/main/default/lwc/quanticFacet/quanticFacet.js
@@ -129,6 +129,16 @@ export default class QuanticFacet extends LightningElement {
* @defaultValue `1000`
*/
@api injectionDepth = 1000;
+ /**
+ * Identifies the facet values that must appear at the top, in order.
+ * This parameter can be used in conjunction with the `sortCriteria` parameter.
+ * Facet values not part of the `customSort` list will be sorted according to the `sortCriteria`.
+ * The maximum amount of custom sort values is 25.
+ * The default value is `undefined`, and the facet values will be sorted using only the `sortCriteria`.
+ * @api
+ * @type {String[]}
+ */
+ @api customSort;
/**
* Whether the facet is collapsed.
* @api
@@ -154,6 +164,7 @@ export default class QuanticFacet extends LightningElement {
'displayValuesAs',
'noFilterFacetCount',
'injectionDepth',
+ 'customSort',
];
/** @type {FacetState} */
@@ -249,6 +260,9 @@ export default class QuanticFacet extends LightningElement {
facetId: this.facetId ?? this.field,
filterFacetCount: !this.noFilterFacetCount,
injectionDepth: Number(this.injectionDepth),
+ customSort: Array.isArray(this.customSort)
+ ? [...this.customSort]
+ : undefined,
};
this.facet = this.headless.buildFacet(engine, {options});
this.unsubscribe = this.facet.subscribe(() => this.updateState());
diff --git a/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/disabledDynamicNavigation.html b/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/disabledDynamicNavigation.html
index af19c4c8f75..944ad407846 100644
--- a/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/disabledDynamicNavigation.html
+++ b/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/disabledDynamicNavigation.html
@@ -120,6 +120,7 @@
no-filter-facet-count={facet.noFilterFacetCount}
injection-depth={facet.injectionDepth}
key={facet.field}
+ custom-sort={facet.customSort}
is-collapsed
>
diff --git a/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/dynamicNavigation.html b/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/dynamicNavigation.html
index 058def95d12..0e0f37c4601 100644
--- a/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/dynamicNavigation.html
+++ b/packages/quantic/force-app/main/default/lwc/quanticRefineModalContent/templates/dynamicNavigation.html
@@ -121,6 +121,7 @@
no-filter-facet-count={facet.noFilterFacetCount}
injection-depth={facet.injectionDepth}
key={facet.field}
+ custom-sort={facet.customSort}
is-collapsed
>
diff --git a/packages/quantic/jest.config.js b/packages/quantic/jest.config.js
index d41019db77f..79116280322 100644
--- a/packages/quantic/jest.config.js
+++ b/packages/quantic/jest.config.js
@@ -29,6 +29,8 @@ module.exports = {
'/force-app/main/default/lwc/quanticResultActionStyles/quanticResultActionStyles',
'^c/searchBoxStyle$':
'/force-app/main/default/lwc/searchBoxStyle/searchBoxStyle',
+ '^c/quanticFacetStyles$':
+ '/force-app/main/default/lwc/quanticFacetStyles/quanticFacetStyles',
},
modulePathIgnorePatterns: ['.cache'],
// add any custom configurations here