Add support for multiselect_some_in for attributes query (#17144)

This commit is contained in:
Hariom Balhara
2024-10-17 12:16:34 +00:00
committed by GitHub
parent cd2382e091
commit ab39f0c8b6
4 changed files with 150 additions and 89 deletions
@@ -60,9 +60,13 @@ describe("Query Builder Config", () => {
assertCommonStructure(FormFieldsBaseConfig);
});
it("should not support multiselect_contains and multiselect_not_contains - because they are not supported in Prisma for reporting(probably)", () => {
expect(FormFieldsBaseConfig.operators).not.toHaveProperty("multiselect_contains");
expect(FormFieldsBaseConfig.operators).not.toHaveProperty("multiselect_not_contains");
it("should not support multiselect_some_in and multiselect_not_some_in - because they are not supported in Prisma for reporting(probably)", () => {
expect(FormFieldsBaseConfig.types.multiselect.widgets.multiselect.operators).not.toContain(
"multiselect_some_in"
);
expect(FormFieldsBaseConfig.types.multiselect.widgets.multiselect.operators).not.toContain(
"multiselect_not_some_in"
);
});
it("should support select_any_in, select_not_any_in, select_equals, select_not_equals - Verify both types.widgets and operators", () => {
@@ -83,9 +87,23 @@ describe("Query Builder Config", () => {
assertCommonStructure(AttributesBaseConfig);
});
it("should support multiselect_contains and multiselect_not_contains operators", () => {
expect(AttributesBaseConfig.operators).toHaveProperty("multiselect_contains");
expect(AttributesBaseConfig.operators).toHaveProperty("multiselect_not_contains");
it("should support multiselect_some_in operator for multiselect", () => {
expect(AttributesBaseConfig.types.multiselect.widgets.multiselect.operators).toContain(
"multiselect_some_in"
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const jsonLogic = AttributesBaseConfig.operators.multiselect_some_in.jsonLogic(
["A"],
"multiselect_some_in",
["A", "B"]
);
// Verifies that it is using some-in implementation
expect(jsonLogic).toEqual({
some: [["A"], { in: [{ var: "" }, ["A", "B"]] }],
});
});
it("should support select_any_in, select_not_any_in, select_equals, select_not_equals - Verify both types.widgets and operators", () => {
@@ -179,21 +179,30 @@ const operators: Operators = {
labelForFormat: "NOT IN",
reversedOp: "select_any_in",
},
// We define this operator but use it conditionally for multiselect for Attributes only
multiselect_some_in: {
label: "Any in",
jsonLogic: (field: any, operator: any, vals: any) => {
return {
// Tested in jsonLogic.test.ts
some: [field, { in: [{ var: "" }, vals] }],
};
},
},
multiselect_equals: {
// TODO: Consider renaming it to "includes" or similar due to faulty implementation of jsonLogic and the operator is in use by users.
label: "Equals",
labelForFormat: "==",
label: "All in",
reversedOp: "multiselect_not_equals",
// jsonLogic2: "all-in",
jsonLogic: (field: any, op: any, vals: any) => ({
// This is wrongly implemented as "includes". This isn't "equals". Because if field is ["a" ] and vals is ["a", "b"], it still matches. Expectation would probably be that it should be a strict match(["a", "b"] or ["b", "a"])
all: [field, { in: [{ var: "" }, vals] }],
}),
jsonLogic: (field: any, op: any, vals: any, ...rest) => {
return {
// This is wrongly implemented as "includes". This isn't "equals". Because if field is ["a" ] and vals is ["a", "b"], it still matches. Expectation would probably be that it should be a strict match(["a", "b"] or ["b", "a"])
all: [field, { in: [{ var: "" }, vals] }],
};
},
},
multiselect_not_equals: {
isNotOp: true,
label: "Not equals",
labelForFormat: "!=",
label: "Not all in",
reversedOp: "multiselect_equals",
},
some: {
@@ -356,14 +365,7 @@ const types: Types = {
defaultOperator: "multiselect_equals",
widgets: {
multiselect: {
operators: [
"multiselect_equals",
"multiselect_not_equals",
// "is_empty",
// "is_not_empty",
"is_null",
"is_not_null",
],
operators: ["multiselect_equals", "multiselect_not_equals", "is_null", "is_not_null"],
},
},
},
@@ -129,7 +129,15 @@ function getWidgets(_configFor: ConfigFor) {
return widgets;
}
function getTypes(_configFor: ConfigFor) {
function getTypes(configFor: ConfigFor) {
const multiSelectOperators = BasicConfig.types.multiselect.widgets.multiselect.operators || [];
if (configFor === ConfigFor.Attributes) {
// Attributes don't need reporting at the moment. So, we can support multiselect_some_in operator for attributes.
// We could probably use them in FormFields later once they are supported through Prisma query as well
multiSelectOperators.push("multiselect_some_in");
}
const types: Types = {
...BasicConfig.types,
phone: {
@@ -150,12 +158,7 @@ function getTypes(_configFor: ConfigFor) {
...BasicConfig.types.multiselect.widgets,
multiselect: {
...BasicConfig.types.multiselect.widgets.multiselect,
operators: [
...(BasicConfig.types.multiselect.widgets.multiselect.operators || []),
// TODO: First verify the definition of multiselect_contains and multiselect_not_contains and then uncomment these operators
// "multiselect_contains",
// "multiselect_not_contains",
],
operators: [...multiSelectOperators],
},
},
},
@@ -167,58 +170,6 @@ function getOperators(configFor: ConfigFor) {
// Clone to avoid mutating the original object
const operators: Operators = {
...BasicConfig.operators,
// Attributes don't need reporting at the moment. So, we can support contains and not contains operators for attributes.
// We could probably use them in FormFields if they are supported through Prisma query as well.
...(configFor === ConfigFor.Attributes
? {
multiselect_contains: {
label: "Contains",
labelForFormat: "CONTAINS",
reversedOp: "multiselect_not_contains",
// jsonLogic2: "some-in",
jsonLogic: function (e, t, r) {
return {
some: [
e,
{
in: [
{
var: "",
},
r,
],
},
],
};
},
},
multiselect_not_contains: {
isNotOp: !0,
label: "Not contains",
labelForFormat: "NOT CONTAINS",
reversedOp: "multiselect_contains",
// jsonLogic2: "!some-in",
jsonLogic: function (e, t, r) {
return {
"!": {
some: [
e,
{
in: [
{
var: "",
},
r,
],
},
],
},
};
},
_jsonLogicIsExclamationOp: !0,
},
}
: {}),
};
return operators;
@@ -67,7 +67,45 @@ describe("jsonLogic", () => {
});
});
describe("all-in", () => {
describe("all-in -> used by multiselect_equals", () => {
it("should return true if all elements of the array in 'data' is in the jsonLogic 'in' array using case insensitivity", () => {
expect(
jsonLogic.apply(
{
and: [
{
all: [{ var: "location" }, { in: [{ var: "" }, ["nevada", "abc"]] }],
},
],
},
// Data
{
there: "no",
location: ["nevada"],
}
)
).toBe(true);
});
it("should return false if even one element of the array in 'data' is not in the jsonLogic 'in' array using case insensitivity", () => {
expect(
jsonLogic.apply(
{
and: [
{
all: [{ var: "location" }, { in: [{ var: "" }, ["India", "Canada"]] }],
},
],
},
// Data
{
there: "no",
location: ["India", "Australia"],
}
)
).toBe(false);
});
it("should return true if the variable value is an array and contains the string", () => {
expect(
jsonLogic.apply(
@@ -78,17 +116,18 @@ describe("jsonLogic", () => {
},
],
},
// Data
{
there: "no",
location: ["nevada"],
location: "nevada",
}
)
).toBe(true);
).toBe(false);
});
});
describe("some-in", () => {
it("should return true if the variable value is an array and contains the string", () => {
describe("some-in -> used by multiselect_some_in", () => {
it("should return true if the only element of the array in 'data' is in the jsonLogic 'in' array using case insensitivity", () => {
expect(
jsonLogic.apply(
{
@@ -99,17 +138,68 @@ describe("jsonLogic", () => {
{
var: "",
},
["nevada", "ABC"],
["India", "USA"],
],
},
],
},
// data
{
there: "no",
location: ["nevada"],
location: ["india"],
}
)
).toBe(true);
});
it("should return true if at least one element of the array in 'data' is in the jsonLogic 'in' array using case insensitivity", () => {
expect(
jsonLogic.apply(
{
some: [
{ var: "location" },
{
in: [
{
var: "",
},
["India", "USA"],
],
},
],
},
// Data
{
there: "no",
location: ["india", "Australia"],
}
)
).toBe(true);
});
it("should return false if none of the elements of the array in 'data' is in the jsonLogic 'in' array using case insensitivity", () => {
expect(
jsonLogic.apply(
{
some: [
{ var: "location" },
{
in: [
{
var: "",
},
["India", "Canada"],
],
},
],
},
// Data
{
there: "no",
location: ["Australia", "Iceland"],
}
)
).toBe(false);
});
});
});