Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: adding tests for jsobject regression tests #38214

Merged
merged 8 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
import HomePage from "../../../../locators/HomePage";
import {
agHelper,
entityExplorer,
jsEditor,
propPane,
draggableWidgets,
locators,
debuggerHelper,
dataSources,
assertHelper,
table,
} from "../../../../support/ee/ObjectsCore_EE";
import EditorNavigation, {
EntityType,
PageLeftPane,
PagePaneSegment,
} from "../../../../support/Pages/EditorNavigation";
import PageList from "../../../../support/Pages/PageList";

describe("Validate JSObj", {}, () => {
before(() => {});

it("1. Verify adding/deleting JSObject and more actions options", () => {
jsEditor.CreateJSObject(
`setInterval(() => {
showAlert("Hi", "success")
}, 2500, "Int")`,
{
paste: true,
completeReplace: false,
toRun: true,
shouldCreateNewJSObj: true,
},
);
jsEditor.EnableDisableAsyncFuncSettings("myFun1");

// Add new JSObject
PageList.AddNewPage("New blank page");
PageLeftPane.switchSegment(PagePaneSegment.JS);
agHelper.GetNClick(locators._createNew);
agHelper.GetNClick(jsEditor._addJSObj);
agHelper.AssertContains("JSObject2", "exist", entityExplorer._entityName);
agHelper.GetNClick(EditorNavigation.locators.MinimizeBtn);
EditorNavigation.CloseAnnouncementModal();
// List view
agHelper.GetNClick('[data-testid="t--list-toggle"]');
agHelper.AssertContains("JSObject1", "exist", entityExplorer._entityName);
agHelper.AssertContains("JSObject2", "exist", entityExplorer._entityName);
// Verify menu item in List view
agHelper.GetNClick(jsEditor._jsPageActions, 0, true);
agHelper.AssertContains("Rename", "exist", HomePage.portalMenuItem);
agHelper.AssertContains("Show bindings", "exist", HomePage.portalMenuItem);
agHelper.AssertContains("Copy to page", "exist", HomePage.portalMenuItem);
agHelper.AssertContains("Move to page", "exist", HomePage.portalMenuItem);
agHelper.AssertContains("Delete", "exist", HomePage.portalMenuItem);

// Add JSObj in List view
agHelper.GetNClick(jsEditor._addJSObj, 0, true);
agHelper.GetNClick(EditorNavigation.locators.MaximizeBtn);
agHelper.AssertContains("JSObject2", "exist", entityExplorer._entityName);

// Delete JSObj
agHelper.GetNClick(jsEditor._addJSObj, 0, true);
agHelper.GetNClick(jsEditor._moreActions, 0, true);
agHelper.GetNClickByContains(HomePage.portalMenuItem, "Delete");
agHelper.GetNClickByContains(HomePage.portalMenuItem, "Are you sure?");
agHelper.ValidateToastMessage("JSObject4 deleted successfully");

// Verify Copy to Page
NandanAnantharamu marked this conversation as resolved.
Show resolved Hide resolved
// agHelper.GetNClick(jsEditor._moreActions, 0, true);
// agHelper.GetNClickByContains(HomePage.portalMenuItem, "Copy to page");
// agHelper.GetNClickByContains(HomePage.portalMenuItem, "Page1");
// agHelper.ValidateToastMessage(
// "JSObject3 copied to page Page1 successfully",
// );
// agHelper.AssertContains("JSObject3", "exist", entityExplorer._entityName);

// Verify Rename
// agHelper.GetNClick(jsEditor._moreActions, 0, true);
// agHelper.AssertContains("Rename", "exist", HomePage.portalMenuItem);
// agHelper.GetNClickByContains(HomePage.portalMenuItem, 'Rename');
// agHelper.ClearNType('[value="JSObject3"]', 'JSObject3New');
// agHelper.AssertContains("JSObject3New", "exist", entityExplorer._entityName);
// agHelper.AssertContains("Copy to page", "exist", HomePage.portalMenuItem);
});

it("2. Verify alert message on page load and adding Function 2 to remove message", () => {
// Verify alert message on page load
EditorNavigation.NavigateToPage("Page1", true);
agHelper.ValidateToastMessage("Hi");
PageLeftPane.switchSegment(PagePaneSegment.JS);
jsEditor.CreateJSObject(`clearInterval("Int")`, {
paste: true,
completeReplace: false,
shouldCreateNewJSObj: false,
lineNumber: 10,
});
jsEditor.SelectFunctionDropdown("myFun2");
jsEditor.RunJSObj();
agHelper.WaitUntilAllToastsDisappear();
});

it("3. Verify moving JSObject to new page", () => {
// Verify Move to Page
agHelper.GetNClick(jsEditor._moreActions, 0, true);
agHelper.HoverElement(
`${HomePage.portalMenuItem}:contains("Move to page")`,
);
agHelper.GetNClick(`${HomePage.portalMenuItem}:contains("Page2")`);

EditorNavigation.NavigateToPage("Page1", true);
PageLeftPane.switchSegment(PagePaneSegment.JS);
agHelper.AssertElementAbsence('.t--entity-name:contains("JSObject1")');
});

it("4. Verify JSObject binding", () => {
EditorNavigation.NavigateToPage("Page2", true);
PageLeftPane.switchSegment(PagePaneSegment.UI);
entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 500, 100);
propPane.EnterJSContext("onClick", "{{JSObject11.myFun1();}}", true, false);
agHelper.GetNClick(locators._widgetInDeployed("buttonwidget"));
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use data- attributes for selectors.*

Replace hardcoded widget selector with a data-* attribute as per coding guidelines.

-    agHelper.GetNClick(locators._widgetInDeployed("buttonwidget"));
+    agHelper.GetNClick("[data-testid='t--widget-buttonwidget']");

Committable suggestion skipped: line range outside the PR's diff.

agHelper.ValidateToastMessage("Hi");
});

it("5. Verify JSObject Coalescing Logs", () => {
PageList.AddNewPage("New blank page");
jsEditor.CreateJSObject(
`// Basic example using nullish coalescing operator
const userProvidedValue = null;
const defaultValue = "Default Value";

const finalValue = userProvidedValue ?? defaultValue;

console.log(finalValue);`,
{
paste: true,
completeReplace: false,
shouldCreateNewJSObj: true,
lineNumber: 5,
},
);
jsEditor.RenameJSObjFromExplorer("JSObject1", "Coalescing");
agHelper.GetNClick(jsEditor.runButtonLocator);
agHelper.GetNClick(debuggerHelper.locators._logsTab);
debuggerHelper.DoesConsoleLogExist("Default Value");
});

it("6. Verify JSObject Typecasting", () => {
// typecasting a string to a number
jsEditor.CreateJSObject(
`export default {
myVar1: [],
myVar2: {},
myFun1 () {
const stringNumber = "42";
const actualNumber = Number(stringNumber);

console.log(typeof stringNumber);
console.log(typeof actualNumber);
console.log(actualNumber);

const numberValue = 100;
const stringValue = String(numberValue);

console.log(typeof numberValue);
console.log(typeof stringValue);
console.log(stringValue);
}
}
`,
{
paste: true,
completeReplace: true,
shouldCreateNewJSObj: true,
},
);
jsEditor.RenameJSObjFromExplorer("JSObject1", "Typecasting");
agHelper.GetNClick(jsEditor.runButtonLocator);
agHelper.GetNClick(debuggerHelper.locators._logsTab);
debuggerHelper.DoesConsoleLogExist("string");
debuggerHelper.DoesConsoleLogExist("number");
debuggerHelper.DoesConsoleLogExist("42");

// typecasting a number to a string
jsEditor.CreateJSObject(
`export default {
myVar1: [],
myVar2: {},
myFun1 () {
const numberValue = 100;
const stringValue = String(numberValue);

console.log(typeof numberValue);
console.log(typeof stringValue);
console.log(stringValue);
}
}
`,
{
paste: true,
completeReplace: true,
shouldCreateNewJSObj: true,
lineNumber: 5,
},
);
agHelper.GetNClick(jsEditor.runButtonLocator);
agHelper.GetNClick(debuggerHelper.locators._logsTab);
debuggerHelper.DoesConsoleLogExist("number");
debuggerHelper.DoesConsoleLogExist("string");
debuggerHelper.DoesConsoleLogExist("100");
});

it("7. Verify Promise", () => {
jsEditor.CreateJSObject(
`export default {
myVar1: [],
myVar2: {},
myFun1 () {
// Create a promise that simulates an asynchronous operation
const myPromise = new Promise((resolve, reject) => {
const success = true; // You can change this to false to simulate a rejection

setTimeout(() => {
if (success) {
resolve("Operation was successful!"); // Fulfill the promise
} else {
reject("Operation failed."); // Reject the promise
}
}, 2000); // Simulate a 2-second delay
});

// Handle the promise
myPromise
.then((message) => {
console.log(message); // Output: "Operation was successful!" if fulfilled
})
.catch((error) => {
console.log(error); // Output: "Operation failed." if rejected
});
}
}
`,
{
paste: true,
completeReplace: true,
shouldCreateNewJSObj: true,
},
);
jsEditor.RenameJSObjFromExplorer("JSObject2", "Pr");
agHelper.GetNClick(jsEditor.runButtonLocator);
agHelper.GetNClick(debuggerHelper.locators._logsTab);
debuggerHelper.DoesConsoleLogExist("Operation was successful!");
});

it("8. Verify Queries", () => {
dataSources.CreateDataSource("Postgres");
dataSources.CreateQueryAfterDSSaved(" ");
agHelper.TypeIntoTextArea(locators._codeEditorTarget, "/");
agHelper.GetNAssertContains(locators._hints, "Coalescing");
agHelper.GetNAssertContains(locators._hints, "Typecasting");
agHelper.GetNAssertContains(locators._hints, "Pr");
agHelper.GetNAssertContains(locators._hints, "JSObject1");
agHelper.GetNAssertContains(locators._hints, "MainContainer");

cy.get("@guid").then((uid) => {
dataSources.GeneratePageForDS(`Postgres ${uid}`);
});
assertHelper.AssertNetworkStatus("@postExecute", 200);
agHelper.ClickButton("Got it");
assertHelper.AssertNetworkStatus("@updateLayout", 200);
agHelper.Sleep(2000);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove explicit sleep calls.

Using agHelper.Sleep() violates the coding guidelines. Use Cypress's built-in retry-ability and assertions instead.

-    agHelper.Sleep(2000);
+    agHelper.AssertElementVisibility(table.locators._table);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
agHelper.Sleep(2000);
agHelper.AssertElementVisibility(table.locators._table);

table.WaitUntilTableLoad(0, 0, "v2");
EditorNavigation.SelectEntityByName("SelectQuery", EntityType.Query);
agHelper.GetNClick(locators._codeEditorTarget);
agHelper.AssertElementVisibility(locators._evaluatedValue);

cy.get(`${locators._codeMirrorCode} pre`).then(($elements) => {
const text = [...$elements].map((el) => el.innerText).join("");
agHelper.GetText(locators._evaluatedValue).then((evalText: any) => {
expect(evalText.replace(/\n/g, "")).to.eq(text);
});
});
});

it("9. Verify JSObject with identical name should not exist Bug: #35385", () => {
for (let i = 0; i < 10; i++) {
agHelper.GetNClick(locators._createNew, 0, true, 0);
}
agHelper.AssertElementAbsence(locators._toastMsg);
});
});
3 changes: 2 additions & 1 deletion app/client/cypress/limited-tests.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# To run only limited tests - give the spec names in below format:
cypress/e2e/Regression/ClientSide/Templates/Fork_Template_spec.js
cypress/e2e/Regression/ClientSide/JSObject/JSObject_Tests_spec.ts

