fix: Add collapse icon for bottom bar (#16939)

* add containerRef and explandedHeight to enable collapse icon

* change icon

* sizing

* alignment fixes

* consistent height

* remove unwanted padding

* debugger panel height

* remove extra divider line

* open panel on header click

* rename method

* cypress tests init

* jsobject navigate instead of create

* clean up

* remove variable

* undo changes

* final clean up

* logs spec clean up

* debugger locators clean up

* rename locator

* mock db spec fix

* logs spec fix

* clean up records count locator

* Rename dubugger locators and methods

* spec file change

* move methods

* rename debugger helper class

* build fix

* handle selectors

* merge clean up

* fix failing tests

* use single variable to set height

* undo cypress env changes
This commit is contained in:
Anand Srinivasan 2022-10-20 17:38:48 +05:30 committed by GitHub
parent bd95ae4ef0
commit d62e1961d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 435 additions and 209 deletions

View File

@ -1,11 +1,10 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
let ee = ObjectsRegistry.EntityExplorer,
const ee = ObjectsRegistry.EntityExplorer,
dataSources = ObjectsRegistry.DataSources,
agHelper = ObjectsRegistry.AggregateHelper,
locator = ObjectsRegistry.CommonLocators,
mockDBNameUsers: any,
mockDBNameMovies: any;
locator = ObjectsRegistry.CommonLocators;
let mockDBNameUsers: any, mockDBNameMovies: any;
describe("Entity explorer context menu should hide on scrolling", function() {
it("1. Bug #15474 - Entity explorer menu must close on scroll", function() {

View File

@ -6,7 +6,8 @@ const jsEditor = ObjectsRegistry.JSEditor,
agHelper = ObjectsRegistry.AggregateHelper,
table = ObjectsRegistry.Table,
apiPage = ObjectsRegistry.ApiPage,
propPane = ObjectsRegistry.PropertyPane;
propPane = ObjectsRegistry.PropertyPane,
debuggerHelper = ObjectsRegistry.DebuggerHelper;
describe("Lint error reporting", () => {
before(() => {
@ -37,18 +38,14 @@ describe("Lint error reporting", () => {
MouseHoverNVerify("name", "'name' is defined but never used.", false);
agHelper.PressEscape();
agHelper.GetNClick(locator._errorTab);
agHelper.AssertContains(
debuggerHelper.DebuggerListDoesnotContain(
"'name' is defined but never used.",
"not.exist",
locator._debuggerList,
);
agHelper.RefreshPage();
agHelper.GetNClick(locator._errorTab);
agHelper.AssertContains(
debuggerHelper.DebuggerListDoesnotContain(
"'name' is defined but never used.",
"not.exist",
locator._debuggerList,
);
});

View File

@ -0,0 +1,57 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
import { PageType } from "../../../../support/Pages/DebuggerHelper";
const {
ApiPage: apiPage,
DataSources: dataSources,
DebuggerHelper: debuggerHelper,
JSEditor: jsEditor,
} = ObjectsRegistry;
describe("Entity bottom bar", () => {
it("1. debugger should be closable", () => {
debuggerHelper.ClickDebuggerIcon();
debuggerHelper.AssertOpen(PageType.Canvas);
debuggerHelper.Close(PageType.Canvas);
debuggerHelper.AssertClosed(PageType.Canvas);
});
it("2. api bottom pane should be collapsable", () => {
apiPage.CreateApi();
debuggerHelper.AssertOpen(PageType.API);
debuggerHelper.Close(PageType.API);
debuggerHelper.AssertClosed(PageType.API);
debuggerHelper.ClickResponseTab();
debuggerHelper.AssertOpen(PageType.API);
});
it("3. jseditor bottom bar should be collapsable", () => {
jsEditor.NavigateToNewJSEditor();
debuggerHelper.AssertOpen(PageType.JsEditor);
debuggerHelper.Close(PageType.JsEditor);
debuggerHelper.AssertClosed(PageType.JsEditor);
debuggerHelper.ClickResponseTab();
debuggerHelper.AssertOpen(PageType.JsEditor);
});
it("4. query bottom bar should be collapsable", () => {
dataSources.CreateMockDB("Users").then((dbName) => {
dataSources.CreateQuery(dbName);
debuggerHelper.AssertOpen(PageType.Query);
debuggerHelper.Close(PageType.Query);
debuggerHelper.AssertClosed(PageType.Query);
debuggerHelper.ClickResponseTab();
debuggerHelper.AssertOpen(PageType.Query);
// clean up
dataSources.DeleteQuery("Query1");
dataSources.DeleteDatasouceFromActiveTab(dbName);
});
});
});

View File

@ -1,18 +1,17 @@
const commonlocators = require("../../../../locators/commonlocators.json");
const debuggerLocators = require("../../../../locators/Debugger.json");
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const {
AggregateHelper: agHelper,
ApiPage: apiPage,
CommonLocators: locator,
DebuggerHelper: debuggerHelper,
EntityExplorer: ee,
JSEditor: jsEditor,
PropertyPane: propPane,
} = ObjectsRegistry;
let logString;
let dataSet;
let logString: string;
let dataSet: unknown;
const generateTestLogString = () => {
const randString = Cypress._.random(0, 1e4);
@ -33,9 +32,9 @@ describe("Debugger logs", function() {
it("1. Modifying widget properties should log the same", function() {
ee.DragDropWidgetNVerify("buttonwidget", 200, 200);
propPane.UpdatePropertyFieldValue("Label", "Test");
agHelper.GetNClick(locator._debuggerIcon, 0, true, 0);
debuggerHelper.ClickDebuggerIcon(0, true, 0);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(locator._debuggerLogState, "Test");
debuggerHelper.LogStateContains("Test");
});
it("2. Reset debugger state", function() {
@ -46,7 +45,7 @@ describe("Debugger logs", function() {
cy.get(commonlocators.homeIcon).click({ force: true });
cy.generateUUID().then((id) => {
cy.CreateAppInFirstListedWorkspace(id);
cy.get(debuggerLocators.errorCount).should("not.exist");
debuggerHelper.AssertErrorCount(0);
});
});
@ -56,12 +55,12 @@ describe("Debugger logs", function() {
propPane.EnterJSContext("onClick", `{{console.log("${logString}")}}`);
agHelper.Sleep(2000);
agHelper.ClickButton("Submit");
agHelper.GetNClick(locator._debuggerIcon);
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.ClickDebuggerIcon();
debuggerHelper.DoesConsoleLogExist(logString);
});
it("4. Console log on button click with arrow function IIFE", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
ee.SelectEntityByName("Button1");
// Testing with normal log in iifee
propPane.EnterJSContext(
@ -71,11 +70,11 @@ describe("Debugger logs", function() {
}) () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("5. Console log on button click with function keyword IIFE", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
ee.SelectEntityByName("Button1");
// Testing with normal log in iifee
propPane.EnterJSContext(
@ -85,11 +84,11 @@ describe("Debugger logs", function() {
} () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("6. Console log on button click with async function IIFE", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
// Testing with normal log in iifee
ee.SelectEntityByName("Button1");
propPane.EnterJSContext(
@ -99,11 +98,11 @@ describe("Debugger logs", function() {
}) () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("7. Console log on button click with mixed function IIFE", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
// Testing with normal log in iifee
ee.SelectEntityByName("Button1");
const logStringChild = generateTestLogString();
@ -115,12 +114,12 @@ describe("Debugger logs", function() {
} () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
agHelper.GetNAssertContains(locator._debuggerLogMessage, logStringChild);
debuggerHelper.DoesConsoleLogExist(logString);
debuggerHelper.DoesConsoleLogExist(logStringChild);
});
it("8. Console log grouping on button click", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
// Testing with normal log in iifee
ee.SelectEntityByName("Button1");
propPane.EnterJSContext(
@ -134,12 +133,12 @@ describe("Debugger logs", function() {
} () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
agHelper.GetNAssertContains(locator._debuggerLogMessageOccurence, "5");
debuggerHelper.DoesConsoleLogExist(logString);
debuggerHelper.Assert_Consecutive_Console_Log_Count(5);
});
it("9. Console log grouping on button click with different log in between", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
// Testing with normal log in iifee
ee.SelectEntityByName("Button1");
propPane.EnterJSContext(
@ -152,16 +151,13 @@ describe("Debugger logs", function() {
} () }}`,
);
agHelper.ClickButton("Submit");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`Different ${logString}`,
);
agHelper.GetNAssertContains(locator._debuggerLogMessageOccurence, "2");
debuggerHelper.DoesConsoleLogExist(logString);
debuggerHelper.DoesConsoleLogExist(`Different ${logString}`);
debuggerHelper.Assert_Consecutive_Console_Log_Count(2);
});
it("10. Console log grouping on button click from different source", function() {
agHelper.GetNClick(locator._debuggerClearLogs);
debuggerHelper.ClearLogs();
// Testing with normal log in iifee
ee.SelectEntityByName("Button1");
propPane.EnterJSContext("onClick", `{{console.log("${logString}")}}`);
@ -172,8 +168,8 @@ describe("Debugger logs", function() {
agHelper.Sleep(2000);
agHelper.ClickButton("Submit");
agHelper.ClickButton("Submit2");
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
agHelper.AssertElementAbsence(locator._debuggerLogMessageOccurence);
debuggerHelper.DoesConsoleLogExist(logString);
debuggerHelper.Assert_Consecutive_Console_Log_Count(0);
});
it("11. Console log on text widget with normal moustache binding", function() {
@ -190,9 +186,9 @@ describe("Debugger logs", function() {
agHelper.RefreshPage();
// Wait for the debugger icon to be visible
agHelper.AssertElementVisible(".t--debugger");
agHelper.GetNClick(locator._debuggerIcon);
debuggerHelper.ClickDebuggerIcon();
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("12. Console log in sync function", function() {
@ -216,7 +212,7 @@ describe("Debugger logs", function() {
},
);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("13. Console log in async function", function() {
@ -241,7 +237,7 @@ describe("Debugger logs", function() {
);
agHelper.WaitUntilAllToastsDisappear();
agHelper.GetNClick(jsEditor._runButton);
agHelper.GetNAssertContains(locator._debuggerLogMessage, logString);
debuggerHelper.DoesConsoleLogExist(logString);
});
it("14. Console log after API succedes", function() {
@ -278,14 +274,8 @@ describe("Debugger logs", function() {
cy.get("@jsObjName").then((jsObjName) => {
agHelper.GetNClick(jsEditor._runButton);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`${logString} Started`,
);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`${logString} Success`,
);
debuggerHelper.DoesConsoleLogExist(`${logString} Started`);
debuggerHelper.DoesConsoleLogExist(`${logString} Success`);
ee.DragDropWidgetNVerify("textwidget", 200, 600);
propPane.UpdatePropertyFieldValue("Text", `{{${jsObjName}.myFun1.data}}`);
agHelper.GetNAssertElementText(
@ -326,14 +316,8 @@ describe("Debugger logs", function() {
agHelper.WaitUntilAllToastsDisappear();
agHelper.GetNClick(jsEditor._runButton);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`${logString} Started`,
);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`${logString} Failed`,
);
debuggerHelper.DoesConsoleLogExist(`${logString} Started`);
debuggerHelper.DoesConsoleLogExist(`${logString} Failed`);
});
it("16. Console log source inside nested function", function() {
@ -357,14 +341,8 @@ describe("Debugger logs", function() {
agHelper.WaitUntilAllToastsDisappear();
agHelper.GetNClick(jsEditor._runButton);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`Parent ${logString}`,
);
agHelper.GetNAssertContains(
locator._debuggerLogMessage,
`Child ${logString}`,
);
debuggerHelper.DoesConsoleLogExist(`Parent ${logString}`);
debuggerHelper.DoesConsoleLogExist(`Child ${logString}`);
});
it("17. Console log grouping", function() {
@ -391,8 +369,8 @@ describe("Debugger logs", function() {
agHelper.WaitUntilAllToastsDisappear();
agHelper.GetNClick(jsEditor._runButton);
agHelper.GetNClick(jsEditor._logsTab);
agHelper.GetNAssertContains(locator._debuggerLogMessage, `${logString}`);
agHelper.GetNAssertContains(locator._debuggerLogMessageOccurence, "5");
debuggerHelper.DoesConsoleLogExist(`${logString}`);
debuggerHelper.Assert_Consecutive_Console_Log_Count(5);
});
// it("Api headers need to be shown as headers in logs", function() {

View File

@ -1,7 +1,9 @@
const dsl = require("../../../../fixtures/debuggerTableDsl.json");
const explorer = require("../../../../locators/explorerlocators.json");
const debuggerLocators = require("../../../../locators/Debugger.json");
const testdata = require("../../../../fixtures/testdata.json");
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const debuggerHelper = ObjectsRegistry.DebuggerHelper;
describe("Check debugger logs state when there are onPageLoad actions", function() {
before(() => {
@ -18,8 +20,8 @@ describe("Check debugger logs state when there are onPageLoad actions", function
cy.reload();
// Wait for the debugger icon to be visible
cy.get(".t--debugger").should("be.visible");
//cy.get(debuggerLocators.errorCount).should("not.exist");
// debuggerHelper.isErrorCount(0);
cy.wait("@postExecute");
cy.contains(debuggerLocators.errorCount, 1);
debuggerHelper.AssertErrorCount(1);
});
});

View File

@ -1,5 +1,6 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const dsl = require("../../../../fixtures/debuggerTableDsl.json");
const debuggerLocators = require("../../../../locators/Debugger.json");
const debuggerHelper = ObjectsRegistry.DebuggerHelper;
describe("Trigger errors in the debugger", function() {
before(() => {
@ -17,10 +18,10 @@ describe("Trigger errors in the debugger", function() {
// Click on a row of the table widget
cy.isSelectRow(1);
cy.wait(5000);
cy.contains(debuggerLocators.errorCount, 2);
debuggerHelper.AssertErrorCount(2);
// Fix code
cy.testJsontext("onrowselected", "{{console.log('test')}}");
cy.isSelectRow(1);
cy.contains(debuggerLocators.errorCount, 1);
debuggerHelper.AssertErrorCount(1);
});
});

View File

@ -1,8 +1,10 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const dsl = require("../../../../fixtures/buttondsl.json");
const debuggerLocators = require("../../../../locators/Debugger.json");
const commonlocators = require("../../../../locators/commonlocators.json");
const widgetLocators = require("../../../../locators/Widgets.json");
const { DebuggerHelper: debuggerHelper } = ObjectsRegistry;
describe("Widget error state", function() {
const modifierKey = Cypress.platform === "darwin" ? "meta" : "ctrl";
@ -23,10 +25,10 @@ describe("Widget error state", function() {
});
it("Check if the current value is shown in the debugger", function() {
cy.get(debuggerLocators.debuggerIcon).click();
debuggerHelper.ClickDebuggerIcon();
cy.contains(".react-tabs__tab", "Errors").click();
cy.get(debuggerLocators.debuggerLogState).contains("Test");
debuggerHelper.LogStateContains("Test");
});
it("Switch to error tab when clicked on the debug button", function() {
@ -43,31 +45,23 @@ describe("Widget error state", function() {
});
it("All errors should be expanded by default", function() {
cy.get(debuggerLocators.errorMessage)
.should("be.visible")
.should("have.length", 2);
debuggerHelper.AssertVisibleErrorMessagesCount(2);
});
it("Recent errors are shown at the top of the list", function() {
cy.testJsontext("label", "{{[]}}");
cy.get(debuggerLocators.debuggerLogState)
.first()
.contains("text");
debuggerHelper.LogStateContains("text", 0);
});
it("Clicking on a message should open the search menu", function() {
cy.get(debuggerLocators.errorMessage)
.first()
.click();
cy.get(debuggerLocators.menuItem).should("be.visible");
debuggerHelper.ClickErrorMessage(0);
debuggerHelper.AssertContextMenuItemVisible();
});
it("Undoing widget deletion should show errors if present", function() {
cy.deleteWidget();
cy.get(debuggerLocators.errorMessage).should("not.exist");
debuggerHelper.AssertVisibleErrorMessagesCount(0);
cy.get("body").type(`{${modifierKey}}z`);
cy.get(debuggerLocators.errorMessage)
.should("be.visible")
.should("have.length", 2);
debuggerHelper.AssertVisibleErrorMessagesCount(2);
});
});

View File

@ -1,14 +1,15 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
let agHelper = ObjectsRegistry.AggregateHelper,
const agHelper = ObjectsRegistry.AggregateHelper,
ee = ObjectsRegistry.EntityExplorer,
jsEditor = ObjectsRegistry.JSEditor,
apiPage = ObjectsRegistry.ApiPage,
locator = ObjectsRegistry.CommonLocators,
deployMode = ObjectsRegistry.DeployMode,
propPane = ObjectsRegistry.PropertyPane;
propPane = ObjectsRegistry.PropertyPane,
debuggerHelper = ObjectsRegistry.DebuggerHelper;
describe("Validate API request body panel", () => {
beforeEach(() => {
agHelper.RestoreLocalStorageCache();
});
@ -93,7 +94,7 @@ describe("Validate API request body panel", () => {
});
it("7. Checks MultiPart form data for a File Type upload + Bug 12476", () => {
let imageNameToUpload = "ConcreteHouse.jpg";
const imageNameToUpload = "ConcreteHouse.jpg";
cy.fixture("multiPartFormDataDsl").then((val: any) => {
agHelper.AddDsl(val);
});
@ -101,7 +102,8 @@ describe("Validate API request body panel", () => {
apiPage.CreateAndFillApi(
"https://api.cloudinary.com/v1_1/appsmithautomationcloud/image/upload?upload_preset=fbbhg4xu",
"CloudinaryUploadApi",
30000, "POST"
30000,
"POST",
);
apiPage.EnterBodyFormData(
"MULTIPART_FORM_DATA",
@ -128,10 +130,7 @@ describe("Validate API request body panel", () => {
);
ee.SelectEntityByName("FilePicker1", "Widgets");
propPane.EnterJSContext(
"onFilesSelected",
`{{JSObject1.upload()}}`
);
propPane.EnterJSContext("onFilesSelected", `{{JSObject1.upload()}}`);
ee.SelectEntityByName("Image1");
propPane.UpdatePropertyFieldValue(
@ -160,7 +159,7 @@ describe("Validate API request body panel", () => {
});
it("8. Checks MultiPart form data for a Array Type upload results in API error", () => {
let imageNameToUpload = "AAAFlowerVase.jpeg";
const imageNameToUpload = "AAAFlowerVase.jpeg";
ee.SelectEntityByName("CloudinaryUploadApi", "Queries/JS");
apiPage.EnterBodyFormData(
"MULTIPART_FORM_DATA",
@ -173,7 +172,7 @@ describe("Validate API request body panel", () => {
agHelper.ClickButton("Select Files");
agHelper.UploadFile(imageNameToUpload);
agHelper.ValidateNetworkExecutionSuccess("@postExecute", false);
agHelper.AssertDebugError(
debuggerHelper.AssertDebugError(
"Execution failed with status 400 BAD_REQUEST",
'{"error":{"message":"Unsupported source URL: {\\"type\\":\\"image/jpeg\\"',
);

View File

@ -1,17 +1,12 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
let agHelper = ObjectsRegistry.AggregateHelper,
const agHelper = ObjectsRegistry.AggregateHelper,
ee = ObjectsRegistry.EntityExplorer,
dataSources = ObjectsRegistry.DataSources;
let mockDBName: any;
describe("Validate Mock Query Active Ds querying & count", () => {
it("1. Create Query from Mock Mongo DB & verify active queries count", () => {
dataSources.NavigateToDSCreateNew();
agHelper.GetNClick(dataSources._mockDB("Movies"));
cy.wait("@getMockDb").then(($createdMock) => {
mockDBName = $createdMock.response?.body.data.name;
dataSources.CreateMockDB("Movies").then((mockDBName) => {
dataSources.CreateQuery(mockDBName);
dataSources.ValidateNSelectDropdown("Commands", "Find Document(s)");
agHelper.EnterValue("movies", {
@ -58,11 +53,7 @@ describe("Validate Mock Query Active Ds querying & count", () => {
});
it("2. Create Query from Mock Postgres DB & verify active queries count", () => {
dataSources.NavigateToDSCreateNew();
agHelper.GetNClick(dataSources._mockDB("Users"));
cy.wait("@getMockDb").then(($createdMock) => {
mockDBName = $createdMock.response?.body.data.name;
dataSources.CreateMockDB("Users").then((mockDBName) => {
dataSources.CreateQuery(mockDBName);
agHelper.GetNClick(dataSources._templateMenuOption("Select"));
dataSources.RunQueryNVerifyResponseViews(10);

View File

@ -1,9 +1,9 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
const jsEditor = ObjectsRegistry.JSEditor;
const agHelper = ObjectsRegistry.AggregateHelper;
const locators = ObjectsRegistry.CommonLocators;
const apiPage = ObjectsRegistry.ApiPage;
const deployMode = ObjectsRegistry.DeployMode;
const debuggerHelper = ObjectsRegistry.DebuggerHelper;
describe("Tests setTimeout API", function() {
it("1. Executes showAlert after 3 seconds and uses default value", () => {
@ -108,19 +108,14 @@ describe("Tests setTimeout API", function() {
},
);
agHelper.Sleep(2000);
agHelper.GetNClick(locators._debuggerIcon);
debuggerHelper.ClickDebuggerIcon();
agHelper.GetNClick(jsEditor._logsTab);
jsEditor.RunJSObj();
agHelper.GetNAssertContains(locators._debuggerLogMessage, "Hey there!");
agHelper.GetNAssertContains(locators._debuggerLogMessage, "Bye!");
agHelper.GetNAssertContains(
locators._debuggerLogMessage,
"Working!",
"not.exist",
100,
);
debuggerHelper.DoesConsoleLogExist("Hey there!");
debuggerHelper.DoesConsoleLogExist("Bye!");
debuggerHelper.DoesConsoleLogExist("Working!", false, undefined, 100);
agHelper.Sleep(3000);
agHelper.GetNAssertContains(locators._debuggerLogMessage, "Working!");
debuggerHelper.DoesConsoleLogExist("Working!");
});
it("4. Resolves promise after 3 seconds and shows alert", () => {

View File

@ -4,7 +4,8 @@ const datasource = require("../../../../locators/DatasourcesEditor.json");
const formControls = require("../../../../locators/FormControl.json");
import homePage from "../../../../locators/HomePage";
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
let ee = ObjectsRegistry.EntityExplorer;
const ee = ObjectsRegistry.EntityExplorer;
const dataSources = ObjectsRegistry.DataSources;
let datasourceName;
@ -63,7 +64,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
// cy.EvaluateCurrentValue(`{"find": "listingAndReviews","limit": 10}`);
cy.runQuery();
cy.xpath(queryLocators.countText).should("have.text", "10 Records");
dataSources.CheckResponseRecordsCount(10);
cy.deleteQueryUsingContext();
});
@ -81,18 +82,18 @@ describe("Create a query with a mongo datasource, run, save and then delete the
cy.typeValueNValidate("listingAndReviews", formControls.mongoCollection);
cy.runQuery();
cy.xpath(queryLocators.countText).should("have.text", "10 Records");
dataSources.CheckResponseRecordsCount(10);
cy.typeValueNValidate("{beds : {$lte: 2}}", formControls.mongoFindQuery);
cy.runQuery();
cy.xpath(queryLocators.countText).should("have.text", "10 Records");
dataSources.CheckResponseRecordsCount(10);
cy.typeValueNValidate(
"{number_of_reviews: -1}",
formControls.mongoFindSort,
); //sort descending
cy.runQuery();
cy.xpath(queryLocators.countText).should("have.text", "10 Records");
dataSources.CheckResponseRecordsCount(10);
cy.typeValueNValidate(
"{house_rules: 1, description:1}",
@ -108,7 +109,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
"Response is not as expected for Find commmand with multiple conditions",
);
});
cy.xpath(queryLocators.countText).should("have.text", "5 Records");
dataSources.CheckResponseRecordsCount(5);
cy.typeValueNValidate("2", formControls.mongoFindSkip); //Skip field
cy.onlyQueryRun();
@ -119,7 +120,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
"Response is not as expected for Find commmand with multiple conditions",
);
});
cy.xpath(queryLocators.countText).should("have.text", "5 Records");
dataSources.CheckResponseRecordsCount(5);
cy.deleteQueryUsingContext();
});
@ -418,7 +419,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
);
cy.runQuery();
cy.xpath(queryLocators.countText).should("have.text", "3 Records");
dataSources.CheckResponseRecordsCount(3);
cy.get("@dSName").then((dbName) => {
//cy.CheckAndUnfoldEntityItem("Datasources");

View File

@ -1,9 +0,0 @@
{
"debuggerIcon": ".t--debugger",
"debuggerLogState": ".t--debugger-log-state",
"debuggerLogMessage": ".t--debugger-log-message",
"debuggerClearLogs": ".t--debugger-clear-logs",
"errorCount": ".t--debugger-count",
"errorMessage": ".t--debugger-message",
"menuItem": ".t--debugger-contextual-menuitem"
}

View File

@ -23,7 +23,6 @@
"queryDelete": "//div[contains(@class, 't--template-menu')]//div[text()='Delete']",
"queryFromEmail":".CodeMirror-lines",
"codeTextArea": "//div[@class='CodeMirror-code']//span/span",
"countText": "//span[contains(@class, 'cs-text')][text()='Result:']/span",
"searchFilefield": "//input[@placeholder='Search File Prefix']",
"copyURLicon": "//button/span[@icon='link']",
"deleteFileicon": "//button/span[@icon='trash']/ancestor::div[contains(@class,'t--widget-iconbuttonwidget')]",

View File

@ -51,15 +51,8 @@ export class CommonLocators {
_createNew = ".t--entity-add-btn.group.files";
_uploadFiles = "div.uppy-Dashboard-AddFiles input";
_uploadBtn = "button.uppy-StatusBar-actionBtn--upload";
_debuggerIcon = ".t--debugger svg";
_errorTab = "[data-cy=t--tab-ERROR]";
_responseTab = "[data-cy=t--tab-response]";
_debugErrorMsg = ".t--debugger-message";
_debuggerLogState = ".t--debugger-log-state";
_debuggerLogMessage = ".t--debugger-log-message";
_debuggerLogMessageOccurence = ".t--debugger-log-message-occurence";
_debuggerClearLogs = ".t--debugger-clear-logs";
_debuggerLabel = "span.debugger-label";
_modal = ".t--modal-widget";
_entityProperties = (entityNameinLeftSidebar: string) =>
"//div[text()='" +
@ -154,8 +147,10 @@ export class CommonLocators {
_deployedPage = `.t--page-switch-tab`;
_hints = "ul.CodeMirror-hints li";
_cancelActionExecution = ".t--cancel-action-button";
_bottomPaneCollapseIcon = ".t--tabs-collapse-icon";
_dropDownMultiTreeValue = (dropdownOption: string) =>
"//span[@class='rc-tree-select-tree-title']/parent::span[@title='" + dropdownOption + "']";
_dropDownMultiTreeSelect = ".rc-tree-select-multiple"
_debuggerList = ".debugger-list";
"//span[@class='rc-tree-select-tree-title']/parent::span[@title='" +
dropdownOption +
"']";
_dropDownMultiTreeSelect = ".rc-tree-select-multiple";
}

View File

@ -11,7 +11,7 @@ import { PropertyPane } from "../Pages/PropertyPane";
import { DeployMode } from "../Pages/DeployModeHelper";
import { GitSync } from "../Pages/GitSync";
import { FakerHelper } from "../Pages/FakerHelper";
import { DebuggerHelper } from "../Pages/DebuggerHelper";
export class ObjectsRegistry {
private static aggregateHelper__: AggregateHelper;
@ -109,7 +109,7 @@ export class ObjectsRegistry {
}
return ObjectsRegistry.gitSync__;
}
private static fakerHelper__: FakerHelper;
static get FakerHelper(): FakerHelper {
if (ObjectsRegistry.fakerHelper__ === undefined) {
@ -117,6 +117,14 @@ export class ObjectsRegistry {
}
return ObjectsRegistry.fakerHelper__;
}
private static DebuggerHelper__: DebuggerHelper;
static get DebuggerHelper(): DebuggerHelper {
if (ObjectsRegistry.DebuggerHelper__ === undefined) {
ObjectsRegistry.DebuggerHelper__ = new DebuggerHelper();
}
return ObjectsRegistry.DebuggerHelper__;
}
}
export const initLocalstorageRegistry = () => {
@ -130,7 +138,7 @@ export const initLocalstorageRegistry = () => {
declare namespace Cypress {
namespace Cypress {
interface Chainable {
TypeTab: (shiftKey: Boolean, ctrlKey: boolean) => void;
TypeTab: (shiftKey: boolean, ctrlKey: boolean) => void;
}
}
}

View File

@ -815,17 +815,6 @@ export class AggregateHelper {
toClickUpload && this.GetNClick(this.locator._uploadBtn, 0, false);
}
public AssertDebugError(label: string, messgae: string) {
this.GetNClick(this.locator._debuggerIcon, 0, true, 0);
this.GetNClick(this.locator._errorTab, 0, true, 0);
this.GetText(this.locator._debuggerLabel, "text", 0).then(($text) => {
expect($text).to.eq(label);
});
this.GetText(this.locator._debugErrorMsg, "text", 0).then(($text) => {
expect($text).to.contains(messgae);
});
}
public AssertElementAbsence(selector: ElementType, timeout = 0) {
//Should not exists - cannot take indexes
return this.GetElement(selector, timeout).should("not.exist");
@ -841,6 +830,12 @@ export class AggregateHelper {
.invoke(textOrValue);
}
AssertHeight(selector: ElementType, height: number) {
return this.GetElement(selector)
.invoke("height")
.should("be.equal", height);
}
public AssertText(
selector: ElementType,
textOrValue: "text" | "val" = "text",
@ -895,13 +890,20 @@ export class AggregateHelper {
public GetNAssertContains(
selector: ElementType,
text: string | RegExp,
text: string | number | RegExp,
exists: "exist" | "not.exist" = "exist",
index?: number,
timeout?: number,
) {
return this.GetElement(selector, timeout)
.contains(text)
.should(exists);
if (index)
return this.GetElement(selector, timeout)
.eq(index)
.contains(text)
.should(exists);
else
return this.GetElement(selector, timeout)
.contains(text)
.should(exists);
}
public ScrollTo(

View File

@ -68,9 +68,7 @@ export class DataSources {
_queryResponse = (responseType: string) =>
"li[data-cy='t--tab-" + responseType + "']";
_queryRecordResult = (recordCount: number) =>
"//div/span[text()='Result:']/span[contains(text(),'" +
recordCount +
" Record')]";
`//div/span[text()='Result:']/span[contains(text(),' ${recordCount} Record')]`;
_noRecordFound = "span[data-testid='no-data-table-message']";
_usePreparedStatement =
"input[name='actionConfiguration.pluginSpecifiedTemplates[0].value'][type='checkbox']";
@ -222,6 +220,14 @@ export class DataSources {
cy.get(this._newDatabases).should("be.visible");
}
CreateMockDB(dbName: "Users" | "Movies"): Cypress.Chainable<string> {
this.NavigateToDSCreateNew();
this.agHelper.GetNClick(this._mockDB(dbName));
return cy
.wait("@getMockDb")
.then(($createdMock) => $createdMock.response?.body.data.name);
}
public FillPostgresDSForm(
shouldAddTrailingSpaces = false,
username = "",
@ -411,6 +417,11 @@ export class DataSources {
this.agHelper.Sleep(2000); //for the CreateQuery
}
DeleteQuery(queryName: string) {
this.ee.ExpandCollapseEntity("Queries/JS");
this.ee.ActionContextMenuByEntityName(queryName, "Delete", "Are you sure?");
}
public ValidateNSelectDropdown(
ddTitle: string,
currentValue = "",
@ -513,7 +524,7 @@ export class DataSources {
}
public RunQueryNVerifyResponseViews(
expectdRecordCount = 1,
expectedRecordsCount = 1,
tableCheck = true,
) {
this.RunQuery();
@ -521,8 +532,12 @@ export class DataSources {
this.agHelper.AssertElementVisible(this._queryResponse("TABLE"));
this.agHelper.AssertElementVisible(this._queryResponse("JSON"));
this.agHelper.AssertElementVisible(this._queryResponse("RAW"));
this.CheckResponseRecordsCount(expectedRecordsCount);
}
public CheckResponseRecordsCount(expectedRecordCount: number) {
this.agHelper.AssertElementVisible(
this._queryRecordResult(expectdRecordCount),
this._queryRecordResult(expectedRecordCount),
);
}

View File

@ -0,0 +1,193 @@
import { ObjectsRegistry } from "../Objects/Registry";
export enum PageType {
Canvas,
API,
Query,
JsEditor,
}
export class DebuggerHelper {
private agHelper = ObjectsRegistry.AggregateHelper;
private commonLocators = ObjectsRegistry.CommonLocators;
// ActionExecutionResizerHeight -> in repo
private readonly bottomPaneHeight = 307;
// from design system
private readonly TAB_MIN_HEIGHT = 36;
public readonly locators = {
_debuggerIcon: ".t--debugger svg",
_tabsContainer: ".t--debugger-tabs-container",
_closeButton: ".t--close-debugger",
_logMessage: ".t--debugger-log-message",
_logState: ".t--debugger-log-state",
_errorCount: ".t--debugger-count",
_clearLogs: ".t--debugger-clear-logs",
_logMessageOccurence: ".t--debugger-log-message-occurence",
_debuggerMessage: ".t--debugger-message",
_contextMenuItem: ".t--debugger-contextual-menuitem",
_debuggerLabel: "span.debugger-label",
_bottomPaneContainer: {
[PageType.API]: ".t--api-bottom-pane-container",
[PageType.Query]: ".t--query-bottom-pane-container",
[PageType.JsEditor]: ".t--js-editor-bottom-pane-container",
},
_debuggerList: ".debugger-list",
};
ClickDebuggerIcon(
index?: number,
force?: boolean,
waitTimeInterval?: number,
) {
this.agHelper.GetNClick(
this.locators._debuggerIcon,
index,
force,
waitTimeInterval,
);
}
ClickResponseTab() {
this.agHelper.GetNClick(this.commonLocators._responseTab);
}
Close(pageType: PageType) {
switch (pageType) {
case PageType.Canvas:
this.agHelper.GetNClick(this.locators._closeButton);
break;
case PageType.API:
case PageType.Query:
case PageType.JsEditor:
this.agHelper.GetNClick(this.commonLocators._bottomPaneCollapseIcon);
break;
}
}
AssertOpen(pageType: PageType) {
switch (pageType) {
case PageType.Canvas:
this.agHelper.AssertElementExist(this.locators._tabsContainer);
break;
case PageType.API:
case PageType.JsEditor:
this.agHelper.AssertHeight(
this.locators._bottomPaneContainer[pageType],
this.bottomPaneHeight,
);
break;
case PageType.Query:
this.agHelper.AssertHeight(
this.locators._bottomPaneContainer[pageType],
this.bottomPaneHeight - 1, // -1 to offset error
);
break;
}
}
AssertClosed(pageType: PageType) {
switch (pageType) {
case PageType.Canvas:
this.agHelper.AssertElementAbsence(this.locators._tabsContainer);
break;
case PageType.API:
case PageType.JsEditor:
this.agHelper.AssertHeight(
this.locators._bottomPaneContainer[pageType],
this.TAB_MIN_HEIGHT,
);
break;
case PageType.Query:
this.agHelper.AssertHeight(
this.locators._bottomPaneContainer[pageType],
this.TAB_MIN_HEIGHT - 1, // -1 to offset error
);
break;
}
}
DoesConsoleLogExist(
text: string,
exists = true,
index?: number,
timeout?: number,
) {
this.agHelper.GetNAssertContains(
this.locators._logMessage,
text,
exists ? "exist" : "not.exist",
index,
timeout,
);
}
LogStateContains(text: string, index?: number) {
this.agHelper.GetNAssertContains(
this.locators._logState,
text,
"exist",
index,
);
}
AssertErrorCount(count: number) {
count > 0
? this.agHelper.GetNAssertContains(this.locators._errorCount, count)
: this.agHelper.AssertElementAbsence(this.locators._errorCount);
}
ClearLogs() {
this.agHelper.GetNClick(this.locators._clearLogs);
}
Assert_Consecutive_Console_Log_Count(count: number) {
count > 0
? this.agHelper.GetNAssertContains(
this.locators._logMessageOccurence,
count,
)
: this.agHelper.AssertElementAbsence(this.locators._logMessageOccurence);
}
AssertVisibleErrorMessagesCount(count: number) {
if (count > 0) {
this.agHelper.AssertElementVisible(this.locators._debuggerMessage);
this.agHelper.AssertElementLength(this.locators._debuggerMessage, count);
} else {
this.agHelper.AssertElementAbsence(this.locators._debuggerMessage);
}
}
ClickErrorMessage(index?: number) {
this.agHelper.GetNClick(this.locators._debuggerMessage, index);
}
AssertContextMenuItemVisible() {
this.agHelper.AssertElementVisible(this.locators._contextMenuItem);
}
AssertDebugError(label: string, message: string) {
this.ClickDebuggerIcon();
this.agHelper.GetNClick(this.commonLocators._errorTab, 0, true, 0);
this.agHelper
.GetText(this.locators._debuggerLabel, "text", 0)
.then(($text) => {
expect($text).to.eq(label);
});
this.agHelper
.GetText(this.locators._debuggerMessage, "text", 0)
.then(($text) => {
expect($text).to.contains(message);
});
}
DebuggerListDoesnotContain(text: string) {
this.agHelper.AssertContains(
text,
"not.exist",
this.locators._debuggerList,
);
}
}

View File

@ -36,6 +36,7 @@ import {
Category,
Icon,
Size,
TAB_MIN_HEIGHT,
Text,
TextType,
} from "design-system";
@ -74,10 +75,6 @@ const ResponseContainer = styled.div`
.react-tabs__tab-panel {
overflow: hidden;
}
.react-tabs__tab-panel > * {
padding-bottom: 10px;
}
`;
const ResponseMetaInfo = styled.div`
display: flex;
@ -91,8 +88,8 @@ const ResponseMetaWrapper = styled.div`
align-items: center;
display: flex;
position: absolute;
right: ${(props) => props.theme.spaces[12]}px;
top: ${(props) => props.theme.spaces[4]}px;
right: ${(props) => props.theme.spaces[17] + 1}px;
top: ${(props) => props.theme.spaces[2] + 1}px;
`;
const ResponseTabWrapper = styled.div`
@ -108,12 +105,13 @@ const TabbedViewWrapper = styled.div`
&&& {
ul.react-tabs__tab-list {
margin: 0px ${(props) => props.theme.spaces[11]}px;
height: ${TAB_MIN_HEIGHT};
}
}
& {
.react-tabs__tab-panel {
height: calc(100% - 32px);
height: calc(100% - ${TAB_MIN_HEIGHT});
}
}
`;
@ -181,7 +179,6 @@ const HelpSection = styled.div`
`;
const ResponseBodyContainer = styled.div`
padding-top: 10px;
overflow-y: auto;
height: 100%;
display: grid;
@ -555,7 +552,7 @@ function ApiResponseView(props: Props) {
];
return (
<ResponseContainer ref={panelRef}>
<ResponseContainer className="t--api-bottom-pane-container" ref={panelRef}>
<Resizer
initialHeight={responsePaneHeight}
onResizeComplete={(height: number) => {
@ -633,6 +630,8 @@ function ApiResponseView(props: Props) {
</ResponseMetaWrapper>
)}
<EntityBottomTabs
containerRef={panelRef}
expandedHeight={`${ActionExecutionResizerHeight}px`}
onSelect={updateSelectedResponseTab}
selectedTabKey={selectedResponseTab}
tabs={tabs}

View File

@ -21,6 +21,7 @@ import { DEBUGGER_TAB_KEYS } from "./helpers";
import { Colors } from "constants/Colors";
import EntityBottomTabs from "../EntityBottomTabs";
import { getSelectedCanvasDebuggerTab } from "selectors/editorContextSelectors";
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
const TABS_HEADER_HEIGHT = 36;
@ -28,7 +29,7 @@ const Container = styled.div`
${ResizerCSS}
position: absolute;
bottom: 0;
height: 25%;
height: ${ActionExecutionResizerHeight}px;
min-height: ${TABS_HEADER_HEIGHT}px;
background-color: ${(props) => props.theme.colors.debugger.background};
border-top: 1px solid ${Colors.ALTO};
@ -76,18 +77,23 @@ function DebuggerTabs() {
const onClose = () => dispatch(showDebugger(false));
return (
<Container onClick={stopEventPropagation} ref={panelRef}>
<Container
className="t--debugger-tabs-container"
onClick={stopEventPropagation}
ref={panelRef}
>
<Resizer panelRef={panelRef} />
<EntityBottomTabs
expandedHeight={`${ActionExecutionResizerHeight}px`}
onSelect={setSelectedTab}
selectedTabKey={selectedTab}
tabs={DEBUGGER_TABS}
/>
<Icon
className="close-debugger t--close-debugger"
name="cross"
name="expand-more"
onClick={onClose}
size={IconSize.SMALL}
size={IconSize.XXXXL}
/>
</Container>
);

View File

@ -39,7 +39,6 @@ import { DebugButton } from "./Debugger/DebugCTA";
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
import EntityBottomTabs from "./EntityBottomTabs";
import { TAB_MIN_HEIGHT } from "design-system";
import { theme } from "constants/DefaultTheme";
import { CodeEditorWithGutterStyles } from "pages/Editor/JSEditor/constants";
import { getIsSavingEntity } from "selectors/editorSelectors";
import { getJSResponseViewState } from "./utils";
@ -51,6 +50,7 @@ import {
setJsPaneResponsePaneHeight,
setJsPaneResponseSelectedTab,
} from "actions/jsPaneActions";
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
const ResponseContainer = styled.div`
${ResizerCSS}
@ -58,7 +58,7 @@ const ResponseContainer = styled.div`
// Minimum height of bottom tabs as it can be resized
min-height: ${TAB_MIN_HEIGHT};
background-color: ${(props) => props.theme.colors.apiPane.responseBody.bg};
height: ${({ theme }) => theme.actionsBottomTabInitialHeight};
height: ${ActionExecutionResizerHeight}px;
.react-tabs__tab-panel {
${CodeEditorWithGutterStyles}
@ -329,7 +329,10 @@ function JSResponseView(props: Props) {
}, []);
return (
<ResponseContainer ref={panelRef}>
<ResponseContainer
className="t--js-editor-bottom-pane-container"
ref={panelRef}
>
<Resizer
initialHeight={responseTabHeight}
onResizeComplete={setResponseHeight}
@ -338,7 +341,7 @@ function JSResponseView(props: Props) {
<TabbedViewWrapper>
<EntityBottomTabs
containerRef={panelRef}
expandedHeight={theme.actionsBottomTabInitialHeight}
expandedHeight={`${ActionExecutionResizerHeight}px`}
onSelect={setSelectedResponseTab}
selectedTabKey={selectedResponseTab}
tabs={tabs}

View File

@ -449,7 +449,6 @@ export type Theme = {
canvasBottomPadding: number;
navbarMenuHeight: string;
navbarMenuLineHeight: string;
actionsBottomTabInitialHeight: string;
sideNav: {
minWidth: number;
maxWidth: number;
@ -2996,7 +2995,6 @@ export const theme: Theme = {
},
pageContentWidth: 1224,
tabPanelHeight: 34,
actionsBottomTabInitialHeight: "40%",
alert: {
info: {
color: Colors.AZURE_RADIANCE,

View File

@ -217,7 +217,7 @@ const Link = styled.a`
const Wrapper = styled.div`
display: flex;
flex-direction: row;
height: calc(100% - 110px);
height: calc(100% - 135px);
position: relative;
`;
export interface CommonFormProps {

View File

@ -102,7 +102,6 @@ import {
import {
responseTabComponent,
InlineButton,
SectionDivider,
CancelRequestButton,
LoadingOverlayContainer,
handleCancelActionExecution,
@ -155,7 +154,7 @@ const ErrorMessage = styled.p`
export const TabbedViewContainer = styled.div`
${ResizerCSS}
height: ${(props) => props.theme.actionsBottomTabInitialHeight};
height: ${ActionExecutionResizerHeight}px;
// Minimum height of bottom tabs as it can be resized
min-height: 36px;
width: 100%;
@ -188,8 +187,8 @@ const SettingsWrapper = styled.div`
const ResultsCount = styled.div`
position: absolute;
right: 13px;
top: 8px;
right: ${(props) => props.theme.spaces[17] + 1}px;
top: ${(props) => props.theme.spaces[2] + 1}px;
color: #716e6e;
`;
@ -774,7 +773,7 @@ export function EditorJSONtoForm(props: Props) {
const responseTabs = [
{
key: "Response",
key: "response",
title: "Response",
panelComponent: (
<ResponseContentWrapper>
@ -1062,7 +1061,10 @@ export function EditorJSONtoForm(props: Props) {
/>
</TabContainerView>
<TabbedViewContainer ref={panelRef}>
<TabbedViewContainer
className="t--query-bottom-pane-container"
ref={panelRef}
>
<Resizable
initialHeight={responsePaneHeight}
onResizeComplete={(height: number) =>
@ -1072,7 +1074,6 @@ export function EditorJSONtoForm(props: Props) {
panelRef={panelRef}
snapToHeight={ActionExecutionResizerHeight}
/>
<SectionDivider />
{isRunning && (
<>
<LoadingOverlayScreen theme={EditorTheme.LIGHT} />
@ -1101,7 +1102,7 @@ export function EditorJSONtoForm(props: Props) {
<ResultsCount>
<Text type={TextType.P3}>
Result:
<Text type={TextType.H5}>{`${output.length} Record${
<Text type={TextType.H5}>{` ${output.length} Record${
output.length > 1 ? "s" : ""
}`}</Text>
</Text>
@ -1109,6 +1110,8 @@ export function EditorJSONtoForm(props: Props) {
)}
<EntityBottomTabs
containerRef={panelRef}
expandedHeight={`${ActionExecutionResizerHeight}px`}
onSelect={setSelectedResponseTab}
selectedTabKey={selectedResponseTab}
tabs={responseTabs}