Skip to content

Commit

Permalink
fix: Route Builder rules should be case insensitive (#9040)
Browse files Browse the repository at this point in the history
* override jsonLogic operators on string operands to allow for case insensitive comparisons.

Affected Operators: "==", "===", "!=", "!==", "in"

* disable no-explicit-any on jsonLogicOverrides file since most of the code there will be from jsonLogic and may not meet our coding style.

Majority of overrides require us to copy over functions and their signatures from jsonLogic and then modify their implementation.

The signature of functions implementing most operators take the operands typed as "any", which is intended, but doesn't adhere to our coding style. Hence the need to override the eslint rule

* run linter to fix issues

* Fix bug in in operator when second arg is an array

* remove redundant indexOf check on overriden jsonLogic "in" operator.

Note: this deviates from the original implementation in the jsonLogic library because our current useage ensures that the second operand is always a string or string[] and will therefore always have .index function. Whenever our invariants change in the future, make sure to modify this implementation to prevent any unexpected

---------

Co-authored-by: Hariom Balhara <[email protected]>
  • Loading branch information
jemiluv8 and hariombalhara authored May 29, 2023
1 parent 5534153 commit 15e50fc
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
53 changes: 53 additions & 0 deletions packages/app-store/routing-forms/lib/jsonLogicOverrides.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import jsonLogic from "json-logic-js";

// converts input to lowercase if string
function normalize<T extends string | string[]>(input: T): T {
if (typeof input === "string") {
return input.toLowerCase() as T;
}
if (input instanceof Array) {
return input.map((item) => {
if (typeof item === "string") {
return item.toLowerCase();
}
// if array item is not a string, return it as is
return item;
}) as T;
}
return input;
}

/**
* Single Select equals and not equals uses it
* Short Text equals and not equals uses it
*/
jsonLogic.add_operation("==", function (a: any, b: any) {
return normalize(a) == normalize(b);
});

jsonLogic.add_operation("===", function (a: any, b: any) {
return normalize(a) === normalize(b);
});

jsonLogic.add_operation("!==", function (a: any, b: any) {
return normalize(a) !== normalize(b);
});

jsonLogic.add_operation("!=", function (a: any, b: any) {
return normalize(a) != normalize(b);
});

/**
* Multiselect "equals" and "not equals" uses it
* Singleselect "any in" and "not in" uses it
* Long Text/Short Text/Email/Phone "contains" also uses it.
*/
jsonLogic.add_operation("in", function (a: string, b: string | string[]) {
const first = normalize(a);
const second = normalize(b);
if (!second) return false;
return second.indexOf(first) !== -1;
});

export default jsonLogic;
2 changes: 1 addition & 1 deletion packages/app-store/routing-forms/lib/processRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { App_RoutingForms_Form } from "@prisma/client";
import jsonLogic from "json-logic-js";
import { Utils as QbUtils } from "react-awesome-query-builder";
import type { z } from "zod";

Expand All @@ -8,6 +7,7 @@ import type { zodNonRouterRoute } from "../zod";
import { getQueryBuilderConfig } from "./getQueryBuilderConfig";
import { isFallbackRoute } from "./isFallbackRoute";
import isRouter from "./isRouter";
import jsonLogic from "./jsonLogicOverrides";

export function processRoute({
form,
Expand Down
6 changes: 3 additions & 3 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ const outputDir = path.join(__dirname, "test-results");
// Dev Server on local can be slow to start up and process requests. So, keep timeouts really high on local, so that tests run reliably locally

// So, if not in CI, keep the timers high, if the test is stuck somewhere and there is unnecessary wait developer can see in browser that it's stuck
const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 50000;
const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 15000 : 50000;
const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 120000;
const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 15000 : 120000;

// Test Timeout can hit due to slow expect, slow navigation.
// So, it should me much higher than sum of expect and navigation timeouts as there can be many async expects and navigations in a single test
const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 120000;
const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 240000;

const headless = !!process.env.CI || !!process.env.PLAYWRIGHT_HEADLESS;

Expand Down

1 comment on commit 15e50fc

@vercel
Copy link

@vercel vercel bot commented on 15e50fc May 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./apps/storybook

ui-git-main-cal.vercel.app
ui-cal.vercel.app
ui.cal.com
www.timelessui.com
timelessui.com
cal-com-storybook.vercel.app

Please sign in to comment.