-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Description Hover over appsmith properties in code to peek data. <img width="380" alt="image" src="https://user-images.githubusercontent.com/66776129/217707810-164924c0-36e8-4450-b087-18af333c7547.png"> This right now covers: - Queries/JsObjects/Apis/Widgets and their properties. - Note: For query or Api, this'll work only upto `Api.data`. (Not `Api.data.users[0].id`) - This is because of the way codemirror renders code and we'll need more time to see how this is best handled. Misc: - added `react-append-to-body` to work with variable height for peek overlay - we needed a container that doesn't apply `position: absolute` to itself - Because, when a container's `height` is zero with `position: absolute` (like in bp3-portal), child elements cannot be positioned using just the `bottom` property - with `react-append-to-body`, the container won't have `position: absolute`, instead it is applied to the child element `<div>` directly, hence we can position using `bottom` property. Fixes #17507 Media https://www.loom.com/share/0f17918fcd604805b023c215d57fce43 ## Type of change - New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Manual ### Test Plan https://github.com/appsmithorg/TestSmith/issues/2173 https://github.com/appsmithorg/TestSmith/issues/2178 ### Issues raised during DP testing #20053 (comment) #20053 (comment) ## Checklist: ### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [x] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [x] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
- Loading branch information
Showing
24 changed files
with
1,117 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
.../cypress/integration/Regression_TestSuite/ClientSideTests/PeekOverlay/PeekOverlay.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import * as _ from "../../../../support/Objects/ObjectsCore"; | ||
|
||
describe("peek overlay", () => { | ||
it("main test", () => { | ||
_.ee.DragDropWidgetNVerify("tablewidgetv2", 500, 100); | ||
_.apiPage.CreateAndFillApi(_.agHelper.mockApiUrl); | ||
_.apiPage.RunAPI(); | ||
_.apiPage.CreateAndFillApi(_.agHelper.mockApiUrl); | ||
_.jsEditor.CreateJSObject( | ||
`export default { | ||
numArray: [1, 2, 3], | ||
objectArray: [ {x: 123}, { y: "123"} ], | ||
objectData: { x: 123, y: "123" }, | ||
nullData: null, | ||
numberData: 1, | ||
myFun1: () => { | ||
// TODO: handle this keyword failure on CI tests | ||
JSObject1.numArray; JSObject1.objectData; JSObject1.nullData; JSObject1.numberData; | ||
Api1.run(); Api1.isLoading; Api2.data; | ||
appsmith.mode; appsmith.store.abc; | ||
Table1.pageNo; Table1.tableData; | ||
}, | ||
myFun2: async () => { | ||
storeValue("abc", 123) | ||
return Api1.run() | ||
} | ||
}`, | ||
{ | ||
paste: true, | ||
completeReplace: true, | ||
toRun: false, | ||
shouldCreateNewJSObj: true, | ||
lineNumber: 0, | ||
prettify: true, | ||
}, | ||
); | ||
_.jsEditor.SelectFunctionDropdown("myFun2"); | ||
_.jsEditor.RunJSObj(); | ||
_.agHelper.Sleep(); | ||
|
||
// check number array | ||
_.peekOverlay.HoverCode("JSObject1.numArray"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("array"); | ||
_.peekOverlay.CheckPrimitveArrayInOverlay([1, 2, 3]); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check basic object | ||
_.peekOverlay.HoverCode("JSObject1.objectData"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("object"); | ||
_.peekOverlay.CheckBasicObjectInOverlay({ x: 123, y: "123" }); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check null - with this keyword | ||
_.peekOverlay.HoverCode("JSObject1.nullData"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("null"); | ||
_.peekOverlay.CheckPrimitiveValue("null"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check number | ||
_.peekOverlay.HoverCode("JSObject1.numberData"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("number"); | ||
_.peekOverlay.CheckPrimitiveValue("1"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check undefined | ||
_.peekOverlay.HoverCode("Api2.data"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("undefined"); | ||
_.peekOverlay.CheckPrimitiveValue("undefined"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check boolean | ||
_.peekOverlay.HoverCode("Api1.isLoading"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("boolean"); | ||
_.peekOverlay.CheckPrimitiveValue("false"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// TODO: handle this function failure on CI tests -> "function(){}" | ||
// check function | ||
// _.peekOverlay.HoverCode("Api1.run"); | ||
// _.peekOverlay.IsOverlayOpen(); | ||
// _.peekOverlay.VerifyDataType("function"); | ||
// _.peekOverlay.CheckPrimitiveValue("function () {}"); | ||
// _.peekOverlay.ResetHover(); | ||
|
||
// check string | ||
_.peekOverlay.HoverCode("appsmith.mode"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("string"); | ||
_.peekOverlay.CheckPrimitiveValue("EDIT"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// check if overlay closes | ||
_.peekOverlay.HoverCode("appsmith.store"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.ResetHover(); | ||
_.peekOverlay.IsOverlayOpen(false); | ||
|
||
// widget object | ||
_.peekOverlay.HoverCode("Table1"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("object"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// widget property | ||
_.peekOverlay.HoverCode("Table1.pageNo"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("number"); | ||
_.peekOverlay.CheckPrimitiveValue("1"); | ||
_.peekOverlay.ResetHover(); | ||
|
||
// widget property | ||
_.peekOverlay.HoverCode("Table1.tableData"); | ||
_.peekOverlay.IsOverlayOpen(); | ||
_.peekOverlay.VerifyDataType("array"); | ||
_.peekOverlay.CheckObjectArrayInOverlay([{}, {}, {}]); | ||
_.peekOverlay.ResetHover(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { ObjectsRegistry } from "../Objects/Registry"; | ||
|
||
export class PeekOverlay { | ||
private readonly PEEKABLE_ATTRIBUTE = "peek-data"; | ||
private readonly locators = { | ||
_overlayContainer: "#t--peek-overlay-container", | ||
_dataContainer: "#t--peek-overlay-data", | ||
_peekableCode: (peekableAttr: string) => | ||
`[${this.PEEKABLE_ATTRIBUTE}="${peekableAttr}"]`, | ||
|
||
// react json viewer selectors | ||
_rjv_variableValue: ".variable-value", | ||
_rjv_topLevelArrayData: | ||
".pushed-content.object-container .object-content .object-key-val", | ||
_rjv_firstLevelBraces: | ||
".pretty-json-container > .object-content:first-of-type > .object-key-val:first-of-type > span", | ||
}; | ||
private readonly agHelper = ObjectsRegistry.AggregateHelper; | ||
|
||
HoverCode(peekableAttribute: string, visibleText?: string) { | ||
(visibleText | ||
? this.agHelper.GetNAssertContains( | ||
this.locators._peekableCode(peekableAttribute), | ||
visibleText, | ||
) | ||
: this.agHelper.GetElement(this.locators._peekableCode(peekableAttribute)) | ||
).realHover(); | ||
this.agHelper.Sleep(); | ||
} | ||
|
||
IsOverlayOpen(checkIsOpen = true) { | ||
checkIsOpen | ||
? this.agHelper.AssertElementExist(this.locators._overlayContainer) | ||
: this.agHelper.AssertElementAbsence(this.locators._overlayContainer); | ||
} | ||
|
||
ResetHover() { | ||
this.agHelper.GetElement("body").realHover({ position: "bottomLeft" }); | ||
this.agHelper.Sleep(); | ||
} | ||
|
||
CheckPrimitiveValue(data: string) { | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.children("div") | ||
.should("have.text", data); | ||
} | ||
|
||
CheckPrimitveArrayInOverlay(array: Array<string | number>) { | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_variableValue) | ||
.should("have.length", array.length); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(0) | ||
.contains("["); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(1) | ||
.contains("]"); | ||
} | ||
|
||
CheckObjectArrayInOverlay(array: Array<Record<string, any>>) { | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_topLevelArrayData) | ||
.should("have.length", array.length); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(0) | ||
.contains("["); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(1) | ||
.contains("]"); | ||
} | ||
|
||
CheckBasicObjectInOverlay(object: Record<string, string | number>) { | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_variableValue) | ||
.should("have.length", Object.entries(object).length); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(0) | ||
.contains("{"); | ||
this.agHelper | ||
.GetElement(this.locators._dataContainer) | ||
.find(this.locators._rjv_firstLevelBraces) | ||
.eq(1) | ||
.contains("}"); | ||
} | ||
|
||
VerifyDataType(type: string) { | ||
this.agHelper | ||
.GetElement(this.locators._overlayContainer) | ||
.children("div") | ||
.eq(0) | ||
.should("have.text", type); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
app/client/src/components/editorComponents/CodeEditor/PeekOverlayPopup/Analytics.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { MouseEventHandler } from "react"; | ||
import AnalyticsUtil from "utils/AnalyticsUtil"; | ||
|
||
export const objectCollapseAnalytics: MouseEventHandler = (ev) => { | ||
/* | ||
* Analytics events to be logged whenever user clicks on | ||
* react json viewer's controls to expand or collapse object/array | ||
*/ | ||
const targetNode = ev.target as HTMLElement; | ||
|
||
if ( | ||
// collapse/expand icon click, object key click | ||
targetNode.parentElement?.parentElement?.parentElement?.firstElementChild?.classList.contains( | ||
"icon-container", | ||
) || | ||
// : click | ||
targetNode.parentElement?.parentElement?.firstElementChild?.classList.contains( | ||
"icon-container", | ||
) || | ||
// { click | ||
targetNode.parentElement?.firstElementChild?.classList.contains( | ||
"icon-container", | ||
) || | ||
// ellipsis click | ||
targetNode.classList.contains("node-ellipsis") || | ||
// collapse/expand icon - svg path click | ||
targetNode.parentElement?.parentElement?.classList.contains( | ||
"collapsed-icon", | ||
) || | ||
targetNode.parentElement?.parentElement?.classList.contains("expanded-icon") | ||
) { | ||
AnalyticsUtil.logEvent("PEEK_OVERLAY_COLLAPSE_EXPAND_CLICK"); | ||
} | ||
}; | ||
|
||
export const textSelectAnalytics = () => { | ||
AnalyticsUtil.logEvent("PEEK_OVERLAY_VALUE_COPIED"); | ||
}; |
Oops, something went wrong.