2022-05-04 09:45:57 +00:00
|
|
|
import {
|
|
|
|
|
ButtonBorderRadiusTypes,
|
|
|
|
|
ButtonVariantTypes,
|
|
|
|
|
} from "components/constants";
|
2023-09-06 12:15:04 +00:00
|
|
|
import type { PropertyUpdates } from "WidgetProvider/constants";
|
2022-11-23 09:48:23 +00:00
|
|
|
import {
|
|
|
|
|
RenderModes,
|
|
|
|
|
TextSizes,
|
|
|
|
|
WidgetHeightLimits,
|
|
|
|
|
} from "constants/WidgetConstants";
|
2022-05-04 09:45:57 +00:00
|
|
|
import { remove } from "lodash";
|
2021-11-06 08:00:57 +00:00
|
|
|
import { getTheme, ThemeMode } from "selectors/themeSelectors";
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
import type { WidgetProps } from "./BaseWidget";
|
2023-09-06 12:15:04 +00:00
|
|
|
import { rgbaMigrationConstantV56 } from "../WidgetProvider/constants";
|
2022-05-04 09:45:57 +00:00
|
|
|
import {
|
|
|
|
|
borderRadiusUtility,
|
|
|
|
|
replaceRgbaMigrationConstant,
|
|
|
|
|
boxShadowMigration,
|
|
|
|
|
boxShadowUtility,
|
|
|
|
|
fontSizeUtility,
|
|
|
|
|
lightenColor,
|
2022-07-14 07:02:35 +00:00
|
|
|
composePropertyUpdateHook,
|
2022-05-04 09:45:57 +00:00
|
|
|
sanitizeKey,
|
2022-11-23 09:48:23 +00:00
|
|
|
shouldUpdateWidgetHeightAutomatically,
|
|
|
|
|
isAutoHeightEnabledForWidget,
|
2023-04-03 06:11:10 +00:00
|
|
|
isAutoHeightEnabledForWidgetWithLimits,
|
2022-11-23 09:48:23 +00:00
|
|
|
getWidgetMaxAutoHeight,
|
|
|
|
|
getWidgetMinAutoHeight,
|
2023-10-13 09:08:01 +00:00
|
|
|
isCompactMode,
|
2022-05-04 09:45:57 +00:00
|
|
|
} from "./WidgetUtils";
|
2021-11-06 08:00:57 +00:00
|
|
|
import {
|
|
|
|
|
getCustomTextColor,
|
|
|
|
|
getCustomBackgroundColor,
|
|
|
|
|
getCustomHoverColor,
|
|
|
|
|
} from "./WidgetUtils";
|
|
|
|
|
|
2022-05-04 09:45:57 +00:00
|
|
|
const tableWidgetProps = {
|
|
|
|
|
dynamicBindingPathList: [
|
|
|
|
|
{
|
|
|
|
|
key: "primaryColumns.action.boxShadowColor",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
primaryColumns: {
|
|
|
|
|
action: {
|
|
|
|
|
boxShadow: "0px 0px 4px 3px rgba(0, 0, 0, 0.25)",
|
|
|
|
|
boxShadowColor: ["red", "red", "red"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2021-11-06 08:00:57 +00:00
|
|
|
describe("validate widget utils button style functions", () => {
|
|
|
|
|
const theme = getTheme(ThemeMode.LIGHT);
|
|
|
|
|
// validate getCustomTextColor function
|
|
|
|
|
it("getCustomTextColor - validate empty or undefined background color", () => {
|
|
|
|
|
// background color is undefined
|
|
|
|
|
const result = getCustomTextColor(theme);
|
|
|
|
|
expect(result).toStrictEqual("#FFFFFF");
|
|
|
|
|
|
|
|
|
|
// background color is empty string
|
|
|
|
|
const backgroundColor = "";
|
|
|
|
|
const expected = "#FFFFFF";
|
|
|
|
|
const result2 = getCustomTextColor(theme, backgroundColor);
|
|
|
|
|
expect(result2).toStrictEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("getCustomTextColor - validate text color in case of dark or light background color", () => {
|
|
|
|
|
// background color is dark
|
|
|
|
|
const blueBackground = "#3366FF";
|
|
|
|
|
const expected1 = "#FFFFFF";
|
|
|
|
|
const result1 = getCustomTextColor(theme, blueBackground);
|
|
|
|
|
expect(result1).toStrictEqual(expected1);
|
|
|
|
|
|
|
|
|
|
// background color is light
|
|
|
|
|
const yellowBackground = "#FFC13D";
|
2022-05-04 09:45:57 +00:00
|
|
|
const expected2 = "#FFFFFF";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result2 = getCustomTextColor(theme, yellowBackground);
|
2022-05-04 09:45:57 +00:00
|
|
|
|
2021-11-06 08:00:57 +00:00
|
|
|
expect(result2).toStrictEqual(expected2);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// validate getCustomBackgroundColor function
|
|
|
|
|
it("getCustomBackgroundColor - validate empty or undefined background color", () => {
|
|
|
|
|
const expected = "none";
|
|
|
|
|
const result = getCustomBackgroundColor();
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("getCustomBackgroundColor - validate background color with primary button variant", () => {
|
|
|
|
|
const backgroundColor = "#03b365";
|
|
|
|
|
const expected = "#03b365";
|
|
|
|
|
const result = getCustomBackgroundColor(
|
|
|
|
|
ButtonVariantTypes.PRIMARY,
|
|
|
|
|
backgroundColor,
|
|
|
|
|
);
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("getCustomBackgroundColor - validate background color with secondary button variant", () => {
|
|
|
|
|
const backgroundColor = "#03b365";
|
|
|
|
|
const expected = "none";
|
|
|
|
|
const result = getCustomBackgroundColor(
|
|
|
|
|
ButtonVariantTypes.SECONDARY,
|
|
|
|
|
backgroundColor,
|
|
|
|
|
);
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// validate getCustomHoverColor function
|
|
|
|
|
it("getCustomHoverColor - validate empty or undefined background color or variant", () => {
|
|
|
|
|
// background color and variant is both are undefined
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected = "hsl(0, 0%, 95%)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result = getCustomHoverColor(theme);
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
|
|
|
|
|
// variant is undefined
|
|
|
|
|
const backgroundColor = "#03b365";
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected1 = "hsl(153, 97%, 31%)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result1 = getCustomHoverColor(theme, undefined, backgroundColor);
|
|
|
|
|
expect(result1).toStrictEqual(expected1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// validate getCustomHoverColor function
|
|
|
|
|
it("getCustomHoverColor - validate hover color for different variant", () => {
|
2022-09-30 11:24:21 +00:00
|
|
|
const backgroundColor = "hsl(153, 97% ,36%)";
|
2021-11-06 08:00:57 +00:00
|
|
|
// variant : PRIMARY
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected1 = "hsl(153, 97%, 31%)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result1 = getCustomHoverColor(
|
|
|
|
|
theme,
|
|
|
|
|
ButtonVariantTypes.PRIMARY,
|
|
|
|
|
backgroundColor,
|
|
|
|
|
);
|
2022-05-04 09:45:57 +00:00
|
|
|
|
2021-11-06 08:00:57 +00:00
|
|
|
expect(result1).toStrictEqual(expected1);
|
|
|
|
|
|
|
|
|
|
// variant : PRIMARY without background
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected2 = "hsl(0, 0%, 95%)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result2 = getCustomHoverColor(theme, ButtonVariantTypes.PRIMARY);
|
|
|
|
|
expect(result2).toStrictEqual(expected2);
|
|
|
|
|
|
|
|
|
|
// variant : SECONDARY
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected3 = "rgba(3, 181, 101, 0.1)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result3 = getCustomHoverColor(
|
|
|
|
|
theme,
|
|
|
|
|
ButtonVariantTypes.SECONDARY,
|
|
|
|
|
backgroundColor,
|
|
|
|
|
);
|
2022-05-04 09:45:57 +00:00
|
|
|
|
2021-11-06 08:00:57 +00:00
|
|
|
expect(result3).toStrictEqual(expected3);
|
|
|
|
|
|
|
|
|
|
// variant : SECONDARY without background
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected4 = "rgba(255, 255, 255, 0.1)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result4 = getCustomHoverColor(theme, ButtonVariantTypes.SECONDARY);
|
|
|
|
|
expect(result4).toStrictEqual(expected4);
|
|
|
|
|
|
|
|
|
|
// variant : TERTIARY
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected5 = "rgba(3, 181, 101, 0.1)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result5 = getCustomHoverColor(
|
|
|
|
|
theme,
|
|
|
|
|
ButtonVariantTypes.TERTIARY,
|
|
|
|
|
backgroundColor,
|
|
|
|
|
);
|
|
|
|
|
expect(result5).toStrictEqual(expected5);
|
|
|
|
|
|
|
|
|
|
// variant : TERTIARY without background
|
2022-09-30 11:24:21 +00:00
|
|
|
const expected6 = "rgba(255, 255, 255, 0.1)";
|
2021-11-06 08:00:57 +00:00
|
|
|
const result6 = getCustomHoverColor(theme, ButtonVariantTypes.TERTIARY);
|
|
|
|
|
expect(result6).toStrictEqual(expected6);
|
|
|
|
|
});
|
2021-11-25 10:52:40 +00:00
|
|
|
|
2022-05-04 09:45:57 +00:00
|
|
|
it("Check if the color is lightened with lightenColor utility", () => {
|
|
|
|
|
/**
|
|
|
|
|
* Colors with :
|
|
|
|
|
* 0% brightness = #000000,
|
|
|
|
|
* > 40% brightness = #696969
|
|
|
|
|
* > 50% brightness = #8a8a8a
|
|
|
|
|
* > 60% brightness = #b0b0b0
|
|
|
|
|
* > 70% brightness = #d6d4d4
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const actualColors = [
|
|
|
|
|
"#000000",
|
|
|
|
|
"#696969",
|
|
|
|
|
"#8a8a8a",
|
|
|
|
|
"#b0b0b0",
|
|
|
|
|
"#d6d4d4",
|
|
|
|
|
];
|
|
|
|
|
const lightColors = ["#ededed", "#ededed", "#ededed", "#ededed", "#eeeded"];
|
|
|
|
|
|
|
|
|
|
actualColors.forEach((color, idx) => {
|
|
|
|
|
expect(lightenColor(color)).toEqual(lightColors[idx]);
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-11-06 08:00:57 +00:00
|
|
|
});
|
feat: JSON Form widget (#8472)
* initial layout
* updated parser to support nested array
* array field rendering
* changes
* ts fix
* minor revert FormWidget
* modified schema structure
* select and switch fields
* added checkbox field
* added RadioGroupField
* partial DateField and defaults, typing refactoring
* added label and field type change
* minor ts changes
* changes
* modified widget/utils for nested panelConfig, modified schema to object approach
* array/object label support
* hide field configuration when children not present
* added tooltip
* field visibility option
* disabled state
* upgraded tslib, form initial values
* custom field configuration - add/hide/edit
* field configuration - label change
* return input when field configuration reaches max depth
* minor changes
* form - scroll, fixedfooter, enitity defn and other minior changes
* form title
* unregister on unmount
* fixes
* zero state
* fix field padding
* patched updating form values, removed linting warnings
* configured action buttons
* minor fix
* minor change
* property pane - sort fields in field configuration
* refactor include all properties
* checkbox properties
* date properties
* refactor typings and radio group properties
* switch, multselect, select, array, object properties
* minor changes
* default value
* ts fixes
* checkbox field properties implementation
* date field prop implementation
* switch field
* select field and fix deep nested meta properties
* multiselect implementation
* minor change
* input field implementation
* fix position jump on field type change
* initial accordian
* field state property and auto-complete of JSONFormComputeControl
* merge fixes
* renamed FormBuilder to JSONForm
* source data validation minor change
* custom field default value fix
* Editable keys for custom field
* minor fixes
* replaced useFieldArray with custom logic, added widget icon
* array and object accordian with border/background styling
* minor change
* disabled states for array and objects
* default value minor fix
* form level styles
* modified logic for isDisabled for array and object, added disabledWhenInvalid, exposed isValid to fieldState for text input, removed useDisableChildren
* added isValid for all field types
* fixed reset to default values
* debounce form values update
* minor change
* minor change
* fix crash - source data change multi-select to array, fix crash - change of options
* fix positioning
* detect date type in source data
* fix crash - when object is passed to regex input field
* fixed default sourceData path for fields
* accodion keep children mounted on collapse
* jest test for schemaParser
* widget/helper and useRegisterFieldInvalid test
* tests for property config helper and generatePanelPropertyConfig
* fix input field validation not appearing
* fix date field type detection
* rename data -> formData
* handle null/undefined field value change in sourceData
* added null/undefined as valid values for defaultValue text field
* auto detect email field
* set formData default value on initial load
* switch field inline positioning
* field margin fix for row direction
* select full width
* fiex date field default value - out of range
* fix any field type to array
* array default value logic change
* base cypress test changes
* initial json form render cy test
* key sanitization
* fix fieldState update logic
* required design, object/array background color, accordion changes, fix - add new custom field
* minor change
* cypress tests
* fix date formatted value, field state cypress test
* cypress - field properties test and fixes
* rename test file
* fix accessort change to blank value, cypress tests
* fix array field default value for modified accessor
* minor fix
* added animate loading
* fix empty state, add new custom field
* test data fix
* fix warnings
* fix timePrecision visibility
* button styling
* ported input v2
* fix jest tests
* fix cypress tests
* perf changes
* perf improvement
* added comments
* multiselect changes
* input field perf refactor
* array field, object field refactor performance
* checkbox field refactor
* refectored date, radio, select and switch
* fixes
* test fixes
* fixes
* minor fix
* rename field renderer
* remove tracked fieldRenderer field
* cypress test fixes
* cypress changes
* array default value fixes
* arrayfield passedDefaultValue
* auto enabled JS mode for few properties, reverted swith and date property controls
* cypress changes
* added widget sniping mode and fixed object passedDefaultValue
* multiselect v2
* select v2
* fix jest tests
* test fixes
* field limit
* rename field type dropdown texts
* field type changes fixes
* jest fixes
* loading state submit button
* default source data for new widget
* modify limit message
* multiseelct default value changes and cypress fix
* select default value
* keep default value intact on field type change
* TextTable cypress text fix
* review changes
* fixed footer changes
* collapse styles section by default
* fixed footer changes
* form modes
* custom field key rentention
* fixed footer fix in view mode
* non ascii characters
* fix meta merge in dataTreeWidget
* minor fixes
* rename useRegisterFieldInvalid.ts -> useRegisterFieldValidity.ts
* modified dependency injection into evaluated values
* refactored fixedfooter logic
* minor change
* accessor update
* minor change
* fixes
* QA fixes date field, scroll content
* fix phone number field, removed visiblity option from array item
* fix sourceData autocomplete
* reset logic
* fix multiselect reset
* form values hydration on widget drag
* code review changes
* reverted order of merge dataTreeWidget
* fixes
* added button titles, fixed hydration issue
* default value fixes
* upgraded react hook form, modified array-level/field-level default value logic
* fixed select validation
* added icon entity explorer, modified icon align control
* modify accessor validation for mongo db _id
* update email field regex
* review changes
* explicitly handle empty source data validation
2022-03-24 07:13:25 +00:00
|
|
|
|
|
|
|
|
describe(".sanitizeKey", () => {
|
|
|
|
|
it("returns sanitized value when passed a valid string", () => {
|
|
|
|
|
const inputAndExpectedOutput = [
|
|
|
|
|
["lowercase", "lowercase"],
|
|
|
|
|
["__abc__", "__abc__"],
|
|
|
|
|
["lower_snake_case", "lower_snake_case"],
|
|
|
|
|
["UPPER_SNAKE_CASE", "UPPER_SNAKE_CASE"],
|
|
|
|
|
["PascalCase", "PascalCase"],
|
|
|
|
|
["camelCase", "camelCase"],
|
|
|
|
|
["lower-kebab-case", "lower_kebab_case"],
|
|
|
|
|
["UPPER_KEBAB-CASE", "UPPER_KEBAB_CASE"],
|
|
|
|
|
["Sentencecase", "Sentencecase"],
|
|
|
|
|
["", "_"],
|
|
|
|
|
["with space", "with_space"],
|
|
|
|
|
["with multiple spaces", "with_multiple__spaces"],
|
|
|
|
|
["with%special)characters", "with_special_characters"],
|
|
|
|
|
["with%$multiple_spl.)characters", "with__multiple_spl__characters"],
|
|
|
|
|
["1startingWithNumber", "_1startingWithNumber"],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
inputAndExpectedOutput.forEach(([input, expectedOutput]) => {
|
|
|
|
|
const result = sanitizeKey(input);
|
|
|
|
|
expect(result).toEqual(expectedOutput);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("returns sanitized value when valid string with existing keys and reserved keys", () => {
|
|
|
|
|
const existingKeys = [
|
|
|
|
|
"__id",
|
|
|
|
|
"__restricted__",
|
|
|
|
|
"firstName1",
|
|
|
|
|
"_1age",
|
|
|
|
|
"gender",
|
|
|
|
|
"poll123",
|
|
|
|
|
"poll124",
|
|
|
|
|
"poll125",
|
|
|
|
|
"address_",
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const inputAndExpectedOutput = [
|
|
|
|
|
["lowercase", "lowercase"],
|
|
|
|
|
["__abc__", "__abc__"],
|
|
|
|
|
["lower_snake_case", "lower_snake_case"],
|
|
|
|
|
["UPPER_SNAKE_CASE", "UPPER_SNAKE_CASE"],
|
|
|
|
|
["PascalCase", "PascalCase"],
|
|
|
|
|
["camelCase", "camelCase"],
|
|
|
|
|
["lower-kebab-case", "lower_kebab_case"],
|
|
|
|
|
["UPPER_KEBAB-CASE", "UPPER_KEBAB_CASE"],
|
|
|
|
|
["Sentencecase", "Sentencecase"],
|
|
|
|
|
["", "_"],
|
|
|
|
|
["with space", "with_space"],
|
|
|
|
|
["with multiple spaces", "with_multiple__spaces"],
|
|
|
|
|
["with%special)characters", "with_special_characters"],
|
|
|
|
|
["with%$multiple_spl.)characters", "with__multiple_spl__characters"],
|
|
|
|
|
["1startingWithNumber", "_1startingWithNumber"],
|
|
|
|
|
["1startingWithNumber", "_1startingWithNumber"],
|
|
|
|
|
["firstName", "firstName"],
|
|
|
|
|
["firstName1", "firstName2"],
|
|
|
|
|
["1age", "_1age1"],
|
|
|
|
|
["address&", "address_1"],
|
|
|
|
|
["%&id", "__id1"],
|
|
|
|
|
["%&restricted*(", "__restricted__1"],
|
|
|
|
|
["poll130", "poll130"],
|
|
|
|
|
["poll124", "poll126"],
|
|
|
|
|
["हिन्दि", "xn__j2bd4cyac6f"],
|
|
|
|
|
["😃", "xn__h28h"],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
inputAndExpectedOutput.forEach(([input, expectedOutput]) => {
|
|
|
|
|
const result = sanitizeKey(input, {
|
|
|
|
|
existingKeys,
|
|
|
|
|
});
|
|
|
|
|
expect(result).toEqual(expectedOutput);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-05-04 09:45:57 +00:00
|
|
|
|
|
|
|
|
describe("Test widget utility functions", () => {
|
|
|
|
|
it("case: fontSizeUtility returns the font sizes based on variant", () => {
|
|
|
|
|
const expectedFontSize = "0.75rem";
|
|
|
|
|
|
|
|
|
|
expect(fontSizeUtility(TextSizes.PARAGRAPH2)).toEqual(expectedFontSize);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("case: borderRadiusUtility returns the borderRadius based on borderRadius variant", () => {
|
|
|
|
|
const expectedBorderRadius = "0.375rem";
|
|
|
|
|
expect(borderRadiusUtility(ButtonBorderRadiusTypes.ROUNDED)).toEqual(
|
|
|
|
|
expectedBorderRadius,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("case: replaceRgbaMigrationConstant returns the new boxShadow by replacing default boxShadowColor with new boxShadowColor", () => {
|
|
|
|
|
const boxShadow = "0px 0px 4px 3px rgba(0, 0, 0, 0.25)";
|
|
|
|
|
const boxShadowColor = "red";
|
|
|
|
|
const expectedBoxShadow = "0px 0px 4px 3px red";
|
|
|
|
|
expect(replaceRgbaMigrationConstant(boxShadow, boxShadowColor)).toEqual(
|
|
|
|
|
expectedBoxShadow,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("case: boxShadowUtility returns the new boxShadow", () => {
|
|
|
|
|
const variants = [
|
|
|
|
|
"VARIANT1",
|
|
|
|
|
"VARIANT2",
|
|
|
|
|
"VARIANT3",
|
|
|
|
|
"VARIANT4",
|
|
|
|
|
"VARIANT5",
|
|
|
|
|
];
|
|
|
|
|
let newBoxShadowColor = rgbaMigrationConstantV56;
|
|
|
|
|
let expectedBoxShadows = [
|
|
|
|
|
`0px 0px 4px 3px ${newBoxShadowColor}`,
|
|
|
|
|
`3px 3px 4px ${newBoxShadowColor}`,
|
|
|
|
|
`0px 1px 3px ${newBoxShadowColor}`,
|
|
|
|
|
`2px 2px 0px ${newBoxShadowColor}`,
|
|
|
|
|
`-2px -2px 0px ${newBoxShadowColor}`,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Check the boxShadow when the boxShadowColor is set to default;
|
|
|
|
|
variants.forEach((value: string, index: number) => {
|
|
|
|
|
expect(boxShadowUtility(value, newBoxShadowColor)).toEqual(
|
|
|
|
|
expectedBoxShadows[index],
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Check the boxShadow when the boxShadowColor is set to custom color;
|
|
|
|
|
newBoxShadowColor = "red";
|
|
|
|
|
expectedBoxShadows = [
|
|
|
|
|
`0px 0px 4px 3px ${newBoxShadowColor}`,
|
|
|
|
|
`3px 3px 4px ${newBoxShadowColor}`,
|
|
|
|
|
`0px 1px 3px ${newBoxShadowColor}`,
|
|
|
|
|
`2px 2px 0px ${newBoxShadowColor}`,
|
|
|
|
|
`-2px -2px 0px ${newBoxShadowColor}`,
|
|
|
|
|
];
|
|
|
|
|
variants.forEach((value: string, index: number) => {
|
|
|
|
|
expect(boxShadowUtility(value, newBoxShadowColor)).toEqual(
|
|
|
|
|
expectedBoxShadows[index],
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("case: boxShadowMigration returns correct boxShadow whenever boxShadow and boxShadowColor ar dynamic", () => {
|
|
|
|
|
/**
|
|
|
|
|
* Function usd inside table widget cell properties for Icon and menu button types.
|
|
|
|
|
* This function is used to run theming migration boxShadow and boxShadowColor has dynamic bindings
|
|
|
|
|
* Function runs for the following scenarios, when:
|
|
|
|
|
* 1. boxShadow: Static; boxShadowColor: Dynamic
|
|
|
|
|
* 2. boxShadow: Dynamic; boxShadowColor: Static
|
|
|
|
|
* 3. boxShadow: Dynamic; boxShadowColor: empty
|
|
|
|
|
* 4. boxShadow: Dynamic; boxShadowColor: dynamic
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Case 1:
|
|
|
|
|
expect(
|
|
|
|
|
boxShadowMigration(
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.dynamicBindingPathList as any,
|
|
|
|
|
"action",
|
|
|
|
|
"0px 0px 4px 3px rgba(0, 0, 0, 0.25)",
|
|
|
|
|
"red",
|
|
|
|
|
),
|
|
|
|
|
).toEqual("0px 0px 4px 3px red");
|
|
|
|
|
|
|
|
|
|
// Case 2 & 3:
|
|
|
|
|
// Make boxShadow dynamic
|
|
|
|
|
/**
|
|
|
|
|
* 1. Add the boxShadow to the DBPL
|
|
|
|
|
* 2. Remove boxShadowColor from the DBPL
|
|
|
|
|
* 3. Assign the action.boxShadowcolor as a static value.
|
|
|
|
|
* 4. Assign the action.boxShadowcolor as a empty value.
|
|
|
|
|
*/
|
|
|
|
|
tableWidgetProps.dynamicBindingPathList.push({
|
|
|
|
|
key: "primaryColumns.action.boxShadow",
|
|
|
|
|
});
|
|
|
|
|
// Remove boxShadowColor from dynamicBindingPathList
|
|
|
|
|
remove(
|
|
|
|
|
tableWidgetProps.dynamicBindingPathList,
|
|
|
|
|
(value: { key: string }) =>
|
|
|
|
|
value.key === "primaryColumns.action.boxShadowColor",
|
|
|
|
|
);
|
|
|
|
|
// Assign values to boxShadow and boxShadowColor
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow = "VARIANT1";
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor = "blue" as any;
|
|
|
|
|
let newBoxShadow = boxShadowMigration(
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.dynamicBindingPathList as any,
|
|
|
|
|
"action",
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow,
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor,
|
|
|
|
|
);
|
|
|
|
|
expect(newBoxShadow).toEqual("0px 0px 4px 3px blue");
|
|
|
|
|
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow = "VARIANT1";
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor = "" as any; // Add empty boxShadowColor.
|
|
|
|
|
|
|
|
|
|
newBoxShadow = boxShadowMigration(
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.dynamicBindingPathList as any,
|
|
|
|
|
"action",
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow,
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor,
|
|
|
|
|
);
|
|
|
|
|
expect(newBoxShadow).toEqual("0px 0px 4px 3px rgba(0, 0, 0, 0.25)");
|
|
|
|
|
|
|
|
|
|
// Case 4:
|
|
|
|
|
// Add boxShadow and boxShadowColor to the dynamicBindingPathList
|
|
|
|
|
tableWidgetProps.dynamicBindingPathList = [
|
|
|
|
|
...tableWidgetProps.dynamicBindingPathList,
|
|
|
|
|
{
|
|
|
|
|
key: "primaryColumns.action.boxShadow",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "primaryColumns.action.boxShadowColor",
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Assign values to boxShadow and boxShadowColor
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow = "VARIANT1";
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor = [
|
|
|
|
|
"orange",
|
|
|
|
|
"orange",
|
|
|
|
|
"orange",
|
|
|
|
|
];
|
|
|
|
|
newBoxShadow = boxShadowMigration(
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.dynamicBindingPathList as any,
|
|
|
|
|
"action",
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow,
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor[0],
|
|
|
|
|
);
|
|
|
|
|
expect(newBoxShadow).toEqual("0px 0px 4px 3px orange");
|
|
|
|
|
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow = "VARIANT1";
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor = ["", "", ""] as any; // Add empty boxShadowColor when dynamic
|
|
|
|
|
|
|
|
|
|
// Add empty boxShadowColor.
|
|
|
|
|
newBoxShadow = boxShadowMigration(
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-05-04 09:45:57 +00:00
|
|
|
tableWidgetProps.dynamicBindingPathList as any,
|
|
|
|
|
"action",
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadow,
|
|
|
|
|
tableWidgetProps.primaryColumns.action.boxShadowColor[0],
|
|
|
|
|
);
|
|
|
|
|
expect(newBoxShadow).toEqual("0px 0px 4px 3px rgba(0, 0, 0, 0.25)");
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-07-14 07:02:35 +00:00
|
|
|
|
|
|
|
|
type composePropertyUpdateHookInputType = Array<
|
|
|
|
|
(
|
|
|
|
|
props: unknown,
|
|
|
|
|
propertyPath: string,
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-07-14 07:02:35 +00:00
|
|
|
propertyValue: any,
|
2023-07-26 05:38:11 +00:00
|
|
|
) => PropertyUpdates[] | undefined
|
2022-07-14 07:02:35 +00:00
|
|
|
>;
|
|
|
|
|
describe("composePropertyUpdateHook", () => {
|
|
|
|
|
it("should test that it's returning a function", () => {
|
|
|
|
|
expect(typeof composePropertyUpdateHook([() => undefined])).toEqual(
|
|
|
|
|
"function",
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should test that calling the function concats the returned values of input functions in the given order", () => {
|
|
|
|
|
const input = [() => [1], () => [2], () => [3], () => [4]];
|
|
|
|
|
|
|
|
|
|
const expected = [1, 2, 3, 4];
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
composePropertyUpdateHook(
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
input as unknown as composePropertyUpdateHookInputType,
|
2022-07-14 07:02:35 +00:00
|
|
|
)(null, "", null),
|
|
|
|
|
).toEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should test that calling the function concats the returned values of input functions in the given order and ignores undefined", () => {
|
|
|
|
|
const input = [() => [1], () => undefined, () => [3], () => [4]];
|
|
|
|
|
|
|
|
|
|
const expected = [1, 3, 4];
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
composePropertyUpdateHook(
|
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
## Description
This PR upgrades Prettier to v2 + enforces TypeScript’s [`import
type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)
syntax where applicable. It’s submitted as a separate PR so we can merge
it easily.
As a part of this PR, we reformat the codebase heavily:
- add `import type` everywhere where it’s required, and
- re-format the code to account for Prettier 2’s breaking changes:
https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes
This PR is submitted against `release` to make sure all new code by team
members will adhere to new formatting standards, and we’ll have fewer
conflicts when merging `bundle-optimizations` into `release`. (I’ll
merge `release` back into `bundle-optimizations` once this PR is
merged.)
### Why is this needed?
This PR is needed because, for the Lodash optimization from
https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3,
we need to use `import type`. Otherwise, `babel-plugin-lodash` complains
that `LoDashStatic` is not a lodash function.
However, just using `import type` in the current codebase will give you
this:
<img width="962" alt="Screenshot 2023-03-08 at 17 45 59"
src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png">
That’s because Prettier 1 can’t parse `import type` at all. To parse it,
we need to upgrade to Prettier 2.
### Why enforce `import type`?
Apart from just enabling `import type` support, this PR enforces
specifying `import type` everywhere it’s needed. (Developers will get
immediate TypeScript and ESLint errors when they forget to do so.)
I’m doing this because I believe `import type` improves DX and makes
refactorings easier.
Let’s say you had a few imports like below. Can you tell which of these
imports will increase the bundle size? (Tip: it’s not all of them!)
```ts
// app/client/src/workers/Linting/utils.ts
import { Position } from "codemirror";
import { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
It’s pretty hard, right?
What about now?
```ts
// app/client/src/workers/Linting/utils.ts
import type { Position } from "codemirror";
import type { LintError as JSHintError, LintOptions } from "jshint";
import { get, isEmpty, isNumber, keys, last, set } from "lodash";
```
Now, it’s clear that only `lodash` will be bundled.
This helps developers to see which imports are problematic, but it
_also_ helps with refactorings. Now, if you want to see where
`codemirror` is bundled, you can just grep for `import \{.*\} from
"codemirror"` – and you won’t get any type-only imports.
This also helps (some) bundlers. Upon transpiling, TypeScript erases
type-only imports completely. In some environment (not ours), this makes
the bundle smaller, as the bundler doesn’t need to bundle type-only
imports anymore.
## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
This was tested to not break the build.
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
---------
Co-authored-by: Satish Gandham <hello@satishgandham.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
|
|
|
input as unknown as composePropertyUpdateHookInputType,
|
2022-07-14 07:02:35 +00:00
|
|
|
)(null, "", null),
|
|
|
|
|
).toEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should test that calling the function without any function returns undefined", () => {
|
2024-07-31 15:41:28 +00:00
|
|
|
// TODO: Fix this the next time the file is edited
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2022-07-14 07:02:35 +00:00
|
|
|
const input: any = [];
|
|
|
|
|
|
|
|
|
|
const expected = undefined;
|
|
|
|
|
|
|
|
|
|
expect(composePropertyUpdateHook(input)(null, "", null)).toEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-11-23 09:48:23 +00:00
|
|
|
|
|
|
|
|
const DUMMY_WIDGET: WidgetProps = {
|
|
|
|
|
bottomRow: 0,
|
|
|
|
|
isLoading: false,
|
|
|
|
|
leftColumn: 0,
|
|
|
|
|
parentColumnSpace: 0,
|
|
|
|
|
parentRowSpace: 0,
|
|
|
|
|
renderMode: RenderModes.CANVAS,
|
|
|
|
|
rightColumn: 0,
|
|
|
|
|
topRow: 0,
|
|
|
|
|
type: "SKELETON_WIDGET",
|
|
|
|
|
version: 2,
|
|
|
|
|
widgetId: "",
|
|
|
|
|
widgetName: "",
|
|
|
|
|
};
|
|
|
|
|
describe("Auto Height Utils", () => {
|
|
|
|
|
it("should return true if withLimits is true and widget has AUTO_HEIGHT_WITH_LIMITS", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 06:11:10 +00:00
|
|
|
const result = isAutoHeightEnabledForWidgetWithLimits(props);
|
2022-11-23 09:48:23 +00:00
|
|
|
expect(result).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
it("should return false if withLimits is true and widget has AUTO_HEIGHT", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT",
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 06:11:10 +00:00
|
|
|
const result = isAutoHeightEnabledForWidgetWithLimits(props);
|
2022-11-23 09:48:23 +00:00
|
|
|
expect(result).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
it("should return true if withLimits is false and widget has AUTO_HEIGHT", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT",
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 06:11:10 +00:00
|
|
|
const result = isAutoHeightEnabledForWidget(props);
|
2022-11-23 09:48:23 +00:00
|
|
|
expect(result).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should return false withLimits is false and widget has FIXED", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "FIXED",
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 06:11:10 +00:00
|
|
|
const result = isAutoHeightEnabledForWidget(props);
|
2022-11-23 09:48:23 +00:00
|
|
|
expect(result).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
it("should return false withLimits is true and widget has FIXED", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "FIXED",
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 06:11:10 +00:00
|
|
|
const result = isAutoHeightEnabledForWidgetWithLimits(props);
|
2022-11-23 09:48:23 +00:00
|
|
|
expect(result).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
it("should return 9000 if widget has AUTO_HEIGHT", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT",
|
|
|
|
|
maxDynamicHeight: 20,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMaxAutoHeight(props);
|
|
|
|
|
expect(result).toBe(WidgetHeightLimits.MAX_HEIGHT_IN_ROWS);
|
|
|
|
|
});
|
|
|
|
|
it("should return 20 if widget has AUTO_HEIGHT_WITH_LIMITS", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
maxDynamicHeight: 20,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMaxAutoHeight(props);
|
|
|
|
|
expect(result).toBe(20);
|
|
|
|
|
});
|
|
|
|
|
it("should return 9000 if widget has AUTO_HEIGHT_WITH_LIMITS and maxDynamicHeight is undefined", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
maxDynamicHeight: undefined,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMaxAutoHeight(props);
|
|
|
|
|
expect(result).toBe(WidgetHeightLimits.MAX_HEIGHT_IN_ROWS);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("should return undefined if widget is FIXED ", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "FIXED",
|
|
|
|
|
maxDynamicHeight: undefined,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMaxAutoHeight(props);
|
|
|
|
|
expect(result).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
it("should return 20 if widget has AUTO_HEIGHT and props has 20", () => {
|
2022-11-23 09:48:23 +00:00
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT",
|
|
|
|
|
minDynamicHeight: 20,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMinAutoHeight(props);
|
2022-11-27 17:12:00 +00:00
|
|
|
expect(result).toBe(20);
|
2022-11-23 09:48:23 +00:00
|
|
|
});
|
|
|
|
|
it("should return 20 if widget has AUTO_HEIGHT_WITH_LIMITS", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
minDynamicHeight: 20,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMinAutoHeight(props);
|
|
|
|
|
expect(result).toBe(20);
|
|
|
|
|
});
|
|
|
|
|
it("should return 4 if widget has AUTO_HEIGHT_WITH_LIMITS and minDynamicHeight is undefined", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
minDynamicHeight: undefined,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMinAutoHeight(props);
|
|
|
|
|
expect(result).toBe(WidgetHeightLimits.MIN_HEIGHT_IN_ROWS);
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-27 17:12:00 +00:00
|
|
|
it("should return undefined if widget is FIXED ", () => {
|
2022-11-23 09:48:23 +00:00
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "FIXED",
|
|
|
|
|
minDynamicHeight: undefined,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const result = getWidgetMinAutoHeight(props);
|
|
|
|
|
expect(result).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("Should Update Widget Height Automatically?", () => {
|
|
|
|
|
it("Multiple scenario tests", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
minDynamicHeight: 19,
|
|
|
|
|
maxDynamicHeight: 40,
|
|
|
|
|
topRow: 20,
|
|
|
|
|
bottomRow: 40,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const inputs = [
|
|
|
|
|
600, // Is beyond max height of 40 rows,
|
|
|
|
|
560, // Is beyond max height of 40 rows
|
|
|
|
|
220, // Is within 20 and 40 rows limits
|
|
|
|
|
180, // Is below the min of 20 rows
|
|
|
|
|
200, // Is the same as current height
|
|
|
|
|
190, // Is exactly min value
|
|
|
|
|
400, // Is exactly max value
|
|
|
|
|
0, // Is below the min possible value
|
|
|
|
|
100, // Is below the min possible value
|
|
|
|
|
];
|
|
|
|
|
const expected = [
|
|
|
|
|
true, // because currentHeight is not close to maxDynamicHeight
|
|
|
|
|
true, // because currentheight is not close to maxDynamicHeight
|
|
|
|
|
true,
|
|
|
|
|
true, // because we need to go as low as possible (minDynamicHeight)
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
true, // because we need to go as low as possible (minDynamicHeight)
|
|
|
|
|
true, // because we need to go as low as possible (minDynamicHeight)
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
inputs.forEach((input, index) => {
|
|
|
|
|
const result = shouldUpdateWidgetHeightAutomatically(input, props);
|
|
|
|
|
expect(result).toStrictEqual(expected[index]);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
it("When height is below min rows, should update, no matter the expectations", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
minDynamicHeight: 19,
|
|
|
|
|
maxDynamicHeight: 40,
|
|
|
|
|
topRow: 20,
|
|
|
|
|
bottomRow: 25,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const input = 0;
|
|
|
|
|
const expected = true;
|
|
|
|
|
|
|
|
|
|
const result = shouldUpdateWidgetHeightAutomatically(input, props);
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
});
|
|
|
|
|
it("When height is above max rows, should update, no matter the expectations", () => {
|
|
|
|
|
const props = {
|
|
|
|
|
...DUMMY_WIDGET,
|
|
|
|
|
dynamicHeight: "AUTO_HEIGHT_WITH_LIMITS",
|
|
|
|
|
minDynamicHeight: 19,
|
|
|
|
|
maxDynamicHeight: 40,
|
|
|
|
|
topRow: 20,
|
|
|
|
|
bottomRow: 65,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const input = 0;
|
|
|
|
|
const expected = true;
|
|
|
|
|
|
|
|
|
|
const result = shouldUpdateWidgetHeightAutomatically(input, props);
|
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
|
|
|
});
|
2023-10-13 09:08:01 +00:00
|
|
|
it("should return correct value for isCompactMode", () => {
|
|
|
|
|
const compactHeight = 40;
|
|
|
|
|
const unCompactHeight = 41;
|
|
|
|
|
expect(isCompactMode(compactHeight)).toBeTruthy();
|
|
|
|
|
expect(isCompactMode(unCompactHeight)).toBeFalsy();
|
|
|
|
|
});
|
2022-11-23 09:48:23 +00:00
|
|
|
});
|