# For running all specs - uncomment below:
#cypress/e2e/**/**/*

Expand Down
1 change: 1 addition & 0 deletions app/client/cypress/support/Pages/EntityExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class EntityExplorer {
_widgetTagSuggestedWidgets = ".widget-tag-collapsible-suggested";
_widgetTagBuildingBlocks = ".widget-tag-collapsible-building-blocks";
_widgetSeeMoreButton = "[data-testid='t--explorer-ui-entity-tag-see-more']";
_entityName = ".t--entity-name"
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider reusing existing selector.

The selector .t--entity-name is already used in the code (e.g., in DeleteAllQueriesForDB method). To maintain DRY principles, consider reusing the existing selector reference.

-  _entityName = ".t--entity-name"

Committable suggestion skipped: line range outside the PR's diff.


public ActionContextMenuByEntityName({
action = "Delete",
Expand Down
3 changes: 3 additions & 0 deletions app/client/cypress/support/Pages/JSEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ export class JSEditor {
"//div[@data-testid='t--query-run-confirmation-modal']//span[text()='" +
text +
"']";
_addJSObj = '[data-testid="t--ide-tabs-add-button"]';
_jsPageActions = ".entity-context-menu";
_moreActions = '[data-testid="t--more-action-trigger"]';
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove duplicate selector and follow consistent naming.

The _moreActions selector duplicates the existing contextMenuTriggerLocator property. Both use the same data-testid attribute.

    _addJSObj = '[data-testid="t--ide-tabs-add-button"]';
    _jsPageActions = ".entity-context-menu";
-    _moreActions = '[data-testid="t--more-action-trigger"]';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_addJSObj = '[data-testid="t--ide-tabs-add-button"]';
_jsPageActions = ".entity-context-menu";
_moreActions = '[data-testid="t--more-action-trigger"]';
_addJSObj = '[data-testid="t--ide-tabs-add-button"]';
_jsPageActions = ".entity-context-menu";

//#endregion

//#region constants
Expand Down
Loading