From cb597f47d92f868e775ce5c6729042df286a2de9 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Mon, 11 Nov 2024 18:17:08 +0300 Subject: [PATCH 01/26] chore: update tabs paddings --- .../src/components/editorComponents/EntityBottomTabs.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/client/src/components/editorComponents/EntityBottomTabs.tsx b/app/client/src/components/editorComponents/EntityBottomTabs.tsx index e649ba41d1a..01f8eeb5da6 100644 --- a/app/client/src/components/editorComponents/EntityBottomTabs.tsx +++ b/app/client/src/components/editorComponents/EntityBottomTabs.tsx @@ -24,8 +24,10 @@ const TabPanelWrapper = styled(TabPanel)` `; const TabsListWrapper = styled(TabsList)` - padding: calc(var(--ads-v2-spaces-1) + 2px) var(--ads-v2-spaces-7) - var(--ads-v2-spaces-1); + && { + padding: var(--ads-v2-spaces-2); + padding-bottom: var(--ads-v2-spaces-1); + } `; export interface BottomTab { From d28b53195403fc4076081dce1858a24463834ebd Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Mon, 11 Nov 2024 18:18:14 +0300 Subject: [PATCH 02/26] chore: update button text --- .../PluginActionResponse/components/BindDataButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx index 56271b6f31d..4f8f0771fe6 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx @@ -380,7 +380,7 @@ function BindDataButton(props: BindDataButtonProps) { size="sm" startIcon="binding-new" > - Bind Data + Display on UI Date: Tue, 12 Nov 2024 22:25:26 +0300 Subject: [PATCH 03/26] feat: add response type selector icons --- .../ads/src/Icon/Icon.provider.tsx | 351 +++++++++--------- .../icons/ads/content-type-json.svg | 3 + .../__assets__/icons/ads/content-type-raw.svg | 3 + .../icons/ads/content-type-table.svg | 3 + 4 files changed, 192 insertions(+), 168 deletions(-) create mode 100644 app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-json.svg create mode 100644 app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-raw.svg create mode 100644 app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-table.svg diff --git a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx index b4154a27d2d..5a5ff05eb1e 100644 --- a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx +++ b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx @@ -1072,6 +1072,18 @@ const InputCursorMoveIcon = importSvg( async () => import("../__assets__/icons/ads/input-cursor-move.svg"), ); +const ContentTypeTable = importSvg( + async () => import("../__assets__/icons/ads/content-type-table.svg"), +); + +const ContentTypeJson = importSvg( + async () => import("../__assets__/icons/ads/content-type-json.svg"), +); + +const ContentTypeRaw = importSvg( + async () => import("../__assets__/icons/ads/content-type-raw.svg"), +); + import PlayIconPNG from "../__assets__/icons/control/play-icon.png"; function PlayIconPNGWrapper() { @@ -1085,134 +1097,168 @@ function PlayIconPNGWrapper() { } const ICON_LOOKUP = { - "delete-control": DeleteIcon, - "move-control": MoveIcon, - "edit-control": EditIcon, - "view-control": ViewIcon, - "more-vertical-control": MoreVerticalIcon, - "more-horizontal-control": OverflowMenuIcon, - "js-toggle": JsToggleIcon, - "increase-control": IncreaseIcon, - "decrease-control": DecreaseIcon, - "draggable-control": DraggableIcon, - "drag-handle": DragHandleIcon, - "close-control": CloseIcon, - "close-circle-control": CloseCircleIcon, - "add-circle-control": AddCircleIcon, - "pick-my-location-selected-control": PickMyLocationSelectedIcon, - "settings-control": SettingsIcon, - "help-control": HelpIcon, - "play-video": PlayIconPNGWrapper, - "remove-control": RemoveIcon, - "drag-control": DragIcon, - "collapse-control": CollapseIcon, - "sort-control": SortIcon, - "edit-white": EditWhiteIcon, - "launch-control": LaunchIcon, - "back-control": BackIcon, - "show-column": EyeIcon, - "hide-column": EyeOffIcon, - "delete-column": DeleteColumnIcon, - "bold-font": BoldFontIcon, - underline: UnderlineIcon, - "italics-font": ItalicsFontIcon, - "center-align": CenterAlignIcon, - "left-align": LeftAlignIcon, - "right-align": RightAlignIcon, - "vertical-right": VerticalAlignRight, - "vertical-left": VerticalAlignLeft, - "vertical-top": VerticalAlignTop, - "vertical-bottom": VerticalAlignBottom, - "vertical-center": VerticalAlignCenter, - "copy-control": CopyIcon, - "copy2-control": Copy2Icon, - "cut-control": CutIcon, - "group-control": GroupIcon, - bullets: BulletsIcon, - "divider-cap-right": DividerCapRightIcon, - "divider-cap-left": DividerCapLeftIcon, - "divider-cap-all": DividerCapAllIcon, - "bind-data-control": TrendingFlat, - "icon-align-left": AlignLeftIcon, - "icon-align-right": AlignRightIcon, - "border-radius-sharp": BorderRadiusSharpIcon, - "border-radius-rounded": BorderRadiusRoundedIcon, - "border-radius-circle": BorderRadiusCircleIcon, - "box-shadow-none": BoxShadowNoneIcon, - "box-shadow-variant1": BoxShadowVariant1Icon, - "box-shadow-variant2": BoxShadowVariant2Icon, - "box-shadow-variant3": BoxShadowVariant3Icon, - "box-shadow-variant4": BoxShadowVariant4Icon, - "box-shadow-variant5": BoxShadowVariant5Icon, - "increase-control-v2": IncreaseV2Icon, - question: QuestionIcon, - "column-unfreeze": SubtractIcon, - "heading-one": HeadingOneIcon, - "heading-two": HeadingTwoIcon, - "heading-three": HeadingThreeIcon, - "gift-line": GiftLineIcon, - paragraph: ParagraphIcon, - "paragraph-two": ParagraphTwoIcon, + "account-box-line": AccountBoxLineIcon, "add-box-line": AddBoxLineIcon, + "add-circle-control": AddCircleIcon, + "add-line": AddLineIcon, "add-more": AddMoreIcon, "add-more-fill": AddMoreFillIcon, - "alert-line": AlertLineIcon, "alert-fill": AlertFillIcon, - "info-fill": InfoFillIcon, + "alert-line": AlertLineIcon, + "align-center": AlignCenter, + "align-left": AlignLeft, + "align-right": AlignRight, + "apps-line": AppsLineIcon, "arrow-down-s-fill": ArrowDownSFillIcon, + "arrow-down-s-line": ArrowDownSLineIcon, "arrow-forward": ArrowForwardIcon, "arrow-go-back": ArrowGoBackLineIcon, "arrow-left": ArrowLeft, + "arrow-left-line": ArrowLeftLineIcon, + "arrow-left-s-line": ArrowLeftSLineIcon, + "arrow-right-line": ArrowRightLineIcon, "arrow-right-s-fill": ArrowRightSFillIcon, + "arrow-right-s-line": ArrowRightSLineIcon, "arrow-right-up-line": ArrowRightUpLineIcon, "arrow-up-line": ArrowUpLineIcon, + "arrow-up-s-line": ArrowUpSLineIcon, + "back-control": BackIcon, + "bill-line": BillLineIcon, + "bind-data-control": TrendingFlat, + "binding-new": BindingIcon, + "bold-font": BoldFontIcon, "book-line": BookLineIcon, + "border-radius-circle": BorderRadiusCircleIcon, + "border-radius-rounded": BorderRadiusRoundedIcon, + "border-radius-sharp": BorderRadiusSharpIcon, + "box-3-line": Box3LineIcon, + "box-shadow-none": BoxShadowNoneIcon, + "box-shadow-variant1": BoxShadowVariant1Icon, + "box-shadow-variant2": BoxShadowVariant2Icon, + "box-shadow-variant3": BoxShadowVariant3Icon, + "box-shadow-variant4": BoxShadowVariant4Icon, + "box-shadow-variant5": BoxShadowVariant5Icon, + "braces-line": BracesLineIcon, "bug-line": BugLineIcon, "cap-dot": CapDotIcon, "cap-solid": CapSolidIcon, "card-context-menu": CardContextMenu, + "center-align": CenterAlignIcon, "chat-help": ChatIcon, + "chat-upload-line": ChatUploadLineIcon, "check-line": CheckLineIcon, "chevron-left": ChevronLeft, "chevron-right": ChevronRight, "close-circle": CloseCircleIcon, + "close-circle-control": CloseCircleIcon, + "close-circle-line": CloseCircleLineIcon, + "close-control": CloseIcon, + "close-line": CloseIcon, "close-modal": CloseLineIcon, "close-x": CloseLineIcon, "cloud-off-line": CloudOfflineIcon, + "collapse-control": CollapseIcon, + "column-freeze": ColumnFreeze, + "column-unfreeze": SubtractIcon, "comment-context-menu": CommentContextMenu, "compasses-line": CompassesLine, + "content-type-table": ContentTypeTable, + "content-type-json": ContentTypeJson, + "content-type-raw": ContentTypeRaw, "context-menu": ContextMenuIcon, + "contract-left-line": ContractLeft, + "contract-right-line": ContractRight, + "copy-control": CopyIcon, + "copy2-control": Copy2Icon, + "cut-control": CutIcon, + "dashboard-line": DashboardLineIcon, "database-2-line": Database2Line, + "datasource-v3": DatasourceV3Icon, + "datasources-2": Datasources2, + "decrease-control": DecreaseIcon, + "delete-bin-line": DeleteBinLineIcon, "delete-blank": DeleteBin7, + "delete-column": DeleteColumnIcon, + "delete-control": DeleteIcon, "delete-row": DeleteRowIcon, - "double-arrow-right": DoubleArrowRightIcon, + "divider-cap-all": DividerCapAllIcon, + "divider-cap-left": DividerCapLeftIcon, + "divider-cap-right": DividerCapRightIcon, "double-arrow-left": DoubleArrowLeftIcon, + "double-arrow-right": DoubleArrowRightIcon, "down-arrow": DownArrowIcon, "down-arrow-2": ArrowDownLineIcon, "download-line": DownloadLineIcon, + "drag-control": DragIcon, + "drag-handle": DragHandleIcon, + "draggable-control": DraggableIcon, + "edit-2-line": Edit2LineIcon, "edit-box-line": EditBoxLineIcon, + "edit-control": EditIcon, "edit-line": EditLineIcon, - "edit-2-line": Edit2LineIcon, "edit-underline": EditUnderlineIcon, + "edit-white": EditWhiteIcon, + "editor-v3": EditorV3Icon, + "enter-line": CornerDownLeftLineIcon, "expand-less": ExpandLess, "expand-more": ExpandMore, + "external-link-line": ExternalLinkIcon, "eye-off": EyeOff, "eye-on": EyeOn, + "file-add-line": FileAddLineIcon, + "file-copy-2-line": FileCopy2Line, "file-line": FileLine, "file-list-2-line": FileList2LineIcon, "file-list-line": FileListLineIcon, + "file-paper-2-line": FilePaper2LineIcon, "file-transfer": FileTransfer, - "fork-2": Fork2Icon, + "folder-download-line": FolderDownloadLineIcon, + "folder-line": FolderLineIcon, + "folder-reduce-line": FolderReduceLineIcon, "forbid-line": ForbidLineIcon, + "fork-2": Fork2Icon, + "gift-line": GiftLineIcon, "git-branch": GitBranchLineIcon, "git-commit": GitCommit, "git-pull-request": GitPullRequest, "git-repository": GitRepository, + "github-fill": GithubFillIcon, "global-line": GlobalLineIcon, + "google-colored": GoogleColoredIcon, + "google-fill": GoogleFillIcon, "group-2-line": Group2LineIcon, + "group-control": GroupIcon, "group-line": GroupLineIcon, + "h-line": HLineIcon, + "heading-one": HeadingOneIcon, + "heading-three": HeadingThreeIcon, + "heading-two": HeadingTwoIcon, + "help-control": HelpIcon, + "hide-column": EyeOffIcon, + "home-3-line": Home3LineIcon, + "icon-align-left": AlignLeftIcon, + "icon-align-right": AlignRightIcon, + "increase-control": IncreaseIcon, + "increase-control-v2": IncreaseV2Icon, + "info-fill": InfoFillIcon, + "input-cursor-move": InputCursorMoveIcon, "invite-user": InviteUserIcon, + "italics-font": ItalicsFontIcon, + "js-file": JSFile, + "js-function": JSFunction, + "js-icon-v2": JSIconV2, + "js-square-v3": JsSquareV3Icon, + "js-toggle": JsToggleIcon, + "js-toggle-v2": JsToggleV2, + "js-toggle-v2-bold": JsToggleV2Bold, + "js-yellow": JSYellowIcon, "key-2-line": Key2LineIcon, + "launch-control": LaunchIcon, + "layout-2-line": Layout2LineIcon, + "layout-5-line": Layout5LineIcon, + "layout-column-line": LayoutColumnLineIcon, + "layout-left-2-line": LayoutLeft2LineIcon, + "left-align": LeftAlignIcon, "left-arrow-2": LeftArrowIcon2, "lightbulb-flash-line": LightbulbFlashLine, "line-dashed": LineDashedIcon, @@ -1220,45 +1266,88 @@ const ICON_LOOKUP = { "link-2": Link2, "link-unlink": LinkUnlinkIcon, "links-line": LinksLineIcon, - "external-link-line": ExternalLinkIcon, + "loader-line": LoaderLineIcon, "lock-2-line": Lock2LineIcon, + "lock-fill": LockFillIcon, "lock-password-line": LockPasswordLineIcon, "lock-unlock-line": LockUnlockLineIcon, - "lock-fill": LockFillIcon, "magic-line": MagicLineIcon, "mail-check-line": MailCheckLineIcon, "mail-line": MailLineIcon, + "map-2-line": Map2LineIcon, "map-pin-2-line": MapPin2LineIcon, + "map-pin-5-line": MapPin5LineIcon, + "map-pin-user-line": MapPinUserLineIcon, + "maximize-v3": MaximizeV3Icon, + "menu-fold": MenuFoldLineIcon, + "menu-unfold": MenuUnfoldLineIcon, + "message-2-line": Message2LineIcon, + "minimize-v3": MinimizeV3Icon, + "money-dollar-circle-line": MoneyDollarCircleLineIcon, "more-2-fill": More2FillIcon, + "more-horizontal-control": OverflowMenuIcon, + "more-vertical-control": MoreVerticalIcon, + "move-control": MoveIcon, "news-paper": NewsPaperLine, + "no-action": ForbidTwoLineIcon, "no-response": NoResponseIcon, "oval-check": OvalCheck, "oval-check-fill": OvalCheckFill, + "packages-v3": PackagesV3Icon, + "page-line": PagesLineIcon, + "paragraph-two": ParagraphTwoIcon, "pencil-fill-icon": PencilFillIcon, + "pencil-line": PencilLineIcon, + "pick-my-location-selected-control": PickMyLocationSelectedIcon, "pin-3": Pin3, "play-circle-line": PlayCircleLineIcon, + "play-line": PlayLineIcon, + "play-video": PlayIconPNGWrapper, + "queries-line": QueriesLineIcon, + "queries-v3": QueriesV3Icon, + "query-main": QueryMain, "question-fill": QuestionFillIcon, "question-line": QuestionLineIcon, "question-mark": QuestionMarkIcon, "reaction-2": Reaction2, "read-pin": ReadPin, + "remove-control": RemoveIcon, + "restart-line": RestartLineIcon, + "right-align": RightAlignIcon, "right-arrow": RightArrowIcon, "right-arrow-2": RightArrowIcon2, "search-eye-line": SearchEyeLineIcon, + "search-line": SearchLineIcon, "send-button": SendButton, + "server-line": ServerLineIcon, "settings-2-line": Settings2LineIcon, + "settings-control": SettingsIcon, "settings-line": SettingsLineIcon, + "settings-v3": SettingsV3Icon, "share-2": ShareIcon2, "share-box": ShareBoxFillIcon, "share-box-line": ShareBoxLineIcon, "share-line": ShareLineIcon, + "show-column": EyeIcon, + "show-modal": ShowModalIcon, + "sip-line": SipLineIcon, + "skip-left-line": SkipLeftLineIcon, + "skip-right-line": SkipRightLineIcon, "sort-asc": SortAscIcon, + "sort-control": SortIcon, "sort-desc": SortDescIcon, "star-fill": StarFillIcon, "star-line": StarLineIcon, "subtract-line": SubtractLine, "swap-horizontal": ArrowLeftRightIcon, + "text-bold": BoldIcon, + "text-italic": ItalicIcon, + "text-underline": UnderLineIcon, + "thumb-down-line": ThumbDownLineIcon, + "thumb-up-line": ThumbUpLineIcon, "timer-2-line": Timer2LineIcon, + "timer-flash-line": TimerFlashLineIcon, + "timer-line": TimerLineIcon, "trash-outline": TrashOutline, "trending-flat": TrendingFlat, "unread-pin": UnreadPin, @@ -1274,104 +1363,27 @@ const ICON_LOOKUP = { "user-settings-line": UserSettingsLineIcon, "user-shared-line": UserSharedLineIcon, "user-unfollow-line": UserUnfollowLineIcon, - "view-all": RightArrowIcon, - "view-less": LeftArrowIcon, - "warning-line": WarningLineIcon, - "warning-triangle": WarningTriangleIcon, - "money-dollar-circle-line": MoneyDollarCircleLineIcon, - "js-toggle-v2": JsToggleV2, - "js-toggle-v2-bold": JsToggleV2Bold, - "query-main": QueryMain, - "js-icon-v2": JSIconV2, - "js-file": JSFile, - "js-function": JSFunction, - "datasources-2": Datasources2, - "arrow-left-line": ArrowLeftLineIcon, - "arrow-right-line": ArrowRightLineIcon, - "close-line": CloseIcon, - "close-circle-line": CloseCircleLineIcon, - "arrow-left-s-line": ArrowLeftSLineIcon, - "arrow-right-s-line": ArrowRightSLineIcon, - "arrow-up-s-line": ArrowUpSLineIcon, - "arrow-down-s-line": ArrowDownSLineIcon, - "account-box-line": AccountBoxLineIcon, - "add-line": AddLineIcon, - "search-line": SearchLineIcon, - "loader-line": LoaderLineIcon, - "delete-bin-line": DeleteBinLineIcon, - "align-center": AlignCenter, - "align-left": AlignLeft, - "align-right": AlignRight, - "column-freeze": ColumnFreeze, "vertical-align-bottom": VerticalBottom, "vertical-align-middle": VerticalMiddle, "vertical-align-top": VerticalTop, - "skip-right-line": SkipRightLineIcon, - "skip-left-line": SkipLeftLineIcon, - "contract-left-line": ContractLeft, - "contract-right-line": ContractRight, + "vertical-bottom": VerticalAlignBottom, + "vertical-center": VerticalAlignCenter, + "vertical-left": VerticalAlignLeft, + "vertical-right": VerticalAlignRight, + "vertical-top": VerticalAlignTop, + "view-all": RightArrowIcon, + "view-control": ViewIcon, + "view-less": LeftArrowIcon, "w-line": WLineIcon, - "h-line": HLineIcon, - "file-add-line": FileAddLineIcon, - "layout-2-line": Layout2LineIcon, - "page-line": PagesLineIcon, - "pencil-line": PencilLineIcon, - "server-line": ServerLineIcon, - "layout-column-line": LayoutColumnLineIcon, - "layout-left-2-line": LayoutLeft2LineIcon, - "text-bold": BoldIcon, - "text-italic": ItalicIcon, - "text-underline": UnderLineIcon, - "sip-line": SipLineIcon, - "no-action": ForbidTwoLineIcon, - "message-2-line": Message2LineIcon, - "folder-download-line": FolderDownloadLineIcon, - "restart-line": RestartLineIcon, - "folder-reduce-line": FolderReduceLineIcon, - "timer-flash-line": TimerFlashLineIcon, - "timer-line": TimerLineIcon, - "map-2-line": Map2LineIcon, - "map-pin-user-line": MapPinUserLineIcon, - "map-pin-5-line": MapPin5LineIcon, - "chat-upload-line": ChatUploadLineIcon, - "home-3-line": Home3LineIcon, - "show-modal": ShowModalIcon, - "folder-line": FolderLineIcon, - "google-colored": GoogleColoredIcon, - "google-fill": GoogleFillIcon, - "github-fill": GithubFillIcon, - "enter-line": CornerDownLeftLineIcon, - "play-line": PlayLineIcon, - "thumb-up-line": ThumbUpLineIcon, - "thumb-down-line": ThumbDownLineIcon, - "menu-fold": MenuFoldLineIcon, - "menu-unfold": MenuUnfoldLineIcon, - "layout-5-line": Layout5LineIcon, - "js-yellow": JSYellowIcon, - "binding-new": BindingIcon, - "bill-line": BillLineIcon, - "file-paper-2-line": FilePaper2LineIcon, - "file-copy-2-line": FileCopy2Line, - "box-3-line": Box3LineIcon, - "apps-line": AppsLineIcon, - "queries-line": QueriesLineIcon, - "braces-line": BracesLineIcon, - "dashboard-line": DashboardLineIcon, - "js-square-v3": JsSquareV3Icon, - "queries-v3": QueriesV3Icon, + "warning-line": WarningLineIcon, + "warning-triangle": WarningTriangleIcon, "widgets-v3": WidgetsV3Icon, - "datasource-v3": DatasourceV3Icon, - "editor-v3": EditorV3Icon, - "settings-v3": SettingsV3Icon, - "packages-v3": PackagesV3Icon, - "minimize-v3": MinimizeV3Icon, - "maximize-v3": MaximizeV3Icon, "workflows-mono": WorkflowsMonochromeIcon, - "input-cursor-move": InputCursorMoveIcon, billing: BillingIcon, binding: Binding, book: BookIcon, bug: BugIcon, + bullets: BulletsIcon, cancel: CancelIcon, chat: Chat, close: CloseIcon, @@ -1402,9 +1414,9 @@ const ICON_LOOKUP = { general: GeneralIcon, grid: GridLineIcon, guide: GuideIcon, - history: HistoryLineIcon, hamburger: HamburgerIcon, help: HelpIcon, + history: HistoryLineIcon, info: InfoIcon, js: JsIcon, key: KeyIcon, @@ -1418,14 +1430,17 @@ const ICON_LOOKUP = { member: UserHeartLineIcon, minimize: MinimizeIcon, minus: RemoveIcon, - module: ModuleIcon, mobile: MobileIcon, + module: ModuleIcon, open: OpenIcon, + package: PackageIcon, pantone: PantoneLineIcon, + paragraph: ParagraphIcon, pin: Pin, play: PlayIcon, plus: CreateNewIcon, query: QueryIcon, + question: QuestionIcon, reaction: Reaction, refresh: RefreshLineIcon, rocket: RocketIcon, @@ -1433,8 +1448,9 @@ const ICON_LOOKUP = { search: SearchIcon, setting: SettingIcon, share: ShareForwardIcon, - shine: ShineIcon, shield: Shield, + shine: ShineIcon, + slash: SlashIcon, snippet: Snippet, success: SuccessIcon, support: SupportIcon, @@ -1442,6 +1458,7 @@ const ICON_LOOKUP = { tablet: TabletIcon, tabletLandscape: TabletLandscapeIcon, trash: Trash, + underline: UnderlineIcon, unpin: Unpin, upArrow: UpArrow, upgrade: DvdLineIcon, @@ -1452,8 +1469,6 @@ const ICON_LOOKUP = { widget: WidgetIcon, workflows: WorkflowsIcon, workspace: WorkspaceIcon, - package: PackageIcon, - slash: SlashIcon, }; export const IconCollection = Object.keys(ICON_LOOKUP); diff --git a/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-json.svg b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-json.svg new file mode 100644 index 00000000000..0d49b1320d3 --- /dev/null +++ b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-json.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-raw.svg b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-raw.svg new file mode 100644 index 00000000000..a7c77f9dacd --- /dev/null +++ b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-raw.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-table.svg b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-table.svg new file mode 100644 index 00000000000..601db25e8a6 --- /dev/null +++ b/app/client/packages/design-system/ads/src/__assets__/icons/ads/content-type-table.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file From 94d376d0b1fa341eac45aeadb9b276f4b6c874aa Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Tue, 12 Nov 2024 23:52:27 +0300 Subject: [PATCH 04/26] feat: change selector to menu & update spacing/layout --- app/client/src/IDE/Components/BottomView.tsx | 2 +- .../QueryResponseTab.tsx | 354 ++++++++++++------ .../components/QueryResponseTab/index.ts | 1 + .../components/QueryResponseTab/styles.ts | 66 ++++ .../Editor/QueryEditor/QueryDebuggerTabs.tsx | 53 --- 5 files changed, 300 insertions(+), 176 deletions(-) rename app/client/src/PluginActionEditor/components/PluginActionResponse/components/{ => QueryResponseTab}/QueryResponseTab.tsx (58%) create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/index.ts create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts diff --git a/app/client/src/IDE/Components/BottomView.tsx b/app/client/src/IDE/Components/BottomView.tsx index 1c8b8f87019..5fb01de1d8a 100644 --- a/app/client/src/IDE/Components/BottomView.tsx +++ b/app/client/src/IDE/Components/BottomView.tsx @@ -69,7 +69,7 @@ interface Props { const ViewHideButton = styled(Button)` &.view-hide-button { position: absolute; - top: 3px; + top: 2px; right: 0; padding: 9px 11px; } diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx similarity index 58% rename from app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab.tsx rename to app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index e5880bd5032..ef6e3831cb4 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from "react"; +import React, { useCallback, useRef, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import ReactJson from "react-json-view"; import { @@ -6,20 +6,26 @@ import { ResponseTabErrorContainer, ResponseTabErrorContent, ResponseTabErrorDefaultMessage, -} from "./ApiResponse"; -import { ResponseFormatTabs } from "./ResponseFormatTabs"; -import { NoResponse } from "./NoResponse"; +} from "../ApiResponse"; +import { ResponseFormatTabs } from "../ResponseFormatTabs"; +import { NoResponse } from "../NoResponse"; import LogAdditionalInfo from "components/editorComponents/Debugger/ErrorLogs/components/LogAdditionalInfo"; import LogHelper from "components/editorComponents/Debugger/ErrorLogs/components/LogHelper"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; import { JsonWrapper } from "components/editorComponents/Debugger/ErrorLogs/components/LogCollapseData"; import { Callout, - Flex, - SegmentedControl, + Menu, + MenuContent, + MenuGroup, + MenuGroupName, + MenuItem, + MenuTrigger, + Text, + Tooltip, type CalloutLinkProps, } from "@appsmith/ads"; -import styled from "styled-components"; + import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/constants"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { setActionResponseDisplayFormat } from "actions/pluginActionActions"; @@ -32,12 +38,12 @@ import { getErrorAsString } from "sagas/ActionExecution/errorUtils"; import { isString } from "lodash"; import ActionExecutionInProgressView from "components/editorComponents/ActionExecutionInProgressView"; import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; -import BindDataButton from "./BindDataButton"; +import BindDataButton from "../BindDataButton"; import { getPluginActionDebuggerState, openPluginActionSettings, setPluginActionEditorSelectedTab, -} from "../../../store"; +} from "../../../../store"; import { createMessage, PREPARED_STATEMENT_WARNING, @@ -46,29 +52,8 @@ import { EDITOR_TABS } from "constants/QueryEditorConstants"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -const HelpSection = styled.div``; - -export const ResponseDataContainer = styled.div` - padding: 0 var(--ads-v2-spaces-7); - padding-top: var(--ads-v2-spaces-4); - display: flex; - flex-direction: column; - gap: var(--ads-v2-spaces-4); - overflow-y: clip; - overflow-x: scroll; -`; - -const ResponseContentWrapper = styled.div<{ isError: boolean }>` - overflow-y: clip; - display: grid; - height: ${(props) => (props.isError ? "" : "100%")}; - - ${HelpSection} { - margin-bottom: 10px; - } - - position: relative; -`; +import * as Styled from "./styles"; +import { useBoolean, useEventCallback, useHover } from "usehooks-ts"; interface Props { actionSource: SourceEntity; @@ -80,7 +65,23 @@ interface Props { actionName: string; } -const QueryResponseTab = (props: Props) => { +// // Move bind data button to the new header component & change its title in the process. (design) +// // Add query name .run as prefix for the header row. This uses code variant of ads text component. (design) +// // Move number of records to the new header component. +// // * Remove paddings in tabs +// // * Acquire query duration & HTTP status and add request execution time to redux. +// // * On hover of query name and number of records, meta data of api run (outlined above) should show up as tooltip. (design) +// // * Change result type from segmented control to a FAB with dropdown menu. +// // * Change loading state button/spinner/spacing. (design) +// * Change the empty state text and button alignment. (design) +// * Update table appearance. +// * Table columns have a fixed width of 170px now, this needs to be updated to min-width. +// * Fix Cypress tests related to result type control change. + +// // ? Query name is a bold Text variant that is of weight 500 in ADS +// // ? Query name/info font size is larger in FE component - 14px vs 13px in Figma + +export const QueryResponseTab = (props: Props) => { const { actionName, actionSource, @@ -90,7 +91,15 @@ const QueryResponseTab = (props: Props) => { onRunClick, runErrorMessage, } = props; + const dispatch = useDispatch(); + const { toggle: toggleContentTypeMenuOpen, value: isContentTypeMenuOpen } = + useBoolean(false); + + const dataContainerRef = useRef(null); + const isDataContainerHovered = useHover(dataContainerRef); + const isContentTypeSelectorVisible = + isDataContainerHovered || isContentTypeMenuOpen; const isActionRedesignEnabled = useFeatureFlag( FEATURE_FLAG.release_actions_redesign_enabled, @@ -105,6 +114,56 @@ const QueryResponseTab = (props: Props) => { actionResponseDisplayDataFormats(actionResponse); let output: Record[] | string = ""; + let errorMessage = runErrorMessage; + let hintMessages: Array = []; + let showPreparedStatementWarning = false; + + // Query is executed even once during the session, show the response data. + if (actionResponse) { + if (!actionResponse.isExecutionSuccess) { + // Pass the error to be shown in the error tab + errorMessage = actionResponse.readableError + ? getErrorAsString(actionResponse.readableError) + : getErrorAsString(actionResponse.body); + } else if (isString(actionResponse.body)) { + //reset error. + errorMessage = ""; + try { + // Try to parse response as JSON array to be displayed in the Response tab + output = JSON.parse(actionResponse.body); + } catch (e) { + // In case the string is not a JSON, wrap it in a response object + output = [ + { + response: actionResponse.body, + }, + ]; + } + } else { + //reset error. + errorMessage = ""; + // TODO: Fix this the next time the file is edited + // eslint-disable-next-line @typescript-eslint/no-explicit-any + output = actionResponse.body as any; + } + + if (actionResponse.messages && actionResponse.messages.length) { + //reset error. + errorMessage = ""; + hintMessages = actionResponse.messages; + } + + const { actionConfiguration } = currentActionConfig; + const hasPluginSpecifiedTemplates = + actionConfiguration?.pluginSpecifiedTemplates?.[0]?.value === true; + // oracle have different key for prepared statements + const hasPreparedStatement = + actionConfiguration?.formData?.preparedStatement?.data === true; + + if (errorMessage && (hasPluginSpecifiedTemplates || hasPreparedStatement)) { + showPreparedStatementWarning = true; + } + } const responseBodyTabs = responseDataTypes && @@ -129,9 +188,8 @@ const QueryResponseTab = (props: Props) => { return { value: item.key, label: item.title }; }); - const [selectedControl, setSelectedControl] = useState( - segmentedControlOptions[0]?.value, - ); + const [firstOption] = segmentedControlOptions; + const [selectedControl, setSelectedControl] = useState(firstOption?.value); const responseState = actionResponse && getUpdateTimestamp(actionResponse.request); @@ -158,64 +216,13 @@ const QueryResponseTab = (props: Props) => { ); }; - const responseTabOnRunClick = () => { + const handleRunClick = useEventCallback(() => { onRunClick(); AnalyticsUtil.logEvent("RESPONSE_TAB_RUN_ACTION_CLICK", { source: "QUERY_PANE", }); - }; - - let error = runErrorMessage; - let hintMessages: Array = []; - let showPreparedStatementWarning = false; - - // Query is executed even once during the session, show the response data. - if (actionResponse) { - if (!actionResponse.isExecutionSuccess) { - // Pass the error to be shown in the error tab - error = actionResponse.readableError - ? getErrorAsString(actionResponse.readableError) - : getErrorAsString(actionResponse.body); - } else if (isString(actionResponse.body)) { - //reset error. - error = ""; - try { - // Try to parse response as JSON array to be displayed in the Response tab - output = JSON.parse(actionResponse.body); - } catch (e) { - // In case the string is not a JSON, wrap it in a response object - output = [ - { - response: actionResponse.body, - }, - ]; - } - } else { - //reset error. - error = ""; - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - output = actionResponse.body as any; - } - - if (actionResponse.messages && actionResponse.messages.length) { - //reset error. - error = ""; - hintMessages = actionResponse.messages; - } - - const { actionConfiguration } = currentActionConfig; - const hasPluginSpecifiedTemplates = - actionConfiguration?.pluginSpecifiedTemplates?.[0]?.value === true; - // oracle have different key for prepared statements - const hasPreparedStatement = - actionConfiguration?.formData?.preparedStatement?.data === true; - - if (error && (hasPluginSpecifiedTemplates || hasPreparedStatement)) { - showPreparedStatementWarning = true; - } - } + }); const navigateToSettings = useCallback(() => { if (isActionRedesignEnabled) { @@ -225,24 +232,70 @@ const QueryResponseTab = (props: Props) => { } }, [dispatch, isActionRedesignEnabled]); - const preparedStatementCalloutLinks: CalloutLinkProps[] = [ - { - onClick: navigateToSettings, - children: createMessage(PREPARED_STATEMENT_WARNING.LINK), - }, - ]; + const preparedStatementCalloutLinks: CalloutLinkProps[] = useMemo( + () => [ + { + onClick: navigateToSettings, + children: createMessage(PREPARED_STATEMENT_WARNING.LINK), + }, + ], + [navigateToSettings], + ); + + const queryTooltipContent = useMemo(() => { + if (actionResponse) { + const messages = [ + [ + "duration", + "Time to run", + `${(Number(actionResponse.duration) / 1000).toFixed(1)}s`, + ], + ]; + + if (actionResponse.size) { + messages.push([ + "size", + "Response size", + `${(Number(5000) / 1000).toFixed(1)}kb`, + ]); + } + + return ( + <> + {messages.map(([key, title, message]) => ( +
{`${title}: ${message}`}
+ ))} + + ); + } + + return null; + }, [actionResponse]); + + const handleContentTypeChange = useEventCallback((e?: Event) => { + if (e?.target && e.target instanceof HTMLElement) { + const { value } = e.target.dataset; + + if (typeof value === "string") { + setSelectedControl(value); + onResponseTabSelect(value); + } + } + }); - if (isRunning) { + if (!isRunning) { return ( - + + + ); } return ( - + {showPreparedStatementWarning && ( { {createMessage(PREPARED_STATEMENT_WARNING.MESSAGE)} )} - {error && ( + {errorMessage && ( @@ -301,22 +354,26 @@ const QueryResponseTab = (props: Props) => { )} {hintMessages && hintMessages.length > 0 && ( - + {hintMessages.map((msg, index) => ( {msg} ))} - + )} + {currentActionConfig && output && responseBodyTabs && responseBodyTabs.length > 0 && selectedTabIndex !== -1 && ( - - - + + {/* { }} options={segmentedControlOptions} value={selectedControl} - /> + /> */} + + + + + {`${actionName}.run():`} + + {actionResponse?.isExecutionSuccess ? ( + {`${output.length} record${output.length > 1 && "s"}`} + ) : ( + + Error + + )} + + - - - + + + + + + + + + {selectedControl} + + + + + View as + + + {segmentedControlOptions.map(({ label, value }) => ( + + {label} + + ))} + + + + )} - {!output && !error && ( + {!output && !errorMessage && ( )} - + ); }; - -export default QueryResponseTab; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/index.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/index.ts new file mode 100644 index 00000000000..9b719118de8 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/index.ts @@ -0,0 +1 @@ +export { QueryResponseTab as default } from "./QueryResponseTab"; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts new file mode 100644 index 00000000000..41392befb69 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts @@ -0,0 +1,66 @@ +import styled from "styled-components"; +import { Button, Text } from "@appsmith/ads"; + +export const HelpSection = styled.div``; + +export const Root = styled.div` + display: flex; + flex-direction: column; +`; + +const STATUS_BAR_HEIGHT = 40; + +export const DataContainer = styled.div<{ $height: number }>` + height: calc(${({ $height }) => $height}px - 1px); + display: grid; + grid-template-rows: ${STATUS_BAR_HEIGHT}px 1fr; + grid-template-columns: 100%; + position: relative; + overflow: clip; +`; + +export const Response = styled.div` + overflow: auto; +`; + +export const StatusBar = styled.div` + position: sticky; + top: 0px; + display: flex; + justify-content: space-between; + height: ${STATUS_BAR_HEIGHT}px; + padding: 8px; + border-bottom: 1px solid var(--ads-v2-color-border); + z-index: var(--ads-v2-z-index-1); +`; + +export const StatusBarInfo = styled.div` + display: flex; + align-items: center; + gap: var(--ads-v2-spaces-2); +`; + +export const Fab = styled(Button)<{ $isVisible: boolean }>` + && { + position: absolute; + right: 20px; + bottom: calc(${STATUS_BAR_HEIGHT}px + 20px); + box-shadow: 0px 1px 20px 0px rgba(76, 86, 100, 0.11); + z-index: var(--ads-v2-z-index-3); + opacity: ${({ $isVisible }) => ($isVisible ? 1 : 0)}; + transition: opacity 0.25s; + } +`; + +export const LoadingContainer = styled.div` + height: calc(100% - ${STATUS_BAR_HEIGHT}px); +`; + +export const StatusBarText = styled(Text)<{ + $isBold?: boolean; + $isError?: boolean; +}>` + font-size: 13px; + ${({ $isBold }) => $isBold && `font-weight: 700;`} + ${({ $isError }) => $isError && `color: var(--ads-v2-color-fg-on-error);`} +`; diff --git a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx index 9dd4c29ead0..de65f52af95 100644 --- a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx +++ b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx @@ -2,9 +2,7 @@ import type { BottomTab } from "components/editorComponents/EntityBottomTabs"; import EntityBottomTabs from "components/editorComponents/EntityBottomTabs"; import React, { useCallback, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import styled from "styled-components"; import { getErrorCount } from "selectors/debuggerSelectors"; -import { Text, TextType } from "@appsmith/ads-old"; import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/constants"; import { DEBUGGER_ERRORS, @@ -16,7 +14,6 @@ import DebuggerLogs from "components/editorComponents/Debugger/DebuggerLogs"; import ErrorLogs from "components/editorComponents/Debugger/Errors"; import Schema from "PluginActionEditor/components/PluginActionResponse/components/Schema"; import type { ActionResponse } from "api/ActionAPI"; -import { isString } from "lodash"; import type { SourceEntity } from "entities/AppsmithConsole"; import type { Action } from "entities/Action"; import QueryResponseTab from "PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab"; @@ -37,17 +34,6 @@ import { getIDEViewMode } from "selectors/ideSelectors"; import { EditorViewMode } from "ee/entities/IDE/constants"; import { IDEBottomView, ViewHideBehaviour } from "IDE"; -const ResultsCount = styled.div` - position: absolute; - right: ${(props) => props.theme.spaces[17] + 1}px; - top: 9px; - color: var(--ads-v2-color-fg); -`; - -const ErrorText = styled(Text)` - color: var(--ads-v2-colors-action-error-label-default-fg); -`; - interface QueryDebuggerTabsProps { actionSource: SourceEntity; currentActionConfig?: Action; @@ -71,9 +57,6 @@ function QueryDebuggerTabs({ runErrorMessage, showSchema, }: QueryDebuggerTabsProps) { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let output: Record[] | null = null; const dispatch = useDispatch(); const { open, responseTabHeight, selectedTab } = useSelector( @@ -172,27 +155,6 @@ function QueryDebuggerTabs({ } }, [currentActionConfig?.id]); - // Query is executed even once during the session, show the response data. - if (actionResponse) { - if (isString(actionResponse.body)) { - try { - // Try to parse response as JSON array to be displayed in the Response tab - output = JSON.parse(actionResponse.body); - } catch (e) { - // In case the string is not a JSON, wrap it in a response object - output = [ - { - response: actionResponse.body, - }, - ]; - } - } else { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - output = actionResponse.body as any; - } - } - const setQueryResponsePaneHeight = useCallback( (height: number) => { dispatch( @@ -276,21 +238,6 @@ function QueryDebuggerTabs({ onHideClick={onToggle} setHeight={setQueryResponsePaneHeight} > - {output && !!output.length && ( - - - Result: - {actionResponse?.isExecutionSuccess ? ( - {` ${output.length} Record${ - output.length > 1 ? "s" : "" - }`} - ) : ( - {" Error"} - )} - - - )} - Date: Tue, 12 Nov 2024 23:53:22 +0300 Subject: [PATCH 05/26] feat: adjust sizing & spacing --- .../editorComponents/ActionExecutionInProgressView.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/client/src/components/editorComponents/ActionExecutionInProgressView.tsx b/app/client/src/components/editorComponents/ActionExecutionInProgressView.tsx index 627d1f1de39..1627c0c1f31 100644 --- a/app/client/src/components/editorComponents/ActionExecutionInProgressView.tsx +++ b/app/client/src/components/editorComponents/ActionExecutionInProgressView.tsx @@ -21,13 +21,12 @@ const LoadingOverlayContainer = styled.div` flex-direction: column; justify-content: center; align-items: center; - gap: var(--ads-v2-spaces-3); + gap: var(--ads-v2-spaces-5); background-color: transparent; position: relative; z-index: 20; width: 100%; height: 100%; - margin-top: 5px; `; const LoadingProgressWrapper = styled.div` @@ -56,7 +55,7 @@ const ActionExecutionInProgressView = ({ - + {createMessage(ACTION_EXECUTION_MESSAGE, actionType)} @@ -64,7 +63,7 @@ const ActionExecutionInProgressView = ({ className={`t--cancel-action-button`} kind="secondary" onClick={handleCancelActionExecution} - size="md" + size="sm" > {createMessage(ACTION_EXECUTION_CANCEL)} From cf838f47b4a8f1b6092a233e002b38c7e4f24ee4 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 13 Nov 2024 11:28:59 +0300 Subject: [PATCH 06/26] chore: remove test condition --- .../components/QueryResponseTab/QueryResponseTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index ef6e3831cb4..79ea79fb83f 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -283,7 +283,7 @@ export const QueryResponseTab = (props: Props) => { } }); - if (!isRunning) { + if (isRunning) { return ( Date: Wed, 13 Nov 2024 14:24:29 +0300 Subject: [PATCH 07/26] chore: add common constants --- .../components/QueryResponseTab/constants.ts | 2 ++ .../components/PluginActionResponse/components/constants.ts | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/constants.ts create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/constants.ts diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/constants.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/constants.ts new file mode 100644 index 00000000000..c8093c4039a --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/constants.ts @@ -0,0 +1,2 @@ +/** Offset needed to make table height match response tab height */ +export const RESPONSE_TABLE_HEIGHT_OFFSET = 14; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/constants.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/constants.ts new file mode 100644 index 00000000000..be218f4476f --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/constants.ts @@ -0,0 +1,2 @@ +/** Height for tab bar in px. Required for container height calculations. */ +export const TAB_BAR_HEIGHT = 40; From 3c6a10748ca8d8f8146b80bb783e9dff8e69b126 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 13 Nov 2024 14:25:57 +0300 Subject: [PATCH 08/26] feat: update design --- .../components/NoResponse.tsx | 36 ++++---- app/client/src/assets/images/no-response.svg | 83 +++++++++++++------ app/client/src/ce/constants/messages.ts | 1 + 3 files changed, 71 insertions(+), 49 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/NoResponse.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/NoResponse.tsx index a133ec66556..e42c027a816 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/NoResponse.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/NoResponse.tsx @@ -1,12 +1,10 @@ import NoResponseSVG from "assets/images/no-response.svg"; -import { Classes, Text, TextType } from "@appsmith/ads-old"; -import { - EMPTY_RESPONSE_FIRST_HALF, - EMPTY_RESPONSE_LAST_HALF, -} from "ee/constants/messages"; +import { Text, TextType } from "@appsmith/ads-old"; +import { EMPTY_RESPONSE_RUN } from "ee/constants/messages"; import { Button } from "@appsmith/ads"; import React from "react"; import styled from "styled-components"; +import { TAB_BAR_HEIGHT } from "./constants"; const StyledText = styled(Text)` &&&& { @@ -15,25 +13,20 @@ const StyledText = styled(Text)` `; const NoResponseContainer = styled.div` - flex: 1; width: 100%; + height: calc(100% - ${TAB_BAR_HEIGHT}px); display: flex; align-items: center; justify-content: center; flex-direction: column; + gap: 24px; +`; - .${Classes.ICON} { - margin-right: 0; - - svg { - width: 150px; - height: 150px; - } - } - - .${Classes.TEXT} { - margin-top: ${(props) => props.theme.spaces[9]}px; - } +const RunGroup = styled.div` + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; `; interface NoResponseProps { @@ -49,8 +42,8 @@ export const NoResponse = ({ }: NoResponseProps) => ( no-response-yet -
- {EMPTY_RESPONSE_FIRST_HALF()} + + {EMPTY_RESPONSE_RUN()} - {EMPTY_RESPONSE_LAST_HALF()} -
+
); diff --git a/app/client/src/assets/images/no-response.svg b/app/client/src/assets/images/no-response.svg index 6fea7ab0957..89f819dc189 100644 --- a/app/client/src/assets/images/no-response.svg +++ b/app/client/src/assets/images/no-response.svg @@ -1,27 +1,56 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index b5a102028ed..379b72999a7 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -569,6 +569,7 @@ export const ACTION_CONFIGURATION_UPDATED = () => "Configuration updated"; export const WIDGET_PROPERTIES_UPDATED = () => "Widget properties were updated"; export const EMPTY_RESPONSE_FIRST_HALF = () => "🙌 Click on"; export const EMPTY_RESPONSE_LAST_HALF = () => "to get a response"; +export const EMPTY_RESPONSE_RUN = () => "Run the query to get a response"; export const EMPTY_JS_RESPONSE_LAST_HALF = () => "to view response of selected function"; export const INVALID_EMAIL = () => "Please enter a valid email"; From 57792a223686bbbd94bf63f600f5ad6c037d671d Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 13 Nov 2024 14:26:37 +0300 Subject: [PATCH 09/26] feat: update design & switch to minWtidth --- .../PluginActionResponse/components/Table.tsx | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx index d8d622476a8..ce176660518 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx @@ -39,7 +39,6 @@ export const TableWrapper = styled.div<{ minColumnWidth?: number }>` width: 100%; height: auto; background: var(--ads-v2-color-bg); - border: 1px solid var(--ads-v2-color-border); box-sizing: border-box; display: flex; justify-content: space-between; @@ -55,7 +54,6 @@ export const TableWrapper = styled.div<{ minColumnWidth?: number }>` border-spacing: 0; color: var(--ads-v2-color-fg); position: relative; - background: var(--ads-v2-color-gray-50); display: table; width: 100%; height: auto; @@ -71,13 +69,7 @@ export const TableWrapper = styled.div<{ minColumnWidth?: number }>` } .tr { overflow: hidden; - border-right: 1px solid var(--ads-v2-color-border); - :nth-child(even) { - background: var(--ads-v2-color-gray-50); - } - :nth-child(odd) { - background: var(--ads-v2-color-bg); - } + border-bottom: 1px solid var(--ads-v2-color-black-75); &.selected-row { background: var(--ads-v2-color-bg-subtle); &:hover { @@ -92,7 +84,6 @@ export const TableWrapper = styled.div<{ minColumnWidth?: number }>` .td { margin: 0; padding: 9px 10px; - border-right: 1px solid var(--ads-v2-color-border); position: relative; font-size: ${TABLE_SIZES.ROW_FONT_SIZE}px; line-height: ${TABLE_SIZES.ROW_FONT_SIZE}px; @@ -255,7 +246,7 @@ function Table(props: TableProps) { const defaultColumn = React.useMemo( () => ({ - width: 170, + minWidth: 170, }), [], ); @@ -343,7 +334,7 @@ function Table(props: TableProps) {
From d78847f9ef6401b0d20c0da968e51454aaefac6e Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 13 Nov 2024 14:27:36 +0300 Subject: [PATCH 10/26] chore: switch to common tab bar height & update type --- .../components/QueryResponseTab/styles.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts index 41392befb69..f560b55f864 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts @@ -1,5 +1,6 @@ import styled from "styled-components"; import { Button, Text } from "@appsmith/ads"; +import { TAB_BAR_HEIGHT } from "../constants"; export const HelpSection = styled.div``; @@ -8,12 +9,10 @@ export const Root = styled.div` flex-direction: column; `; -const STATUS_BAR_HEIGHT = 40; - export const DataContainer = styled.div<{ $height: number }>` height: calc(${({ $height }) => $height}px - 1px); display: grid; - grid-template-rows: ${STATUS_BAR_HEIGHT}px 1fr; + grid-template-rows: ${TAB_BAR_HEIGHT}px 1fr; grid-template-columns: 100%; position: relative; overflow: clip; @@ -28,7 +27,7 @@ export const StatusBar = styled.div` top: 0px; display: flex; justify-content: space-between; - height: ${STATUS_BAR_HEIGHT}px; + height: ${TAB_BAR_HEIGHT}px; padding: 8px; border-bottom: 1px solid var(--ads-v2-color-border); z-index: var(--ads-v2-z-index-1); @@ -44,7 +43,7 @@ export const Fab = styled(Button)<{ $isVisible: boolean }>` && { position: absolute; right: 20px; - bottom: calc(${STATUS_BAR_HEIGHT}px + 20px); + bottom: calc(${TAB_BAR_HEIGHT}px + 20px); box-shadow: 0px 1px 20px 0px rgba(76, 86, 100, 0.11); z-index: var(--ads-v2-z-index-3); opacity: ${({ $isVisible }) => ($isVisible ? 1 : 0)}; @@ -53,13 +52,15 @@ export const Fab = styled(Button)<{ $isVisible: boolean }>` `; export const LoadingContainer = styled.div` - height: calc(100% - ${STATUS_BAR_HEIGHT}px); + height: calc(100% - ${TAB_BAR_HEIGHT}px); `; -export const StatusBarText = styled(Text)<{ +interface StatusBarTextProps { $isBold?: boolean; $isError?: boolean; -}>` +} + +export const StatusBarText = styled(Text)` font-size: 13px; ${({ $isBold }) => $isBold && `font-weight: 700;`} ${({ $isError }) => $isError && `color: var(--ads-v2-color-fg-on-error);`} From 70c4e999851924fbe7f7ffde7ed5b179badcc9c5 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 13 Nov 2024 14:28:30 +0300 Subject: [PATCH 11/26] chore: correct size & fix potential bug --- .../QueryResponseTab/QueryResponseTab.tsx | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index 79ea79fb83f..c5f3c8abb12 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -54,6 +54,7 @@ import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import * as Styled from "./styles"; import { useBoolean, useEventCallback, useHover } from "usehooks-ts"; +import { RESPONSE_TABLE_HEIGHT_OFFSET } from "./constants"; interface Props { actionSource: SourceEntity; @@ -73,9 +74,11 @@ interface Props { // // * On hover of query name and number of records, meta data of api run (outlined above) should show up as tooltip. (design) // // * Change result type from segmented control to a FAB with dropdown menu. // // * Change loading state button/spinner/spacing. (design) -// * Change the empty state text and button alignment. (design) -// * Update table appearance. -// * Table columns have a fixed width of 170px now, this needs to be updated to min-width. +// // * Change the empty state text and button alignment. (design) +// // * Change segmented control naming +// // * Update table appearance. +// // * Table columns have a fixed width of 170px now, this needs to be updated to min-width. +// * Fix FAB hover issue. // * Fix Cypress tests related to result type control change. // // ? Query name is a bold Text variant that is of weight 500 in ADS @@ -182,14 +185,18 @@ export const QueryResponseTab = (props: Props) => { }; }); - const segmentedControlOptions = + const contentTypeOptions = responseBodyTabs && responseBodyTabs.map((item) => { return { value: item.key, label: item.title }; }); - const [firstOption] = segmentedControlOptions; - const [selectedControl, setSelectedControl] = useState(firstOption?.value); + const [firstContentTypeOption] = contentTypeOptions; + const [selectedContentType, setSelectedContentType] = useState( + firstContentTypeOption?.value, + ); + + const contentType = selectedContentType || firstContentTypeOption?.value; const responseState = actionResponse && getUpdateTimestamp(actionResponse.request); @@ -256,7 +263,7 @@ export const QueryResponseTab = (props: Props) => { messages.push([ "size", "Response size", - `${(Number(5000) / 1000).toFixed(1)}kb`, + `${(Number(actionResponse.size) / 1000).toFixed(1)}kb`, ]); } @@ -277,7 +284,7 @@ export const QueryResponseTab = (props: Props) => { const { value } = e.target.dataset; if (typeof value === "string") { - setSelectedControl(value); + setSelectedContentType(value); onResponseTabSelect(value); } } @@ -294,6 +301,16 @@ export const QueryResponseTab = (props: Props) => { ); } + if (!output && !errorMessage) { + return ( + + ); + } + return ( {showPreparedStatementWarning && ( @@ -413,10 +430,10 @@ export const QueryResponseTab = (props: Props) => { @@ -429,9 +446,9 @@ export const QueryResponseTab = (props: Props) => { : "arrow-down-s-line" } kind="secondary" - startIcon={`content-type-${selectedControl.toLocaleLowerCase()}`} + startIcon={`content-type-${contentType.toLocaleLowerCase()}`} > - {selectedControl} + {selectedContentType} @@ -439,7 +456,7 @@ export const QueryResponseTab = (props: Props) => { View as - {segmentedControlOptions.map(({ label, value }) => ( + {contentTypeOptions.map(({ label, value }) => ( Date: Wed, 13 Nov 2024 19:45:16 +0300 Subject: [PATCH 12/26] fix: switch from hook&refs to direct event handlers --- .../QueryResponseTab/QueryResponseTab.tsx | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index c5f3c8abb12..318bc42b629 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useRef, useMemo, useState } from "react"; +import React, { useCallback, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import ReactJson from "react-json-view"; import { @@ -53,7 +53,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import * as Styled from "./styles"; -import { useBoolean, useEventCallback, useHover } from "usehooks-ts"; +import { useBoolean, useEventCallback } from "usehooks-ts"; import { RESPONSE_TABLE_HEIGHT_OFFSET } from "./constants"; interface Props { @@ -78,7 +78,7 @@ interface Props { // // * Change segmented control naming // // * Update table appearance. // // * Table columns have a fixed width of 170px now, this needs to be updated to min-width. -// * Fix FAB hover issue. +// // * Fix FAB hover issue. // * Fix Cypress tests related to result type control change. // // ? Query name is a bold Text variant that is of weight 500 in ADS @@ -99,8 +99,12 @@ export const QueryResponseTab = (props: Props) => { const { toggle: toggleContentTypeMenuOpen, value: isContentTypeMenuOpen } = useBoolean(false); - const dataContainerRef = useRef(null); - const isDataContainerHovered = useHover(dataContainerRef); + const { + setFalse: setIsNotHovered, + setTrue: setIsHovered, + value: isDataContainerHovered, + } = useBoolean(false); + const isContentTypeSelectorVisible = isDataContainerHovered || isContentTypeMenuOpen; @@ -196,7 +200,8 @@ export const QueryResponseTab = (props: Props) => { firstContentTypeOption?.value, ); - const contentType = selectedContentType || firstContentTypeOption?.value; + const currentContentType = + selectedContentType || firstContentTypeOption?.value; const responseState = actionResponse && getUpdateTimestamp(actionResponse.request); @@ -387,7 +392,8 @@ export const QueryResponseTab = (props: Props) => { selectedTabIndex !== -1 && ( {/* { {`${actionName}.run():`} {actionResponse?.isExecutionSuccess ? ( - {`${output.length} record${output.length > 1 && "s"}`} + {`${output.length} record${output.length > 1 ? "s" : ""}`} ) : ( Error @@ -430,7 +436,7 @@ export const QueryResponseTab = (props: Props) => { { : "arrow-down-s-line" } kind="secondary" - startIcon={`content-type-${contentType.toLocaleLowerCase()}`} + startIcon={`content-type-${currentContentType.toLocaleLowerCase()}`} > - {selectedContentType} + {currentContentType} @@ -471,13 +477,6 @@ export const QueryResponseTab = (props: Props) => { )} - {!output && !errorMessage && ( - - )} ); }; From c741a2f1b7d928f10ce80450c7d89a73a275e8c2 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Thu, 14 Nov 2024 18:42:24 +0300 Subject: [PATCH 13/26] fix: account for scrollbar width --- .../components/QueryResponseTab/QueryResponseTab.tsx | 4 +++- .../components/QueryResponseTab/styles.ts | 2 ++ .../components/PluginActionResponse/components/Table.tsx | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index 318bc42b629..6c88b0f559d 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -438,7 +438,9 @@ export const QueryResponseTab = (props: Props) => { data={output} responseType={currentContentType} tableBodyHeight={ - responseTabHeight + RESPONSE_TABLE_HEIGHT_OFFSET + responseTabHeight + + RESPONSE_TABLE_HEIGHT_OFFSET - + scrollbarOffset } /> diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts index f560b55f864..213dc3b6a4a 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/styles.ts @@ -20,6 +20,8 @@ export const DataContainer = styled.div<{ $height: number }>` export const Response = styled.div` overflow: auto; + width: 100%; + height: 100%; `; export const StatusBar = styled.div` diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx index ce176660518..d833e5b43e0 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Table.tsx @@ -43,7 +43,7 @@ export const TableWrapper = styled.div<{ minColumnWidth?: number }>` display: flex; justify-content: space-between; flex-direction: column; - overflow: scroll; + overflow: auto; .tableWrap { height: 100%; display: block; From 7df67760d81c5fd34d07647032f2e621d1f9c000 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Thu, 14 Nov 2024 18:44:00 +0300 Subject: [PATCH 14/26] chore: add status bar for error state --- .../QueryResponseTab/QueryResponseTab.tsx | 130 +++++++++++------- .../components/QueryResponseTab/styles.ts | 4 + 2 files changed, 81 insertions(+), 53 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index 6c88b0f559d..1a6190fefe4 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -55,6 +55,7 @@ import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import * as Styled from "./styles"; import { useBoolean, useEventCallback } from "usehooks-ts"; import { RESPONSE_TABLE_HEIGHT_OFFSET } from "./constants"; +import { scrollbarWidth } from "utils/helpers"; interface Props { actionSource: SourceEntity; @@ -79,8 +80,14 @@ interface Props { // // * Update table appearance. // // * Table columns have a fixed width of 170px now, this needs to be updated to min-width. // // * Fix FAB hover issue. +// // * Account for scrollbars that are always shown. +// // * Add status bar to error state, hide bind to UI button. +// // * Add dashed underline for status bar fn name & meta. +// * Update REST API +// * Update GQL API // * Fix Cypress tests related to result type control change. +// ? Make table stretchable - this is not easily accomplishable with the current table component, need to calculate column width manually. // // ? Query name is a bold Text variant that is of weight 500 in ADS // // ? Query name/info font size is larger in FE component - 14px vs 13px in Figma @@ -120,6 +127,8 @@ export const QueryResponseTab = (props: Props) => { const { responseDataTypes, responseDisplayFormat } = actionResponseDisplayDataFormats(actionResponse); + const scrollbarOffset = scrollbarWidth(); + let output: Record[] | string = ""; let errorMessage = runErrorMessage; let hintMessages: Array = []; @@ -328,52 +337,67 @@ export const QueryResponseTab = (props: Props) => { )} {errorMessage && ( - - - - Your query failed to execute +
+ + + + {`${actionName}.run():`} + + + Error + + + + + + + Your query failed to execute + {actionResponse && + (actionResponse.pluginErrorDetails || actionResponse.body) && + ":"} + {actionResponse && - (actionResponse.pluginErrorDetails || actionResponse.body) && - ":"} - - {actionResponse && - (actionResponse.pluginErrorDetails ? ( - <> -
- {actionResponse.pluginErrorDetails.downstreamErrorMessage || - actionResponse.pluginErrorDetails.appsmithErrorMessage} -
- {actionResponse.pluginErrorDetails.downstreamErrorCode && ( - - )} - - ) : ( - actionResponse.body && ( -
{actionResponse.body}
- ) - ))} - -
- {actionResponse && actionResponse.request && ( - e.stopPropagation()} - > - - - )} -
+ (actionResponse.pluginErrorDetails ? ( + <> +
+ {actionResponse.pluginErrorDetails + .downstreamErrorMessage || + actionResponse.pluginErrorDetails.appsmithErrorMessage} +
+ {actionResponse.pluginErrorDetails.downstreamErrorCode && ( + + )} + + ) : ( + actionResponse.body && ( +
+ {actionResponse.body} +
+ ) + ))} + + + {actionResponse && actionResponse.request && ( + e.stopPropagation()} + > + + + )} + +
)} {hintMessages && hintMessages.length > 0 && ( @@ -392,6 +416,7 @@ export const QueryResponseTab = (props: Props) => { selectedTabIndex !== -1 && ( @@ -414,16 +439,13 @@ export const QueryResponseTab = (props: Props) => { placement="bottom" > - + {`${actionName}.run():`} - {actionResponse?.isExecutionSuccess ? ( - {`${output.length} record${output.length > 1 ? "s" : ""}`} - ) : ( - - Error - - )} + {`${output.length} record${output.length > 1 ? "s" : ""}`} { ` font-size: 13px; + ${({ $hasTooltip }) => + $hasTooltip && + `text-decoration: underline var(--ads-v2-color-border) dashed;`} ${({ $isBold }) => $isBold && `font-weight: 700;`} ${({ $isError }) => $isError && `color: var(--ads-v2-color-fg-on-error);`} `; From 041e7b6431add197b577e2696e766974d600aedd Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Tue, 19 Nov 2024 00:29:41 +0300 Subject: [PATCH 15/26] chore: fix response type selector tests --- .../BugTests/Binding_Bug28287_Spec.ts | 4 +- .../Datasources/Redis_Basic_Spec.ts | 20 +++++----- .../ServerSide/GenerateCRUD/MySQL1_Spec.ts | 4 +- .../ServerSide/GenerateCRUD/MySQL2_Spec.ts | 6 +-- .../ServerSide/GenerateCRUD/Postgres2_Spec.ts | 6 +-- .../Postgres_DataTypes/UUID_Spec.ts | 6 +-- .../ServerSide/QueryPane/Mongo1_spec.ts | 8 ++-- .../ServerSide/QueryPane/S3_1_spec.js | 2 +- .../Sanity/Datasources/Arango_Basic_Spec.ts | 10 ++--- .../e2e/Sanity/Datasources/MockDBs_Spec.ts | 4 +- .../cypress/support/Pages/DataSources.ts | 22 +++++++++++ .../support/Pages/IDE/BottomPane/Response.ts | 32 +++++++++++++--- .../QueryResponseTab/QueryResponseTab.tsx | 37 +------------------ 13 files changed, 85 insertions(+), 76 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts b/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts index 5a38feeaf45..04fef39098d 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts @@ -45,9 +45,9 @@ describe( EditorNavigation.SelectEntityByName(queryName, EntityType.Query); BottomPane.response.switchToResponseTab(); - + BottomPane.response.openResponseTypeMenu(); agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("TABLE"), + BottomPane.response.getResponseTypeMenuItem("TABLE"), ); }); }); diff --git a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts index 01e4106a445..bab4634d5b4 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts @@ -30,32 +30,32 @@ describe( //Add HSET dataSources.CreateQueryAfterDSSaved(); dataSources.EnterQuery(hSetReceipe); - dataSources.RunQueryNVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! dataSources.AssertQueryTableResponse(0, "4"); //Success response for 4 keys inserted via above HSET! //Read only one key from above HSET dataSources.EnterQuery(hGetKeys); - dataSources.RunQueryNVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! dataSources.AssertQueryTableResponse(0, "Vegetable Stir Fry"); //Read more than one key from above HSET dataSources.EnterQuery(hMGet); - dataSources.RunQueryNVerifyResponseViews(2); + dataSources.runQueryAndVerifyResponseViews(2); dataSources.AssertQueryTableResponse(0, "easy"); dataSources.AssertQueryTableResponse(1, "Vegetable Stir Fry"); //Update key value in HSET dataSources.EnterQuery(hUpdate); - dataSources.RunQueryNVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! //validate updated key dataSources.EnterQuery(getUpdatedKey); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); dataSources.AssertQueryTableResponse(0, "medium"); //Get All keys from HSET dataSources.EnterQuery(getAll); - dataSources.RunQueryNVerifyResponseViews(8); //4 keys, 4 values + dataSources.runQueryAndVerifyResponseViews(8); //4 keys, 4 values dataSources.ReadQueryTableResponse(0).then(($cellData: any) => { expect($cellData).to.be.oneOf([ "name", @@ -70,11 +70,11 @@ describe( //Ading one more key/value to HSET dataSources.EnterQuery(addNewKeyValue); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); //Verify new key/value also added to HSET dataSources.EnterQuery(getAll); - dataSources.RunQueryNVerifyResponseViews(10); //5 keys, 5 values + dataSources.runQueryAndVerifyResponseViews(10); //5 keys, 5 values dataSources.ReadQueryTableResponse(0).then(($cellData: any) => { expect($cellData).to.be.oneOf([ "name", @@ -87,11 +87,11 @@ describe( //Deleting the Hash key dataSources.EnterQuery(deletehKey); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); //Verify Deletion is success dataSources.EnterQuery(hGetKeys); - dataSources.RunQueryNVerifyResponseViews(); //5 keys, 5 values + dataSources.runQueryAndVerifyResponseViews(); //5 keys, 5 values dataSources.AssertQueryTableResponse(0, "null"); // Delete the query & datasource diff --git a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL1_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL1_Spec.ts index e174cd171cf..b17735d1508 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL1_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL1_Spec.ts @@ -163,7 +163,7 @@ describe( agHelper.FocusElement(locators._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); //failing sometimes! - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertTableInVirtuosoList(dsName, "productlines"); agHelper.ActionContextMenuWithInPane({ @@ -279,7 +279,7 @@ describe( agHelper.FocusElement(locators._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertTableInVirtuosoList(dsName, "Stores", false); }); diff --git a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts index ce5773313e8..6fa93253ff7 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts @@ -68,7 +68,7 @@ describe( agHelper.FocusElement(locators._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertTableInVirtuosoList(dsName, "Stores"); agHelper.ActionContextMenuWithInPane({ @@ -79,7 +79,7 @@ describe( it("2. Validate Select record from Postgress datasource & verify query response", () => { dataSources.CreateQueryForDS(dsName, "SELECT * FROM Stores LIMIT 10"); - dataSources.RunQueryNVerifyResponseViews(10); + dataSources.runQueryAndVerifyResponseViews(10); dataSources.AssertQueryTableResponse(5, "2112"); dataSources.AssertQueryTableResponse(6, "Mike's Liquors"); // Commenting this deletion of query to make the generate crud work on the new page instead of the current page @@ -375,7 +375,7 @@ describe( agHelper.FocusElement(locators._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertTableInVirtuosoList(dsName, "Stores", false); agHelper.ActionContextMenuWithInPane({ diff --git a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts index 09a77eb14b2..3c827205fa1 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts @@ -61,7 +61,7 @@ describe( agHelper.FocusElement(locators._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); //failing sometimes! - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); }); it("2. Validate Select record from Postgress datasource & verify query response", () => { @@ -70,7 +70,7 @@ describe( "public.vessels", "Select", ); - dataSources.RunQueryNVerifyResponseViews(10); + dataSources.runQueryAndVerifyResponseViews(10); dataSources.AssertQueryTableResponse(0, "371681"); dataSources.AssertQueryTableResponse(6, "Passenger"); agHelper.ActionContextMenuWithInPane({ @@ -617,7 +617,7 @@ describe( dataSources.CreateQueryForDS(dsName, deleteTblQuery, "DropVessels"); agHelper.FocusElement(locators._codeMirrorTextArea); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertTableInVirtuosoList(dsName, "public.vessels", false); }); diff --git a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts index d63fde861a2..bcccd2c15cc 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts @@ -259,7 +259,7 @@ describe( //Validating use of extention query = `CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pgcrypto"`; dataSources.CreateQueryForDS(dsName, query, "verifyUUIDFunctions"); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); @@ -297,7 +297,7 @@ describe( //Validating Addition of new column taking default value form package method query = `ALTER TABLE uuidtype ADD COLUMN newUUID uuid DEFAULT uuid_generate_v4();`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); @@ -314,7 +314,7 @@ describe( //Validating altering the new column default value to generate id from pgcrypto package query = `ALTER TABLE uuidtype ALTER COLUMN newUUID SET DEFAULT gen_random_uuid();`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts index 08fe4506112..49f058d0e52 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts @@ -333,7 +333,7 @@ describe( "Find", ); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); - dataSources.RunQueryNVerifyResponseViews(1, false); + dataSources.runQueryAndVerifyResponseViews(1, false); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -352,7 +352,7 @@ describe( directInput: false, inputFieldName: "Query", }); - dataSources.RunQueryNVerifyResponseViews(1, false); + dataSources.runQueryAndVerifyResponseViews(1, false); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -738,7 +738,7 @@ describe( "Aggregate", ); dataSources.ValidateNSelectDropdown("Command", "Aggregate"); - dataSources.RunQueryNVerifyResponseViews(7, false); + dataSources.runQueryAndVerifyResponseViews(7, false); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -899,7 +899,7 @@ describe( "Find", ); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); - dataSources.RunQueryNVerifyResponseViews(4, false); + dataSources.runQueryAndVerifyResponseViews(4, false); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js index 2bd496ead58..9a0797ac913 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js @@ -77,7 +77,7 @@ describe( "List files", ); - dataSources.RunQueryNVerifyResponseViews(100); + dataSources.runQueryAndVerifyResponseViews(100); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, diff --git a/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts index cbf69cdf90b..84e8546916a 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts @@ -219,7 +219,7 @@ if (CURRENT_REPO == REPO.CE) { } INTO ${collectionName}`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryResponseHeaders([ "writesExecuted", "writesIgnored", @@ -232,7 +232,7 @@ if (CURRENT_REPO == REPO.CE) { FILTER place.type == "Natural" RETURN { country: doc.country, name: place.name }`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(5); //Verify all records are filtered + dataSources.runQueryAndVerifyResponseViews(5); //Verify all records are filtered dataSources.AssertQueryTableResponse(0, "Japan"); dataSources.AssertQueryTableResponse(1, "Mount Fuji"); dataSources.AssertQueryTableResponse(6, "Brazil"); //Widget binding is verified here @@ -265,7 +265,7 @@ if (CURRENT_REPO == REPO.CE) { } IN ${collectionName}`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(); + dataSources.runQueryAndVerifyResponseViews(); dataSources.createQueryWithDatasourceSchemaTemplate( dsName, @@ -276,7 +276,7 @@ if (CURRENT_REPO == REPO.CE) { FILTER document._key == "1" RETURN document`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(1); dataSources.AssertQueryTableResponse(3, "Australia"); //Delete record from collection @@ -287,7 +287,7 @@ if (CURRENT_REPO == REPO.CE) { ); query = `REMOVE "1" in ${collectionName}`; dataSources.EnterQuery(query); - dataSources.RunQueryNVerifyResponseViews(1); //Removing Australia + dataSources.runQueryAndVerifyResponseViews(1); //Removing Australia //Verify no records return for the deleted key query = `FOR document IN ${collectionName} diff --git a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts index b1cd5d459fc..5da58d57cca 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts @@ -42,7 +42,7 @@ describe( 'SELECT * FROM public."users" LIMIT 10;', ); - dataSources.RunQueryNVerifyResponseViews(); //minimum 1 rows are expected + dataSources.runQueryAndVerifyResponseViews(); //minimum 1 rows are expected AppSidebar.navigate(AppSidebarButton.Data); dataSources .getDatasourceListItemDescription(mockDBName) @@ -57,7 +57,7 @@ describe( expect(interception.request.body.source).to.equal("SELF"); }); - dataSources.RunQueryNVerifyResponseViews(); //minimum 1 rows are expected + dataSources.runQueryAndVerifyResponseViews(); //minimum 1 rows are expected AppSidebar.navigate(AppSidebarButton.Data); dataSources .getDatasourceListItemDescription(mockDBName) diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index 059bf5413b8..63d82b767cc 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -1133,6 +1133,7 @@ export class DataSources { this.assertHelper.AssertNetworkStatus("@saveAction", 200); } + /** @deprecated */ public RunQueryNVerifyResponseViews( expectedRecordsCount = 1, tableCheck = true, @@ -1152,6 +1153,27 @@ export class DataSources { BottomPane.response.validateRecordCount(expectedRecordsCount); } + public runQueryAndVerifyResponseViews( + expectedRecordsCount = 1, + tableCheck = true, + ) { + this.RunQuery(); + if (tableCheck) { + BottomPane.response.openResponseTypeMenu(); + + this.agHelper.AssertElementVisibility( + BottomPane.response.getResponseTypeMenuItem("TABLE"), + ); + this.agHelper.AssertElementVisibility( + BottomPane.response.getResponseTypeMenuItem("JSON"), + ); + this.agHelper.AssertElementVisibility( + BottomPane.response.getResponseTypeMenuItem("RAW"), + ); + } + BottomPane.response.validateRecordCount(expectedRecordsCount); + } + public CreateDataSource( dsType: | "Postgres" diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index ca1db0fa7ca..46fcc4802ef 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -1,17 +1,39 @@ class Response { - private ResponseTab = "//button[@data-testid='t--tab-RESPONSE_TAB']"; + private locators = { + responseTab: "//button[@data-testid='t--tab-RESPONSE_TAB']", + responseDataContainer: "[data-testid='t--query-response-data-container']", + responseTypeMenuTrigger: "[data-testid='t--query-response-type-trigger']", + responseType(type: string): string { + return `//div[@data-testid='t--response-tab-segmented-control']//span[text()='${type}']`; + }, + responseTypeMenuItem(type: string): string { + return `//div[@data-testid='t--query-response-type-menu-item' and @data-value='${type}']`; + }, + }; + + /** @deprecated */ + public getResponseTypeSelector = this.locators.responseType; + + public getResponseTypeMenuItem = this.locators.responseTypeMenuItem; public switchToResponseTab(): void { - cy.xpath(this.ResponseTab).click({ force: true }); + cy.xpath(this.locators.responseTab).click({ force: true }); } - public getResponseTypeSelector(type: string): string { - return `//div[@data-testid='t--response-tab-segmented-control']//span[text()='${type}']`; + public openResponseTypeMenu() { + cy.get(this.locators.responseDataContainer).realHover(); + cy.get(this.locators.responseTypeMenuTrigger).realClick(); + } + + public selectResponseResponseTypeFromMenu(type: string): void { + this.switchToResponseTab(); + this.openResponseTypeMenu(); + cy.xpath(this.locators.responseTypeMenuItem(type)).realClick(); } public switchResponseType(type: string): void { this.switchToResponseTab(); - cy.xpath(this.getResponseTypeSelector(type)).click({ force: true }); + cy.xpath(this.locators.responseType(type)).click({ force: true }); } // TODO: Implement this method when response UI is ready diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index 1a6190fefe4..28cf92cdd29 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -67,30 +67,6 @@ interface Props { actionName: string; } -// // Move bind data button to the new header component & change its title in the process. (design) -// // Add query name .run as prefix for the header row. This uses code variant of ads text component. (design) -// // Move number of records to the new header component. -// // * Remove paddings in tabs -// // * Acquire query duration & HTTP status and add request execution time to redux. -// // * On hover of query name and number of records, meta data of api run (outlined above) should show up as tooltip. (design) -// // * Change result type from segmented control to a FAB with dropdown menu. -// // * Change loading state button/spinner/spacing. (design) -// // * Change the empty state text and button alignment. (design) -// // * Change segmented control naming -// // * Update table appearance. -// // * Table columns have a fixed width of 170px now, this needs to be updated to min-width. -// // * Fix FAB hover issue. -// // * Account for scrollbars that are always shown. -// // * Add status bar to error state, hide bind to UI button. -// // * Add dashed underline for status bar fn name & meta. -// * Update REST API -// * Update GQL API -// * Fix Cypress tests related to result type control change. - -// ? Make table stretchable - this is not easily accomplishable with the current table component, need to calculate column width manually. -// // ? Query name is a bold Text variant that is of weight 500 in ADS -// // ? Query name/info font size is larger in FE component - 14px vs 13px in Figma - export const QueryResponseTab = (props: Props) => { const { actionName, @@ -421,18 +397,6 @@ export const QueryResponseTab = (props: Props) => { onMouseLeave={setIsNotHovered} > - {/* { - setSelectedControl(value); - onResponseTabSelect(value); - }} - options={segmentedControlOptions} - value={selectedControl} - /> */} - { {contentTypeOptions.map(({ label, value }) => ( Date: Tue, 19 Nov 2024 16:50:25 +0300 Subject: [PATCH 16/26] chore: test fixes --- .../BugTests/Binding_Bug28287_Spec.ts | 2 +- .../ServerSide/QueryPane/S3_1_spec.js | 3 +-- .../cypress/support/Pages/DataSources.ts | 8 +++--- .../support/Pages/IDE/BottomPane/Response.ts | 26 ++++++++++++------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts b/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts index 04fef39098d..3f92ef47c03 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/BugTests/Binding_Bug28287_Spec.ts @@ -47,7 +47,7 @@ describe( BottomPane.response.switchToResponseTab(); BottomPane.response.openResponseTypeMenu(); agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeMenuItem("TABLE"), + BottomPane.response.locators.responseTypeMenuItem("TABLE"), ); }); }); diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js index 9a0797ac913..3a1057df353 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js @@ -191,8 +191,7 @@ describe( cy.typeValueNValidate(fileName, formControls.s3ListPrefix); dataSources.RunQuery({ toValidateResponse: false }); - BottomPane.response.switchResponseType("TABLE"); - BottomPane.response.switchResponseType("JSON"); + BottomPane.response.selectResponseResponseTypeFromMenu("JSON"); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.isExecutionSuccess).to.eq(true); diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index 63d82b767cc..0ceb2d217af 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -1162,14 +1162,16 @@ export class DataSources { BottomPane.response.openResponseTypeMenu(); this.agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeMenuItem("TABLE"), + BottomPane.response.locators.responseTypeMenuItem("TABLE"), ); this.agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeMenuItem("JSON"), + BottomPane.response.locators.responseTypeMenuItem("JSON"), ); this.agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeMenuItem("RAW"), + BottomPane.response.locators.responseTypeMenuItem("RAW"), ); + + BottomPane.response.closeResponseTypeMenu(); } BottomPane.response.validateRecordCount(expectedRecordsCount); } diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index 46fcc4802ef..2fdf4c7ba73 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -1,23 +1,30 @@ class Response { - private locators = { - responseTab: "//button[@data-testid='t--tab-RESPONSE_TAB']", + public locators = { + responseTab: "[data-testid='t--tab-RESPONSE_TAB']", responseDataContainer: "[data-testid='t--query-response-data-container']", responseTypeMenuTrigger: "[data-testid='t--query-response-type-trigger']", + + /** @deprecated */ responseType(type: string): string { return `//div[@data-testid='t--response-tab-segmented-control']//span[text()='${type}']`; }, - responseTypeMenuItem(type: string): string { - return `//div[@data-testid='t--query-response-type-menu-item' and @data-value='${type}']`; + + responseTypeMenuItem(type: string) { + return `div[data-testid="t--query-response-type-menu-item"][data-value="${type}"]`; }, }; /** @deprecated */ public getResponseTypeSelector = this.locators.responseType; - public getResponseTypeMenuItem = this.locators.responseTypeMenuItem; + /** @deprecated */ + public switchResponseType(type: string): void { + this.switchToResponseTab(); + cy.xpath(this.locators.responseType(type)).click({ force: true }); + } public switchToResponseTab(): void { - cy.xpath(this.locators.responseTab).click({ force: true }); + cy.get(this.locators.responseTab).click({ force: true }); } public openResponseTypeMenu() { @@ -28,12 +35,11 @@ class Response { public selectResponseResponseTypeFromMenu(type: string): void { this.switchToResponseTab(); this.openResponseTypeMenu(); - cy.xpath(this.locators.responseTypeMenuItem(type)).realClick(); + cy.get(this.locators.responseTypeMenuItem(type)).realClick(); } - public switchResponseType(type: string): void { - this.switchToResponseTab(); - cy.xpath(this.locators.responseType(type)).click({ force: true }); + public closeResponseTypeMenu() { + cy.get("body").realClick({ x: 0, y: 0 }); } // TODO: Implement this method when response UI is ready From 66f044b52a025425ce978ae98ef2bbf1e5088197 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Tue, 19 Nov 2024 22:29:13 +0300 Subject: [PATCH 17/26] test: add record count test --- app/client/cypress/support/Pages/DataSources.ts | 2 +- .../support/Pages/IDE/BottomPane/Response.ts | 14 +++++++++----- .../QueryResponseTab/QueryResponseTab.tsx | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index 0ceb2d217af..afa7bea96c5 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -1150,7 +1150,6 @@ export class DataSources { BottomPane.response.getResponseTypeSelector("RAW"), ); } - BottomPane.response.validateRecordCount(expectedRecordsCount); } public runQueryAndVerifyResponseViews( @@ -1173,6 +1172,7 @@ export class DataSources { BottomPane.response.closeResponseTypeMenu(); } + BottomPane.response.validateRecordCount(expectedRecordsCount); } diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index 2fdf4c7ba73..b858eaa4701 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -3,6 +3,7 @@ class Response { responseTab: "[data-testid='t--tab-RESPONSE_TAB']", responseDataContainer: "[data-testid='t--query-response-data-container']", responseTypeMenuTrigger: "[data-testid='t--query-response-type-trigger']", + responseRecordCount: "[data-testid='t--query-response-record-count']", /** @deprecated */ responseType(type: string): string { @@ -10,7 +11,7 @@ class Response { }, responseTypeMenuItem(type: string) { - return `div[data-testid="t--query-response-type-menu-item"][data-value="${type}"]`; + return `[data-testid="t--query-response-type-menu-item"][data-value="${type}"]`; }, }; @@ -29,7 +30,7 @@ class Response { public openResponseTypeMenu() { cy.get(this.locators.responseDataContainer).realHover(); - cy.get(this.locators.responseTypeMenuTrigger).realClick(); + cy.get(this.locators.responseTypeMenuTrigger).click({ force: true }); } public selectResponseResponseTypeFromMenu(type: string): void { @@ -39,11 +40,14 @@ class Response { } public closeResponseTypeMenu() { - cy.get("body").realClick({ x: 0, y: 0 }); + cy.get(this.locators.responseTypeMenuTrigger).realClick(); } - // TODO: Implement this method when response UI is ready - public validateRecordCount(count: number): void {} + public validateRecordCount(count: number): void { + cy.get(this.locators.responseRecordCount) + .invoke("text") + .should("match", new RegExp(`^${count}\\b`)); + } } export { Response }; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index 28cf92cdd29..a1fb280d2dc 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -408,6 +408,7 @@ export const QueryResponseTab = (props: Props) => { {`${output.length} record${output.length > 1 ? "s" : ""}`} From 9a4fbbe93d4d35554af9a07de2aa401b1fc01f08 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 20 Nov 2024 17:20:31 +0300 Subject: [PATCH 18/26] fix: added default record count of 1 for cud operations --- .../components/QueryResponseTab/QueryResponseTab.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx index a1fb280d2dc..2f2c5942786 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab/QueryResponseTab.tsx @@ -157,6 +157,8 @@ export const QueryResponseTab = (props: Props) => { } } + const recordCount = output?.length ?? 1; + const responseBodyTabs = responseDataTypes && responseDataTypes.map((dataType, index) => { @@ -280,6 +282,10 @@ export const QueryResponseTab = (props: Props) => { } }); + const handleJsonWrapperClick = useEventCallback( + (e: React.MouseEvent) => e.stopPropagation(), + ); + if (isRunning) { return ( @@ -367,7 +373,7 @@ export const QueryResponseTab = (props: Props) => { {actionResponse && actionResponse.request && ( e.stopPropagation()} + onClick={handleJsonWrapperClick} > @@ -410,7 +416,7 @@ export const QueryResponseTab = (props: Props) => { $hasTooltip data-testid="t--query-response-record-count" kind="code" - >{`${output.length} record${output.length > 1 ? "s" : ""}`} + >{`${recordCount} record${recordCount > 1 ? "s" : ""}`} Date: Wed, 20 Nov 2024 17:43:32 +0300 Subject: [PATCH 19/26] feat: add record checking & improve content type checking --- .../Datasources/Redis_Basic_Spec.ts | 20 +-- .../ServerSide/GenerateCRUD/MySQL2_Spec.ts | 2 +- .../ServerSide/GenerateCRUD/Postgres2_Spec.ts | 2 +- .../Postgres_DataTypes/UUID_Spec.ts | 6 +- .../ServerSide/QueryPane/Mongo1_spec.ts | 144 +++++++++++------- .../ServerSide/QueryPane/S3_1_spec.js | 6 +- .../Sanity/Datasources/Arango_Basic_Spec.ts | 6 +- .../e2e/Sanity/Datasources/MockDBs_Spec.ts | 18 ++- .../cypress/support/Pages/DataSources.ts | 37 +++-- .../support/Pages/IDE/BottomPane/Response.ts | 57 ++++++- 10 files changed, 198 insertions(+), 100 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts index bab4634d5b4..7e833e24bcb 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts @@ -30,32 +30,32 @@ describe( //Add HSET dataSources.CreateQueryAfterDSSaved(); dataSources.EnterQuery(hSetReceipe); - dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(); //verify all views are returned! dataSources.AssertQueryTableResponse(0, "4"); //Success response for 4 keys inserted via above HSET! //Read only one key from above HSET dataSources.EnterQuery(hGetKeys); - dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(); //verify all views are returned! dataSources.AssertQueryTableResponse(0, "Vegetable Stir Fry"); //Read more than one key from above HSET dataSources.EnterQuery(hMGet); - dataSources.runQueryAndVerifyResponseViews(2); + dataSources.runQueryAndVerifyResponseViews({ count: 2 }); //verify all views are returned! dataSources.AssertQueryTableResponse(0, "easy"); dataSources.AssertQueryTableResponse(1, "Vegetable Stir Fry"); //Update key value in HSET dataSources.EnterQuery(hUpdate); - dataSources.runQueryAndVerifyResponseViews(1); //verify all views are returned! + dataSources.runQueryAndVerifyResponseViews(); //verify all views are returned! //validate updated key dataSources.EnterQuery(getUpdatedKey); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryTableResponse(0, "medium"); //Get All keys from HSET dataSources.EnterQuery(getAll); - dataSources.runQueryAndVerifyResponseViews(8); //4 keys, 4 values + dataSources.runQueryAndVerifyResponseViews({ count: 8 }); //4 keys, 4 values dataSources.ReadQueryTableResponse(0).then(($cellData: any) => { expect($cellData).to.be.oneOf([ "name", @@ -70,11 +70,11 @@ describe( //Ading one more key/value to HSET dataSources.EnterQuery(addNewKeyValue); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); //Verify new key/value also added to HSET dataSources.EnterQuery(getAll); - dataSources.runQueryAndVerifyResponseViews(10); //5 keys, 5 values + dataSources.runQueryAndVerifyResponseViews({ count: 10 }); //5 keys, 5 values dataSources.ReadQueryTableResponse(0).then(($cellData: any) => { expect($cellData).to.be.oneOf([ "name", @@ -87,11 +87,11 @@ describe( //Deleting the Hash key dataSources.EnterQuery(deletehKey); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); //Verify Deletion is success dataSources.EnterQuery(hGetKeys); - dataSources.runQueryAndVerifyResponseViews(); //5 keys, 5 values + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryTableResponse(0, "null"); // Delete the query & datasource diff --git a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts index 6fa93253ff7..fdce0f8f1b4 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/MySQL2_Spec.ts @@ -79,7 +79,7 @@ describe( it("2. Validate Select record from Postgress datasource & verify query response", () => { dataSources.CreateQueryForDS(dsName, "SELECT * FROM Stores LIMIT 10"); - dataSources.runQueryAndVerifyResponseViews(10); + dataSources.runQueryAndVerifyResponseViews({ count: 10 }); dataSources.AssertQueryTableResponse(5, "2112"); dataSources.AssertQueryTableResponse(6, "Mike's Liquors"); // Commenting this deletion of query to make the generate crud work on the new page instead of the current page diff --git a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts index 3c827205fa1..1124d1235f0 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/GenerateCRUD/Postgres2_Spec.ts @@ -70,7 +70,7 @@ describe( "public.vessels", "Select", ); - dataSources.runQueryAndVerifyResponseViews(10); + dataSources.runQueryAndVerifyResponseViews({ count: 10 }); dataSources.AssertQueryTableResponse(0, "371681"); dataSources.AssertQueryTableResponse(6, "Passenger"); agHelper.ActionContextMenuWithInPane({ diff --git a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts index bcccd2c15cc..94425b929e3 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/UUID_Spec.ts @@ -259,7 +259,7 @@ describe( //Validating use of extention query = `CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pgcrypto"`; dataSources.CreateQueryForDS(dsName, query, "verifyUUIDFunctions"); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); @@ -297,7 +297,7 @@ describe( //Validating Addition of new column taking default value form package method query = `ALTER TABLE uuidtype ADD COLUMN newUUID uuid DEFAULT uuid_generate_v4();`; dataSources.EnterQuery(query); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); @@ -314,7 +314,7 @@ describe( //Validating altering the new column default value to generate id from pgcrypto package query = `ALTER TABLE uuidtype ALTER COLUMN newUUID SET DEFAULT gen_random_uuid();`; dataSources.EnterQuery(query); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryResponseHeaders(["affectedRows"]); dataSources.ReadQueryTableResponse(0).then(($cellData) => { expect($cellData).to.eq("0"); diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts index 49f058d0e52..6583c23c847 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Mongo1_spec.ts @@ -16,7 +16,6 @@ import EditorNavigation, { EntityType, } from "../../../../support/Pages/EditorNavigation"; import PageList from "../../../../support/Pages/PageList"; -import BottomPane from "../../../../support/Pages/IDE/BottomPane"; let dsName: any; @@ -333,7 +332,11 @@ describe( "Find", ); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); - dataSources.runQueryAndVerifyResponseViews(1, false); + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -352,7 +355,11 @@ describe( directInput: false, inputFieldName: "Query", }); - dataSources.runQueryAndVerifyResponseViews(1, false); + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -430,12 +437,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.n)), ).to.eq(3); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -467,12 +475,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.nModified)), ).to.eq(0); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -514,12 +523,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.nModified)), ).to.eq(2); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -556,12 +566,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.nModified)), ).to.eq(1); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -587,12 +598,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.n)), ).to.eq(0); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -620,12 +632,13 @@ describe( parseInt(JSON.stringify(resObj.response.body.data.body.n)), ).to.eq(1); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -657,12 +670,13 @@ describe( 2, ); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -682,12 +696,13 @@ describe( 7, ); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -719,12 +734,13 @@ describe( JSON.parse(JSON.stringify(resObj.response.body.data.body.values[1])), ).to.eql("51e062189c6ae665454e301d"); }); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("JSON"), - ); - agHelper.AssertElementVisibility( - BottomPane.response.getResponseTypeSelector("RAW"), - ); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -738,7 +754,12 @@ describe( "Aggregate", ); dataSources.ValidateNSelectDropdown("Command", "Aggregate"); - dataSources.runQueryAndVerifyResponseViews(7, false); + + dataSources.runQueryAndVerifyResponseViews({ + count: 7, + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, @@ -899,7 +920,12 @@ describe( "Find", ); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); - dataSources.runQueryAndVerifyResponseViews(4, false); + + dataSources.runQueryAndVerifyResponseViews({ + count: 4, + responseTypes: ["JSON", "RAW"], + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js index 3a1057df353..4cd40d69e78 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/S3_1_spec.js @@ -77,7 +77,11 @@ describe( "List files", ); - dataSources.runQueryAndVerifyResponseViews(100); + dataSources.runQueryAndVerifyResponseViews({ + count: 100, + operator: "gte", + }); + agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, diff --git a/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts index 84e8546916a..5fc5d0bc4c0 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/Arango_Basic_Spec.ts @@ -232,7 +232,7 @@ if (CURRENT_REPO == REPO.CE) { FILTER place.type == "Natural" RETURN { country: doc.country, name: place.name }`; dataSources.EnterQuery(query); - dataSources.runQueryAndVerifyResponseViews(5); //Verify all records are filtered + dataSources.runQueryAndVerifyResponseViews({ count: 5 }); //Verify all records are filtered dataSources.AssertQueryTableResponse(0, "Japan"); dataSources.AssertQueryTableResponse(1, "Mount Fuji"); dataSources.AssertQueryTableResponse(6, "Brazil"); //Widget binding is verified here @@ -276,7 +276,7 @@ if (CURRENT_REPO == REPO.CE) { FILTER document._key == "1" RETURN document`; dataSources.EnterQuery(query); - dataSources.runQueryAndVerifyResponseViews(1); + dataSources.runQueryAndVerifyResponseViews(); dataSources.AssertQueryTableResponse(3, "Australia"); //Delete record from collection @@ -287,7 +287,7 @@ if (CURRENT_REPO == REPO.CE) { ); query = `REMOVE "1" in ${collectionName}`; dataSources.EnterQuery(query); - dataSources.runQueryAndVerifyResponseViews(1); //Removing Australia + dataSources.runQueryAndVerifyResponseViews(); //Removing Australia //Verify no records return for the deleted key query = `FOR document IN ${collectionName} diff --git a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts index 5da58d57cca..11df7b8477e 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/MockDBs_Spec.ts @@ -42,7 +42,11 @@ describe( 'SELECT * FROM public."users" LIMIT 10;', ); - dataSources.runQueryAndVerifyResponseViews(); //minimum 1 rows are expected + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + }); //minimum 1 rows are expected + AppSidebar.navigate(AppSidebarButton.Data); dataSources .getDatasourceListItemDescription(mockDBName) @@ -57,7 +61,11 @@ describe( expect(interception.request.body.source).to.equal("SELF"); }); - dataSources.runQueryAndVerifyResponseViews(); //minimum 1 rows are expected + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + }); //minimum 1 rows are expected + AppSidebar.navigate(AppSidebarButton.Data); dataSources .getDatasourceListItemDescription(mockDBName) @@ -81,6 +89,12 @@ describe( assertHelper.AssertNetworkStatus("@trigger"); dataSources.ValidateNSelectDropdown("Command", "Find document(s)"); + + dataSources.runQueryAndVerifyResponseViews({ + count: 1, + operator: "gte", + responseTypes: ["JSON", "RAW"], + }); }); }); }, diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index afa7bea96c5..4b9329d561e 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -1152,28 +1152,33 @@ export class DataSources { } } - public runQueryAndVerifyResponseViews( - expectedRecordsCount = 1, - tableCheck = true, - ) { + public runQueryAndVerifyResponseViews({ + count = 1, + operator = "eq", + responseTypes = ["TABLE", "JSON", "RAW"], + }: { + count?: number; + operator?: Parameters< + typeof BottomPane.response.validateRecordCount + >[0]["operator"]; + responseTypes?: ("TABLE" | "JSON" | "RAW")[]; + } = {}) { this.RunQuery(); - if (tableCheck) { - BottomPane.response.openResponseTypeMenu(); + BottomPane.response.openResponseTypeMenu(); + + responseTypes.forEach((responseType) => { this.agHelper.AssertElementVisibility( - BottomPane.response.locators.responseTypeMenuItem("TABLE"), - ); - this.agHelper.AssertElementVisibility( - BottomPane.response.locators.responseTypeMenuItem("JSON"), - ); - this.agHelper.AssertElementVisibility( - BottomPane.response.locators.responseTypeMenuItem("RAW"), + BottomPane.response.locators.responseTypeMenuItem(responseType), ); + }); - BottomPane.response.closeResponseTypeMenu(); - } + BottomPane.response.closeResponseTypeMenu(); - BottomPane.response.validateRecordCount(expectedRecordsCount); + BottomPane.response.validateRecordCount({ + count, + operator, + }); } public CreateDataSource( diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index b858eaa4701..bba87779850 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -1,3 +1,10 @@ +type ComparisonOperator = "eq" | "gt" | "gte" | "lt" | "lte"; + +interface ValidationParams { + count: number; + operator: ComparisonOperator; +} + class Response { public locators = { responseTab: "[data-testid='t--tab-RESPONSE_TAB']", @@ -15,10 +22,10 @@ class Response { }, }; - /** @deprecated */ + /** @deprecated: method will be deleted when segmented control in response pane is replaced */ public getResponseTypeSelector = this.locators.responseType; - /** @deprecated */ + /** @deprecated: method will be deleted when segmented control in response pane is replaced */ public switchResponseType(type: string): void { this.switchToResponseTab(); cy.xpath(this.locators.responseType(type)).click({ force: true }); @@ -43,10 +50,52 @@ class Response { cy.get(this.locators.responseTypeMenuTrigger).realClick(); } - public validateRecordCount(count: number): void { + public validateRecordCount({ count, operator }: ValidationParams): void { cy.get(this.locators.responseRecordCount) .invoke("text") - .should("match", new RegExp(`^${count}\\b`)); + .then((text) => { + const extractedCount = parseInt(text.match(/\d+/)?.[0] || "0", 10); + + switch (operator) { + case "eq": + if (extractedCount !== count) { + throw new Error( + `Expected count to equal ${count}, but got ${extractedCount}`, + ); + } + break; + case "gt": + if (extractedCount <= count) { + throw new Error( + `Expected count > ${count}, but got ${extractedCount}`, + ); + } + break; + case "gte": + if (extractedCount < count) { + throw new Error( + `Expected count >= ${count}, but got ${extractedCount}`, + ); + } + break; + case "lt": + if (extractedCount >= count) { + throw new Error( + `Expected count < ${count}, but got ${extractedCount}`, + ); + } + break; + case "lte": + if (extractedCount > count) { + throw new Error( + `Expected count <= ${count}, but got ${extractedCount}`, + ); + } + break; + default: + throw new Error(`Invalid comparison operator: ${operator}`); + } + }); } } From fe16e7d57a5b36c98a39eff80a4be0a2495af34f Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 20 Nov 2024 21:51:20 +0300 Subject: [PATCH 20/26] chore: fix unit tests --- .../src/components/editorComponents/JSResponseView.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/client/src/components/editorComponents/JSResponseView.test.tsx b/app/client/src/components/editorComponents/JSResponseView.test.tsx index 5d3e177cc17..b873c110660 100644 --- a/app/client/src/components/editorComponents/JSResponseView.test.tsx +++ b/app/client/src/components/editorComponents/JSResponseView.test.tsx @@ -12,7 +12,7 @@ import { EditorViewMode } from "ee/entities/IDE/constants"; import type { JSCollectionData } from "ee/reducers/entityReducers/jsActionsReducer"; import { PluginType } from "entities/Action"; import "@testing-library/jest-dom/extend-expect"; -import { EMPTY_RESPONSE_LAST_HALF } from "ee/constants/messages"; +import { EMPTY_RESPONSE_RUN } from "ee/constants/messages"; import { DEBUGGER_TAB_KEYS } from "./Debugger/constants"; jest.mock("ee/utils/actionExecutionUtils"); @@ -116,7 +116,7 @@ describe("JSResponseView", () => { , ); - expect(getByText(EMPTY_RESPONSE_LAST_HALF())).toBeInTheDocument(); + expect(getByText(EMPTY_RESPONSE_RUN())).toBeInTheDocument(); }); it("should render correctly when isBrowserExecutionAllowed returns false", () => { @@ -144,7 +144,7 @@ describe("JSResponseView", () => { , ); // nothing should be rendered here since the implementation for component is in EE code - expect(queryByText(document.body, EMPTY_RESPONSE_LAST_HALF())).toBeNull(); + expect(queryByText(document.body, EMPTY_RESPONSE_RUN())).toBeNull(); }); it("the container should have class select-text to enable the selection of text for user", () => { From 7ce1bd4a55d3568ab037de6a7287a760e48eba72 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 20 Nov 2024 21:51:56 +0300 Subject: [PATCH 21/26] chore: remove detached tests --- .../QueryEditor/QueryDebuggerTabs.test.tsx | 84 +------------------ 1 file changed, 1 insertion(+), 83 deletions(-) diff --git a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.test.tsx b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.test.tsx index 047147748af..603fa158132 100644 --- a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.test.tsx +++ b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.test.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { render, screen } from "@testing-library/react"; +import { render } from "@testing-library/react"; import configureStore from "redux-mock-store"; import { Provider } from "react-redux"; import { ThemeProvider } from "styled-components"; @@ -10,36 +10,9 @@ import { EditorViewMode } from "ee/entities/IDE/constants"; import "@testing-library/jest-dom/extend-expect"; import QueryDebuggerTabs from "./QueryDebuggerTabs"; import { ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils"; -import type { ActionResponse } from "api/ActionAPI"; const mockStore = configureStore([]); -const mockSuccessResponse: ActionResponse = { - body: ["Record 1", "Record 2"], - statusCode: "200", - dataTypes: [], - duration: "3000", - size: "200", - isExecutionSuccess: true, - headers: { - "Content-Type": ["application/json"], - "Cache-Control": ["no-cache"], - }, -}; - -const mockFailedResponse: ActionResponse = { - body: [{ response: "Failed" }], - statusCode: "200", - dataTypes: [], - duration: "3000", - size: "200", - isExecutionSuccess: false, - headers: { - "Content-Type": ["application/json"], - "Cache-Control": ["no-cache"], - }, -}; - const storeState = { ...unitTestBaseMockStore, evaluations: { @@ -113,59 +86,4 @@ describe("ApiResponseView", () => { ?.classList.contains("select-text"), ).toBe(true); }); - it("should show record count as result if the query response returns records", () => { - render( - - - - {}} - /> - - - , - ); - - const expectedResultText = "Result: 2 Records"; - const resultTextElement = screen.getByTestId("result-text"); - - expect(resultTextElement).toBeInTheDocument(); - expect(resultTextElement?.textContent).toContain(expectedResultText); - }); - - it("should show error as result if the query response returns the error", () => { - render( - - - - {}} - /> - - - , - ); - - const expectedResultText = "Result: Error"; - const resultTextElement = screen.getByTestId("result-text"); - - expect(resultTextElement).toBeInTheDocument(); - expect(resultTextElement?.textContent).toContain(expectedResultText); - }); }); From 97ada3df09b12fbf2b4e08e3a96c3c9e8e7a27aa Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Wed, 20 Nov 2024 21:52:41 +0300 Subject: [PATCH 22/26] chore: change record count params --- .../ServerSide/QueryPane/Querypane_Mongo_Spec.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js index f1f7adcb057..6ef54ca0b94 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js @@ -71,7 +71,7 @@ describe( dataSources.EnterQuery(`{"find": "listingAndReviews","limit": 10}`); agHelper.FocusElement(locators._codeMirrorTextArea); dataSources.RunQuery(); - BottomPane.response.validateRecordCount(10); + BottomPane.response.validateRecordCount({ count: 10 }); cy.deleteQueryUsingContext(); }); @@ -93,7 +93,7 @@ describe( fieldValue: "listingAndReviews", }); dataSources.RunQuery(); - BottomPane.response.validateRecordCount(10); + BottomPane.response.validateRecordCount({ count: 10 }); agHelper.EnterValue("{beds : {$lte: 2}}", { propFieldName: "", @@ -101,7 +101,7 @@ describe( inputFieldName: "Query", }); dataSources.RunQuery(); - BottomPane.response.validateRecordCount(10); + BottomPane.response.validateRecordCount({ count: 10 }); agHelper.EnterValue("{number_of_reviews: -1}", { propFieldName: "", @@ -109,7 +109,7 @@ describe( inputFieldName: "Sort", }); //sort descending dataSources.RunQuery(); - BottomPane.response.validateRecordCount(10); + BottomPane.response.validateRecordCount({ count: 10 }); agHelper.EnterValue("{house_rules: 1, description:1}", { propFieldName: "", @@ -131,7 +131,7 @@ describe( "Response is not as expected for Find commmand with multiple conditions", ); }); - BottomPane.response.validateRecordCount(5); + BottomPane.response.validateRecordCount({ count: 10 }); agHelper.EnterValue("2", { propFieldName: "", @@ -145,7 +145,7 @@ describe( "Response is not as expected for Find commmand with multiple conditions", ); }); - BottomPane.response.validateRecordCount(5); + BottomPane.response.validateRecordCount({ count: 10 }); cy.deleteQueryUsingContext(); }); @@ -433,7 +433,7 @@ describe( ); dataSources.RunQuery(); - BottomPane.response.validateRecordCount(3); + BottomPane.response.validateRecordCount({ count: 10 }); dataSources.AssertTableInVirtuosoList(datasourceName, "NonAsciiTest"); From 9d827b756fa89f33f3e06198bb278f2badc371e2 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Thu, 21 Nov 2024 10:21:55 +0300 Subject: [PATCH 23/26] fix: make operator optional & add a default --- .../cypress/support/Pages/IDE/BottomPane/Response.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index bba87779850..fc265863efe 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -2,7 +2,7 @@ type ComparisonOperator = "eq" | "gt" | "gte" | "lt" | "lte"; interface ValidationParams { count: number; - operator: ComparisonOperator; + operator?: ComparisonOperator; } class Response { @@ -50,7 +50,10 @@ class Response { cy.get(this.locators.responseTypeMenuTrigger).realClick(); } - public validateRecordCount({ count, operator }: ValidationParams): void { + public validateRecordCount({ + count, + operator = "eq", + }: ValidationParams): void { cy.get(this.locators.responseRecordCount) .invoke("text") .then((text) => { From 2f3e880b783b2ffbf29dd2b01c5226ad46af5091 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 21 Nov 2024 10:49:02 +0300 Subject: [PATCH 24/26] chore: update conditions Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../support/Pages/IDE/BottomPane/Response.ts | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts index fc265863efe..485559535a7 100644 --- a/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts +++ b/app/client/cypress/support/Pages/IDE/BottomPane/Response.ts @@ -61,39 +61,19 @@ class Response { switch (operator) { case "eq": - if (extractedCount !== count) { - throw new Error( - `Expected count to equal ${count}, but got ${extractedCount}`, - ); - } + expect(extractedCount).to.equal(count); break; case "gt": - if (extractedCount <= count) { - throw new Error( - `Expected count > ${count}, but got ${extractedCount}`, - ); - } + expect(extractedCount).to.be.greaterThan(count); break; case "gte": - if (extractedCount < count) { - throw new Error( - `Expected count >= ${count}, but got ${extractedCount}`, - ); - } + expect(extractedCount).to.be.at.least(count); break; case "lt": - if (extractedCount >= count) { - throw new Error( - `Expected count < ${count}, but got ${extractedCount}`, - ); - } + expect(extractedCount).to.be.lessThan(count); break; case "lte": - if (extractedCount > count) { - throw new Error( - `Expected count <= ${count}, but got ${extractedCount}`, - ); - } + expect(extractedCount).to.be.at.most(count); break; default: throw new Error(`Invalid comparison operator: ${operator}`); From 3f1d3f25cbef8a8c2094a1cd9b06532a56b347fc Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Thu, 21 Nov 2024 17:51:43 +0300 Subject: [PATCH 25/26] chore: update message --- .../QueryPane/Querypane_Mongo_Spec.js | 434 +++++++++--------- app/client/src/ce/constants/messages.ts | 2 +- 2 files changed, 218 insertions(+), 218 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js index 6ef54ca0b94..689d4acc97a 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js @@ -71,230 +71,230 @@ describe( dataSources.EnterQuery(`{"find": "listingAndReviews","limit": 10}`); agHelper.FocusElement(locators._codeMirrorTextArea); dataSources.RunQuery(); - BottomPane.response.validateRecordCount({ count: 10 }); + BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); cy.deleteQueryUsingContext(); }); - it("2. Validate Find documents command & Run and then delete the query", function () { - dataSources.CreateQueryForDS(datasourceName); - dataSources.SetQueryTimeout(20000); - - //cy.xpath(queryLocators.findDocs).should("exist"); //Verifying update is success or below line - //cy.expect(queryLocators.findDocs).to.exist; - - assertHelper.AssertNetworkStatus("@trigger"); - cy.ValidateAndSelectDropdownOption( - formControls.commandDropdown, - "Find document(s)", - ); - - dataSources.EnterJSContext({ - fieldLabel: "Collection", - fieldValue: "listingAndReviews", - }); - dataSources.RunQuery(); - BottomPane.response.validateRecordCount({ count: 10 }); - - agHelper.EnterValue("{beds : {$lte: 2}}", { - propFieldName: "", - directInput: false, - inputFieldName: "Query", - }); - dataSources.RunQuery(); - BottomPane.response.validateRecordCount({ count: 10 }); - - agHelper.EnterValue("{number_of_reviews: -1}", { - propFieldName: "", - directInput: false, - inputFieldName: "Sort", - }); //sort descending - dataSources.RunQuery(); - BottomPane.response.validateRecordCount({ count: 10 }); - - agHelper.EnterValue("{house_rules: 1, description:1}", { - propFieldName: "", - directInput: false, - inputFieldName: "Projection", - }); //Projection field - dataSources.RunQuery(); - - agHelper.EnterValue("5", { - propFieldName: "", - directInput: false, - inputFieldName: "Limit", - }); //Limit field - - dataSources.RunQuery({ toValidateResponse: false }); - cy.wait("@postExecute").then(({ response }) => { - expect(response.body.data.body[0].description).to.contains( - "The ideal apartment to visit the magnificent city of Porto and the northern region of Portugal, with family or with a couple of friends", - "Response is not as expected for Find commmand with multiple conditions", - ); - }); - BottomPane.response.validateRecordCount({ count: 10 }); - - agHelper.EnterValue("2", { - propFieldName: "", - directInput: false, - inputFieldName: "Skip", - }); - dataSources.RunQuery({ toValidateResponse: false }); - cy.wait("@postExecute").then(({ response }) => { - expect(response.body.data.body[0].description).to.contains( - "My place is close to the beach, family-friendly activities, great views, and a short drive to art and culture, and restaurants and dining", - "Response is not as expected for Find commmand with multiple conditions", - ); - }); - BottomPane.response.validateRecordCount({ count: 10 }); - cy.deleteQueryUsingContext(); - }); - - it("3. Validate Count command & Run and then delete the query", function () { - dataSources.CreateQueryForDS(datasourceName); - assertHelper.AssertNetworkStatus("@trigger"); - cy.ValidateAndSelectDropdownOption( - formControls.commandDropdown, - "Find document(s)", - "Count", - ); - dataSources.EnterJSContext({ - fieldLabel: "Collection", - fieldValue: "listingAndReviews", - }); - dataSources.RunQuery(); - agHelper.EnterValue("{guests_included : {$gte: 2}}", { - propFieldName: "", - directInput: false, - inputFieldName: "Query", - }); - dataSources.RunQuery({ toValidateResponse: false }); - cy.wait("@postExecute").then(({ response }) => { - expect(response.body.data.body.n).to.be.above( - 0, - "Response is not as expected for Count commmand", - ); - }); - cy.deleteQueryUsingContext(); - }); - - it("4. Validate Distinct command & Run and then delete the query", function () { - dataSources.CreateQueryForDS(datasourceName); - assertHelper.AssertNetworkStatus("@trigger"); - cy.ValidateAndSelectDropdownOption( - formControls.commandDropdown, - "Find document(s)", - "Distinct", - ); - dataSources.EnterJSContext({ - fieldLabel: "Collection", - fieldValue: "listingAndReviews", - }); - agHelper.EnterValue("{price : {$gte: 100}}", { - propFieldName: "", - directInput: false, - inputFieldName: "Query", - }); - agHelper.EnterValue("property_type", { - propFieldName: "", - directInput: false, - inputFieldName: "Key", - }); - dataSources.RunQuery({ toValidateResponse: false }); - cy.wait("@postExecute").then(({ response }) => { - expect(response.body.data.body.values[0]).to.eq( - "Aparthotel", - "Response is not as expected for Distint commmand", - ); - }); - cy.deleteQueryUsingContext(); - }); - - it("5. Validate Aggregate command & Run and then delete the query", function () { - dataSources.CreateQueryForDS(datasourceName); - assertHelper.AssertNetworkStatus("@trigger"); - cy.ValidateAndSelectDropdownOption( - formControls.commandDropdown, - "Find document(s)", - "Aggregate", - ); - dataSources.EnterJSContext({ - fieldLabel: "Collection", - fieldValue: "listingAndReviews", - }); - agHelper.EnterValue(`[{ $project: { count: { $size:"$amenities" }}}]`, { - propFieldName: "", - directInput: false, - inputFieldName: "Array of pipelines", - }); - - dataSources.RunQuery({ toValidateResponse: false }); - cy.wait("@postExecute").then(({ request, response }) => { - // cy.log(request.method + ": is req.method") - //expect(request.method).to.equal('POST') - expect(response.body.data.body[0].count).to.be.above( - 0, - "Response is not as expected for Aggregate commmand", - ); - // it is good practice to add message to the assertion - // expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') - }); - cy.deleteQueryUsingContext(); - }); - - it("6. Verify generation of NewPage from collection [Select] + Bug 12162", function () { - //Verifying Select from UI - cy.NavigateToDSGeneratePage(datasourceName); - agHelper.Sleep(3000); //giving some time for options to load - cy.get(generatePage.selectTableDropdown).click(); - cy.get(generatePage.dropdownOption) - //.first() - .contains("listingAndReviews") - .scrollIntoView() - .should("be.visible") - .click(); - - cy.get(generatePage.generatePageFormSubmitBtn).click(); - - cy.wait("@replaceLayoutWithCRUDPage").should( - "have.nested.property", - "response.body.responseMeta.status", - 201, - ); - - cy.wait("@getActions"); + // it("2. Validate Find documents command & Run and then delete the query", function () { + // dataSources.CreateQueryForDS(datasourceName); + // dataSources.SetQueryTimeout(20000); + + // //cy.xpath(queryLocators.findDocs).should("exist"); //Verifying update is success or below line + // //cy.expect(queryLocators.findDocs).to.exist; + + // assertHelper.AssertNetworkStatus("@trigger"); + // cy.ValidateAndSelectDropdownOption( + // formControls.commandDropdown, + // "Find document(s)", + // ); + + // dataSources.EnterJSContext({ + // fieldLabel: "Collection", + // fieldValue: "listingAndReviews", + // }); + // dataSources.RunQuery(); + // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); + + // agHelper.EnterValue("{beds : {$lte: 2}}", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Query", + // }); + // dataSources.RunQuery(); + // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); + + // agHelper.EnterValue("{number_of_reviews: -1}", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Sort", + // }); //sort descending + // dataSources.RunQuery(); + // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); + + // agHelper.EnterValue("{house_rules: 1, description:1}", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Projection", + // }); //Projection field + // dataSources.RunQuery(); + + // agHelper.EnterValue("5", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Limit", + // }); //Limit field + + // dataSources.RunQuery({ toValidateResponse: false }); + // cy.wait("@postExecute").then(({ response }) => { + // expect(response.body.data.body[0].description).to.contains( + // "The ideal apartment to visit the magnificent city of Porto and the northern region of Portugal, with family or with a couple of friends", + // "Response is not as expected for Find commmand with multiple conditions", + // ); + // }); + // BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); + + // agHelper.EnterValue("2", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Skip", + // }); + // dataSources.RunQuery({ toValidateResponse: false }); + // cy.wait("@postExecute").then(({ response }) => { + // expect(response.body.data.body[0].description).to.contains( + // "My place is close to the beach, family-friendly activities, great views, and a short drive to art and culture, and restaurants and dining", + // "Response is not as expected for Find commmand with multiple conditions", + // ); + // }); + // BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); + // cy.deleteQueryUsingContext(); + // }); - cy.wait("@postExecute").should( - "have.nested.property", - "response.body.responseMeta.status", - 200, - ); //This verifies the Select on the table, ie page is created fine + // it("3. Validate Count command & Run and then delete the query", function () { + // dataSources.CreateQueryForDS(datasourceName); + // assertHelper.AssertNetworkStatus("@trigger"); + // cy.ValidateAndSelectDropdownOption( + // formControls.commandDropdown, + // "Find document(s)", + // "Count", + // ); + // dataSources.EnterJSContext({ + // fieldLabel: "Collection", + // fieldValue: "listingAndReviews", + // }); + // dataSources.RunQuery(); + // agHelper.EnterValue("{guests_included : {$gte: 2}}", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Query", + // }); + // dataSources.RunQuery({ toValidateResponse: false }); + // cy.wait("@postExecute").then(({ response }) => { + // expect(response.body.data.body.n).to.be.above( + // 0, + // "Response is not as expected for Count commmand", + // ); + // }); + // cy.deleteQueryUsingContext(); + // }); - cy.ClickGotIt(); + // it("4. Validate Distinct command & Run and then delete the query", function () { + // dataSources.CreateQueryForDS(datasourceName); + // assertHelper.AssertNetworkStatus("@trigger"); + // cy.ValidateAndSelectDropdownOption( + // formControls.commandDropdown, + // "Find document(s)", + // "Distinct", + // ); + // dataSources.EnterJSContext({ + // fieldLabel: "Collection", + // fieldValue: "listingAndReviews", + // }); + // agHelper.EnterValue("{price : {$gte: 100}}", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Query", + // }); + // agHelper.EnterValue("property_type", { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Key", + // }); + // dataSources.RunQuery({ toValidateResponse: false }); + // cy.wait("@postExecute").then(({ response }) => { + // expect(response.body.data.body.values[0]).to.eq( + // "Aparthotel", + // "Response is not as expected for Distint commmand", + // ); + // }); + // cy.deleteQueryUsingContext(); + // }); - //Check if table is loaded & CRUD is success + // it("5. Validate Aggregate command & Run and then delete the query", function () { + // dataSources.CreateQueryForDS(datasourceName); + // assertHelper.AssertNetworkStatus("@trigger"); + // cy.ValidateAndSelectDropdownOption( + // formControls.commandDropdown, + // "Find document(s)", + // "Aggregate", + // ); + // dataSources.EnterJSContext({ + // fieldLabel: "Collection", + // fieldValue: "listingAndReviews", + // }); + // agHelper.EnterValue(`[{ $project: { count: { $size:"$amenities" }}}]`, { + // propFieldName: "", + // directInput: false, + // inputFieldName: "Array of pipelines", + // }); + + // dataSources.RunQuery({ toValidateResponse: false }); + // cy.wait("@postExecute").then(({ request, response }) => { + // // cy.log(request.method + ": is req.method") + // //expect(request.method).to.equal('POST') + // expect(response.body.data.body[0].count).to.be.above( + // 0, + // "Response is not as expected for Aggregate commmand", + // ); + // // it is good practice to add message to the assertion + // // expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') + // }); + // cy.deleteQueryUsingContext(); + // }); - cy.get(generatePage.selectedRow).should("exist"); - // cy.get(generatePage.updateBtn) - // .closest("button") - // .then((selector) => { - // cy.get(selector) - // .invoke("attr", "class") - // .then((classes) => { - // cy.log("classes are:" + classes); - // expect(classes).not.contain("bp3-disabled"); - // }); - // }); - }); + // it("6. Verify generation of NewPage from collection [Select] + Bug 12162", function () { + // //Verifying Select from UI + // cy.NavigateToDSGeneratePage(datasourceName); + // agHelper.Sleep(3000); //giving some time for options to load + // cy.get(generatePage.selectTableDropdown).click(); + // cy.get(generatePage.dropdownOption) + // //.first() + // .contains("listingAndReviews") + // .scrollIntoView() + // .should("be.visible") + // .click(); + + // cy.get(generatePage.generatePageFormSubmitBtn).click(); + + // cy.wait("@replaceLayoutWithCRUDPage").should( + // "have.nested.property", + // "response.body.responseMeta.status", + // 201, + // ); + + // cy.wait("@getActions"); + + // cy.wait("@postExecute").should( + // "have.nested.property", + // "response.body.responseMeta.status", + // 200, + // ); //This verifies the Select on the table, ie page is created fine + + // cy.ClickGotIt(); + + // //Check if table is loaded & CRUD is success + + // cy.get(generatePage.selectedRow).should("exist"); + // // cy.get(generatePage.updateBtn) + // // .closest("button") + // // .then((selector) => { + // // cy.get(selector) + // // .invoke("attr", "class") + // // .then((classes) => { + // // cy.log("classes are:" + classes); + // // expect(classes).not.contain("bp3-disabled"); + // // }); + // // }); + // }); - it("7. Validate Deletion of the Newly Created Page", () => { - dataSources.DeleteDatasourceFromWithinDS(datasourceName, 409); - entityExplorer.ActionContextMenuByEntityName({ - entityNameinLeftSidebar: "ListingAndReviews", - action: "Delete", - entityType: entityItems.Page, - }); - EditorNavigation.SelectEntityByName("Page1", EntityType.Page); - }); + // it("7. Validate Deletion of the Newly Created Page", () => { + // dataSources.DeleteDatasourceFromWithinDS(datasourceName, 409); + // entityExplorer.ActionContextMenuByEntityName({ + // entityNameinLeftSidebar: "ListingAndReviews", + // action: "Delete", + // entityType: entityItems.Page, + // }); + // EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + // }); it("8. Bug 7399: Validate Form based & Raw command based templates", function () { let id; @@ -433,7 +433,7 @@ describe( ); dataSources.RunQuery(); - BottomPane.response.validateRecordCount({ count: 10 }); + BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); dataSources.AssertTableInVirtuosoList(datasourceName, "NonAsciiTest"); diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 379b72999a7..b3bcdf349ab 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -569,7 +569,7 @@ export const ACTION_CONFIGURATION_UPDATED = () => "Configuration updated"; export const WIDGET_PROPERTIES_UPDATED = () => "Widget properties were updated"; export const EMPTY_RESPONSE_FIRST_HALF = () => "🙌 Click on"; export const EMPTY_RESPONSE_LAST_HALF = () => "to get a response"; -export const EMPTY_RESPONSE_RUN = () => "Run the query to get a response"; +export const EMPTY_RESPONSE_RUN = () => "Click ‘Run’ to get a response"; export const EMPTY_JS_RESPONSE_LAST_HALF = () => "to view response of selected function"; export const INVALID_EMAIL = () => "Please enter a valid email"; From 7bb20a6aa22de285ec4529296f9319ef461bc052 Mon Sep 17 00:00:00 2001 From: Alex Golovanov Date: Thu, 21 Nov 2024 17:53:04 +0300 Subject: [PATCH 26/26] chore: uncomment --- .../QueryPane/Querypane_Mongo_Spec.js | 430 +++++++++--------- 1 file changed, 215 insertions(+), 215 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js index 689d4acc97a..dcbd88e431d 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/Querypane_Mongo_Spec.js @@ -75,226 +75,226 @@ describe( cy.deleteQueryUsingContext(); }); - // it("2. Validate Find documents command & Run and then delete the query", function () { - // dataSources.CreateQueryForDS(datasourceName); - // dataSources.SetQueryTimeout(20000); - - // //cy.xpath(queryLocators.findDocs).should("exist"); //Verifying update is success or below line - // //cy.expect(queryLocators.findDocs).to.exist; - - // assertHelper.AssertNetworkStatus("@trigger"); - // cy.ValidateAndSelectDropdownOption( - // formControls.commandDropdown, - // "Find document(s)", - // ); - - // dataSources.EnterJSContext({ - // fieldLabel: "Collection", - // fieldValue: "listingAndReviews", - // }); - // dataSources.RunQuery(); - // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); - - // agHelper.EnterValue("{beds : {$lte: 2}}", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Query", - // }); - // dataSources.RunQuery(); - // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); - - // agHelper.EnterValue("{number_of_reviews: -1}", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Sort", - // }); //sort descending - // dataSources.RunQuery(); - // BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); - - // agHelper.EnterValue("{house_rules: 1, description:1}", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Projection", - // }); //Projection field - // dataSources.RunQuery(); - - // agHelper.EnterValue("5", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Limit", - // }); //Limit field - - // dataSources.RunQuery({ toValidateResponse: false }); - // cy.wait("@postExecute").then(({ response }) => { - // expect(response.body.data.body[0].description).to.contains( - // "The ideal apartment to visit the magnificent city of Porto and the northern region of Portugal, with family or with a couple of friends", - // "Response is not as expected for Find commmand with multiple conditions", - // ); - // }); - // BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); - - // agHelper.EnterValue("2", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Skip", - // }); - // dataSources.RunQuery({ toValidateResponse: false }); - // cy.wait("@postExecute").then(({ response }) => { - // expect(response.body.data.body[0].description).to.contains( - // "My place is close to the beach, family-friendly activities, great views, and a short drive to art and culture, and restaurants and dining", - // "Response is not as expected for Find commmand with multiple conditions", - // ); - // }); - // BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); - // cy.deleteQueryUsingContext(); - // }); + it("2. Validate Find documents command & Run and then delete the query", function () { + dataSources.CreateQueryForDS(datasourceName); + dataSources.SetQueryTimeout(20000); - // it("3. Validate Count command & Run and then delete the query", function () { - // dataSources.CreateQueryForDS(datasourceName); - // assertHelper.AssertNetworkStatus("@trigger"); - // cy.ValidateAndSelectDropdownOption( - // formControls.commandDropdown, - // "Find document(s)", - // "Count", - // ); - // dataSources.EnterJSContext({ - // fieldLabel: "Collection", - // fieldValue: "listingAndReviews", - // }); - // dataSources.RunQuery(); - // agHelper.EnterValue("{guests_included : {$gte: 2}}", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Query", - // }); - // dataSources.RunQuery({ toValidateResponse: false }); - // cy.wait("@postExecute").then(({ response }) => { - // expect(response.body.data.body.n).to.be.above( - // 0, - // "Response is not as expected for Count commmand", - // ); - // }); - // cy.deleteQueryUsingContext(); - // }); + //cy.xpath(queryLocators.findDocs).should("exist"); //Verifying update is success or below line + //cy.expect(queryLocators.findDocs).to.exist; - // it("4. Validate Distinct command & Run and then delete the query", function () { - // dataSources.CreateQueryForDS(datasourceName); - // assertHelper.AssertNetworkStatus("@trigger"); - // cy.ValidateAndSelectDropdownOption( - // formControls.commandDropdown, - // "Find document(s)", - // "Distinct", - // ); - // dataSources.EnterJSContext({ - // fieldLabel: "Collection", - // fieldValue: "listingAndReviews", - // }); - // agHelper.EnterValue("{price : {$gte: 100}}", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Query", - // }); - // agHelper.EnterValue("property_type", { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Key", - // }); - // dataSources.RunQuery({ toValidateResponse: false }); - // cy.wait("@postExecute").then(({ response }) => { - // expect(response.body.data.body.values[0]).to.eq( - // "Aparthotel", - // "Response is not as expected for Distint commmand", - // ); - // }); - // cy.deleteQueryUsingContext(); - // }); + assertHelper.AssertNetworkStatus("@trigger"); + cy.ValidateAndSelectDropdownOption( + formControls.commandDropdown, + "Find document(s)", + ); - // it("5. Validate Aggregate command & Run and then delete the query", function () { - // dataSources.CreateQueryForDS(datasourceName); - // assertHelper.AssertNetworkStatus("@trigger"); - // cy.ValidateAndSelectDropdownOption( - // formControls.commandDropdown, - // "Find document(s)", - // "Aggregate", - // ); - // dataSources.EnterJSContext({ - // fieldLabel: "Collection", - // fieldValue: "listingAndReviews", - // }); - // agHelper.EnterValue(`[{ $project: { count: { $size:"$amenities" }}}]`, { - // propFieldName: "", - // directInput: false, - // inputFieldName: "Array of pipelines", - // }); - - // dataSources.RunQuery({ toValidateResponse: false }); - // cy.wait("@postExecute").then(({ request, response }) => { - // // cy.log(request.method + ": is req.method") - // //expect(request.method).to.equal('POST') - // expect(response.body.data.body[0].count).to.be.above( - // 0, - // "Response is not as expected for Aggregate commmand", - // ); - // // it is good practice to add message to the assertion - // // expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') - // }); - // cy.deleteQueryUsingContext(); - // }); + dataSources.EnterJSContext({ + fieldLabel: "Collection", + fieldValue: "listingAndReviews", + }); + dataSources.RunQuery(); + BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); - // it("6. Verify generation of NewPage from collection [Select] + Bug 12162", function () { - // //Verifying Select from UI - // cy.NavigateToDSGeneratePage(datasourceName); - // agHelper.Sleep(3000); //giving some time for options to load - // cy.get(generatePage.selectTableDropdown).click(); - // cy.get(generatePage.dropdownOption) - // //.first() - // .contains("listingAndReviews") - // .scrollIntoView() - // .should("be.visible") - // .click(); - - // cy.get(generatePage.generatePageFormSubmitBtn).click(); - - // cy.wait("@replaceLayoutWithCRUDPage").should( - // "have.nested.property", - // "response.body.responseMeta.status", - // 201, - // ); - - // cy.wait("@getActions"); - - // cy.wait("@postExecute").should( - // "have.nested.property", - // "response.body.responseMeta.status", - // 200, - // ); //This verifies the Select on the table, ie page is created fine - - // cy.ClickGotIt(); - - // //Check if table is loaded & CRUD is success - - // cy.get(generatePage.selectedRow).should("exist"); - // // cy.get(generatePage.updateBtn) - // // .closest("button") - // // .then((selector) => { - // // cy.get(selector) - // // .invoke("attr", "class") - // // .then((classes) => { - // // cy.log("classes are:" + classes); - // // expect(classes).not.contain("bp3-disabled"); - // // }); - // // }); - // }); + agHelper.EnterValue("{beds : {$lte: 2}}", { + propFieldName: "", + directInput: false, + inputFieldName: "Query", + }); + dataSources.RunQuery(); + BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); - // it("7. Validate Deletion of the Newly Created Page", () => { - // dataSources.DeleteDatasourceFromWithinDS(datasourceName, 409); - // entityExplorer.ActionContextMenuByEntityName({ - // entityNameinLeftSidebar: "ListingAndReviews", - // action: "Delete", - // entityType: entityItems.Page, - // }); - // EditorNavigation.SelectEntityByName("Page1", EntityType.Page); - // }); + agHelper.EnterValue("{number_of_reviews: -1}", { + propFieldName: "", + directInput: false, + inputFieldName: "Sort", + }); //sort descending + dataSources.RunQuery(); + BottomPane.response.validateRecordCount({ count: 10, operator: "lte" }); + + agHelper.EnterValue("{house_rules: 1, description:1}", { + propFieldName: "", + directInput: false, + inputFieldName: "Projection", + }); //Projection field + dataSources.RunQuery(); + + agHelper.EnterValue("5", { + propFieldName: "", + directInput: false, + inputFieldName: "Limit", + }); //Limit field + + dataSources.RunQuery({ toValidateResponse: false }); + cy.wait("@postExecute").then(({ response }) => { + expect(response.body.data.body[0].description).to.contains( + "The ideal apartment to visit the magnificent city of Porto and the northern region of Portugal, with family or with a couple of friends", + "Response is not as expected for Find commmand with multiple conditions", + ); + }); + BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); + + agHelper.EnterValue("2", { + propFieldName: "", + directInput: false, + inputFieldName: "Skip", + }); + dataSources.RunQuery({ toValidateResponse: false }); + cy.wait("@postExecute").then(({ response }) => { + expect(response.body.data.body[0].description).to.contains( + "My place is close to the beach, family-friendly activities, great views, and a short drive to art and culture, and restaurants and dining", + "Response is not as expected for Find commmand with multiple conditions", + ); + }); + BottomPane.response.validateRecordCount({ count: 5, operator: "lte" }); + cy.deleteQueryUsingContext(); + }); + + it("3. Validate Count command & Run and then delete the query", function () { + dataSources.CreateQueryForDS(datasourceName); + assertHelper.AssertNetworkStatus("@trigger"); + cy.ValidateAndSelectDropdownOption( + formControls.commandDropdown, + "Find document(s)", + "Count", + ); + dataSources.EnterJSContext({ + fieldLabel: "Collection", + fieldValue: "listingAndReviews", + }); + dataSources.RunQuery(); + agHelper.EnterValue("{guests_included : {$gte: 2}}", { + propFieldName: "", + directInput: false, + inputFieldName: "Query", + }); + dataSources.RunQuery({ toValidateResponse: false }); + cy.wait("@postExecute").then(({ response }) => { + expect(response.body.data.body.n).to.be.above( + 0, + "Response is not as expected for Count commmand", + ); + }); + cy.deleteQueryUsingContext(); + }); + + it("4. Validate Distinct command & Run and then delete the query", function () { + dataSources.CreateQueryForDS(datasourceName); + assertHelper.AssertNetworkStatus("@trigger"); + cy.ValidateAndSelectDropdownOption( + formControls.commandDropdown, + "Find document(s)", + "Distinct", + ); + dataSources.EnterJSContext({ + fieldLabel: "Collection", + fieldValue: "listingAndReviews", + }); + agHelper.EnterValue("{price : {$gte: 100}}", { + propFieldName: "", + directInput: false, + inputFieldName: "Query", + }); + agHelper.EnterValue("property_type", { + propFieldName: "", + directInput: false, + inputFieldName: "Key", + }); + dataSources.RunQuery({ toValidateResponse: false }); + cy.wait("@postExecute").then(({ response }) => { + expect(response.body.data.body.values[0]).to.eq( + "Aparthotel", + "Response is not as expected for Distint commmand", + ); + }); + cy.deleteQueryUsingContext(); + }); + + it("5. Validate Aggregate command & Run and then delete the query", function () { + dataSources.CreateQueryForDS(datasourceName); + assertHelper.AssertNetworkStatus("@trigger"); + cy.ValidateAndSelectDropdownOption( + formControls.commandDropdown, + "Find document(s)", + "Aggregate", + ); + dataSources.EnterJSContext({ + fieldLabel: "Collection", + fieldValue: "listingAndReviews", + }); + agHelper.EnterValue(`[{ $project: { count: { $size:"$amenities" }}}]`, { + propFieldName: "", + directInput: false, + inputFieldName: "Array of pipelines", + }); + + dataSources.RunQuery({ toValidateResponse: false }); + cy.wait("@postExecute").then(({ request, response }) => { + // cy.log(request.method + ": is req.method") + //expect(request.method).to.equal('POST') + expect(response.body.data.body[0].count).to.be.above( + 0, + "Response is not as expected for Aggregate commmand", + ); + // it is good practice to add message to the assertion + // expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') + }); + cy.deleteQueryUsingContext(); + }); + + it("6. Verify generation of NewPage from collection [Select] + Bug 12162", function () { + //Verifying Select from UI + cy.NavigateToDSGeneratePage(datasourceName); + agHelper.Sleep(3000); //giving some time for options to load + cy.get(generatePage.selectTableDropdown).click(); + cy.get(generatePage.dropdownOption) + //.first() + .contains("listingAndReviews") + .scrollIntoView() + .should("be.visible") + .click(); + + cy.get(generatePage.generatePageFormSubmitBtn).click(); + + cy.wait("@replaceLayoutWithCRUDPage").should( + "have.nested.property", + "response.body.responseMeta.status", + 201, + ); + + cy.wait("@getActions"); + + cy.wait("@postExecute").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); //This verifies the Select on the table, ie page is created fine + + cy.ClickGotIt(); + + //Check if table is loaded & CRUD is success + + cy.get(generatePage.selectedRow).should("exist"); + // cy.get(generatePage.updateBtn) + // .closest("button") + // .then((selector) => { + // cy.get(selector) + // .invoke("attr", "class") + // .then((classes) => { + // cy.log("classes are:" + classes); + // expect(classes).not.contain("bp3-disabled"); + // }); + // }); + }); + + it("7. Validate Deletion of the Newly Created Page", () => { + dataSources.DeleteDatasourceFromWithinDS(datasourceName, 409); + entityExplorer.ActionContextMenuByEntityName({ + entityNameinLeftSidebar: "ListingAndReviews", + action: "Delete", + entityType: entityItems.Page, + }); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + }); it("8. Bug 7399: Validate Form based & Raw command based templates", function () { let id;