feat: query creation dumb templates replaced with smart templates (#24234)

## Description
 
This PR replaces dumb template that is shown on new query creation with
smart templates. With current implementation whenever we create a new DB
query, we see this template before writing the query, when we select any
of the template options, it shows us template query like `SELECT * FROM
users ORDER BY id LIMIT 10;` Since its a template query, users table may
not exist in user's actual database, thus leading them to error results.
<img width="1174" alt="Screenshot 2023-06-09 at 2 45 40 PM"
src="https://github.com/appsmithorg/appsmith/assets/30018882/4dede184-439f-4064-abe0-faf7b236748e">

With new implementation, we are removing this template page, instead if
we have the structure of the datasource available, we would simply get
the first table from the structure, and create select query using that.
This way we are populating query editor with user's actual table names
rather than dumb table name like `users`. Thus leading users to create
successful query

Note: This change is done only for sql plugins like MySQL, MSSQL,
PostgreSQL, Redshift, Oracle, Snowflake.

#### PR fixes following issue(s)
Fixes #23960 
> if no issue exists, please create an issue and ask the maintainers
about this first
>
>
#### Media
> A video or a GIF is preferred. when using Loom, don’t embed because it
looks like it’s a GIF. instead, just link to the video
>
>
#### Type of change
- New feature (non-breaking change which adds functionality)
>
>
>
## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [x] Manual
- [ ] Jest
- [x] Cypress
>
>
#### Test Plan
> Create a Connection on the DB 
> Create a Query from the established Query
> Ensure the 1st table data is placed when Add Query button is clicked
from the Review page
> If the query is created from Entity explorer ensure the right table
name is been added

#### Issues raised during DP testing
> Link issues raised during DP testing for better visibility and
tracking (copy link from comments dropped on this PR)
>
>
>
## 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
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change)
have been covered
- [x] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [x] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [x] Cypress test cases have been added and approved by SDET/manual QA
- [x] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed

---------

Co-authored-by: “sneha122” <“sneha@appsmith.com”>
Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
sneha122 2023-06-19 15:23:34 +05:30 committed by GitHub
parent a85c2b5e7c
commit f36bcf2a6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 169 additions and 300 deletions

View File

@ -13,7 +13,7 @@ describe("SQL Autocompletion", () => {
dsName = $dsName;
//Shows autocompletion hints in SQL", () => {
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery("");
agHelper.TypeText(locators._codeMirrorTextArea, "select");
// Hints should exist
agHelper.AssertElementExist(locators._hints);

View File

@ -20,11 +20,8 @@ describe("Addwidget from Query and bind with other widgets", function () {
datasourceName = httpResponse.response.body.data.name;
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click();
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM configs LIMIT 10;");
// Resetting the default query and rewriting a new one
_.dataSources.EnterQuery("SELECT * FROM configs LIMIT 10;");
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000);
// Mock the response for this test

View File

@ -28,7 +28,6 @@ describe("Bug #14299 - The data from the query does not show up on the widget",
it("1. Creating query & JSObject", () => {
query = `SELECT id, name, date_of_birth, date_of_death, nationality FROM public."astronauts" LIMIT 20;`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("getAstronauts");
jsEditor.CreateJSObject(

View File

@ -38,8 +38,7 @@ describe("Entity explorer tests related to copy query", function () {
200,
);
cy.get(queryLocators.templateMenu).click();
cy.get(".CodeMirror textarea").first().focus().type("select * from users");
dataSources.EnterQuery("select * from users");
cy.EvaluateCurrentValue("select * from users");
cy.get(".t--action-name-edit-field").click({ force: true });

View File

@ -1,7 +1,10 @@
const explorer = require("../../../../locators/explorerlocators.json");
const queryLocators = require("../../../../locators/QueryEditor.json");
const apiwidget = require("../../../../locators/apiWidgetslocator.json");
import { entityExplorer } from "../../../../support/Objects/ObjectsCore";
import {
entityExplorer,
dataSources,
} from "../../../../support/Objects/ObjectsCore";
describe("Entity explorer datasource structure", function () {
let datasourceName;
@ -71,7 +74,6 @@ describe("Entity explorer datasource structure", function () {
it("2. Refresh datasource structure", function () {
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
//cy.GlobalSearchEntity(datasourceName);
// cy.get(`.t--entity.datasource:contains(${datasourceName})`)
@ -87,7 +89,7 @@ describe("Entity explorer datasource structure", function () {
const tableName = Math.random()
.toString(36)
.replace(/[^a-z]+/g, "");
cy.typeValueNValidate(`CREATE TABLE public.${tableName} ( ID int );`);
dataSources.EnterQuery(`CREATE TABLE public.${tableName} ( ID int );`);
cy.onlyQueryRun();
cy.wait("@postExecute").then(({ response }) => {
expect(response.body.data.request.requestParams.Query.value).to.contain(

View File

@ -83,8 +83,7 @@ describe("Entity explorer tests related to query and datasource", function () {
200,
);
// cy.get(queryLocators.templateMenu).click();
cy.get(".CodeMirror textarea").first().focus().type("select * from users");
dataSources.EnterQuery("select * from users");
cy.EvaluateCurrentValue("select * from users");
cy.get(".t--action-name-edit-field").click({ force: true });

View File

@ -63,7 +63,6 @@ describe("Git discard changes:", function () {
cy.wait("@getPage");
// create new postgres query
dataSources.NavigateFromActiveDS(datasourceName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(`SELECT * FROM public."category" LIMIT 10;`);
agHelper.RenameWithInPane(query2);
dataSources.RunQuery();

View File

@ -288,7 +288,6 @@ describe("Git sync apps", function () {
// create postgres select query
//cy.CheckAndUnfoldEntityItem("Datasources");
dataSources.NavigateFromActiveDS(datasourceName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery("SELECT * FROM users ORDER BY id LIMIT 10;");
agHelper.RenameWithInPane("get_users");
dataSources.RunQuery();

View File

@ -47,7 +47,6 @@ const clickButtonAndAssertLintError = (
const createMySQLDatasourceQuery = () => {
// Create Query
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
const tableCreateQuery = `SELECT * FROM spacecrafts LIMIT 10;`;
dataSources.EnterQuery(tableCreateQuery);
};

View File

@ -19,12 +19,7 @@ describe("Add widget - Postgress DataSource", function () {
_.autoLayout.ConvertToAutoLayoutAndVerify(false);
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click();
cy.wait(500);
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("select * from public.configs");
_.dataSources.EnterQuery("select * from public.configs");
cy.WaitAutoSave();
cy.runQuery();
cy.get(queryEditor.suggestedTableWidget).click();

View File

@ -97,7 +97,7 @@ describe("Entity bottom bar", () => {
_.debuggerHelper.CloseBottomBar();
_.debuggerHelper.AssertClosed();
//Create and run query.
_.agHelper.GetNClick(_.dataSources._templateMenu);
_.dataSources.EnterQuery(
"SELECT * FROM users ORDER BY id LIMIT 10;",
1000,
@ -131,7 +131,6 @@ describe("Entity bottom bar", () => {
_.debuggerHelper.CloseBottomBar();
_.debuggerHelper.AssertClosed();
//Create and run query.
_.agHelper.GetNClick(_.dataSources._templateMenu);
_.dataSources.EnterQuery("SELECT * FROM users ORDER BY id LIMIT 10;", 1000);
_.dataSources.RunQuery();
//Verify if bottom bar is open on executing query.

View File

@ -97,7 +97,8 @@ describe("Undo/Redo functionality", function () {
it("3. Checks undo/redo in query editor", () => {
dataSources.NavigateFromActiveDS(postgresDatasourceName, true);
cy.get(queryLocators.templateMenu).click();
// Resetting the default query and rewriting a new one
dataSources.EnterQuery("");
cy.get(".CodeMirror textarea").first().focus().type("{{FirstAPI}}", {
force: true,
parseSpecialCharSequences: false,

View File

@ -35,18 +35,11 @@ describe("Chart Widget Skeleton Loading Functionality", function () {
cy.wait(2000);
_.dataSources.CreateMockDB("Users").then((dbName) => {
_.dataSources.CreateQueryFromActiveTab(dbName, false);
_.agHelper.GetNClick(_.dataSources._templateMenuOption("Select"));
_.dataSources.ToggleUsePreparedStatement(false);
});
// Step6.2: writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users ORDER BY id LIMIT 10;", {
force: true,
parseSpecialCharSequences: false,
});
_.dataSources.EnterQuery("SELECT * FROM users ORDER BY id LIMIT 10;");
cy.WaitAutoSave();
//Step7:
@ -120,16 +113,8 @@ describe("Chart Widget Skeleton Loading Functionality", function () {
cy.get(queryLocators.switch).last().click({ force: true });
cy.get(queryLocators.templateMenu).click();
cy.xpath(queryLocators.query).click({ force: true });
_.dataSources.EnterQuery("SELECT * FROM users ORDER BY id LIMIT 10;");
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users ORDER BY id LIMIT 10;", {
force: true,
parseSpecialCharSequences: false,
});
cy.WaitAutoSave();
cy.runQuery();

View File

@ -165,20 +165,13 @@ describe("List widget V2 page number and page size", () => {
cy.wait(2000);
_.dataSources.CreateMockDB("Users").then((dbName) => {
_.dataSources.CreateQueryFromActiveTab(dbName, false);
_.agHelper.GetNClick(_.dataSources._templateMenuOption("Select"));
_.dataSources.ToggleUsePreparedStatement(false);
});
// writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type(
"SELECT * FROM users OFFSET {{List1.pageNo * List1.pageSize}} LIMIT {{List1.pageSize}};",
{
force: true,
parseSpecialCharSequences: false,
},
);
_.dataSources.EnterQuery(
"SELECT * FROM users OFFSET {{List1.pageNo * List1.pageSize}} LIMIT {{List1.pageSize}};",
);
cy.WaitAutoSave();
cy.runQuery();
@ -222,21 +215,10 @@ describe("List widget V2 page number and page size", () => {
// switching off Use Prepared Statement toggle
cy.get(queryLocators.switch).last().click({ force: true });
//.1: Click on Write query area
cy.get(queryLocators.templateMenu).click();
cy.xpath(queryLocators.query).click({ force: true });
_.dataSources.EnterQuery(
"SELECT * FROM users OFFSET {{List1.pageNo * 1}} LIMIT {{List1.pageSize}};",
);
// writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type(
"SELECT * FROM users OFFSET {{List1.pageNo * 1}} LIMIT {{List1.pageSize}};",
{
force: true,
parseSpecialCharSequences: false,
},
);
cy.WaitAutoSave();
cy.runQuery();

View File

@ -17,7 +17,6 @@ describe("List widget v2 - Basic server side data tests", () => {
// Create sample(mock) user database.
_.dataSources.CreateMockDB("Users").then((dbName) => {
_.dataSources.CreateQueryFromActiveTab(dbName, false);
_.agHelper.GetNClick(_.dataSources._templateMenu);
_.dataSources.ToggleUsePreparedStatement(false);
_.dataSources.EnterQuery(
"SELECT * FROM users OFFSET {{List1.pageNo * List1.pageSize}} LIMIT {{List1.pageSize}};",
@ -32,7 +31,6 @@ describe("List widget v2 - Basic server side data tests", () => {
_.dataSources.NavigateToActiveTab();
cy.wait(1000);
_.dataSources.CreateQueryFromActiveTab($dsName, false);
_.agHelper.GetNClick(_.dataSources._templateMenuOption("Select"));
_.dataSources.ToggleUsePreparedStatement(false);
_.dataSources.EnterQuery(
"SELECT * FROM users OFFSET {{List1.pageNo * 1}} LIMIT {{List1.pageSize}};",
@ -358,19 +356,9 @@ describe("List widget v2 - Basic server side data tests", () => {
});
//.1: Click on Write query area
cy.get(queryLocators.templateMenu).click();
cy.xpath(queryLocators.query).click({
force: true,
});
// writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users LIMIT 20;", {
force: true,
parseSpecialCharSequences: false,
});
_.dataSources.EnterQuery("SELECT * FROM users LIMIT 20;");
cy.WaitAutoSave();
cy.runQuery();
@ -412,19 +400,8 @@ describe("List widget v2 - Basic server side data tests", () => {
});
//.1: Click on Write query area
cy.get(queryLocators.templateMenu).click();
cy.xpath(queryLocators.query).click({
force: true,
});
_.dataSources.EnterQuery("SELECT * FROM users LIMIT 20;");
// writing query to get the schema
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users LIMIT 20;", {
force: true,
parseSpecialCharSequences: false,
});
cy.WaitAutoSave();
cy.runQuery();

View File

@ -18,7 +18,8 @@ describe("Table Widget property pane feature validation", function () {
cy.openPropertyPane("tablewidget");
// Select show message in the "on selected row" dropdown
cy.getAlert("onRowSelected", "Row is selected");
_.deployMode.DeployApp();
_.deployMode.DeployApp(_.locators._widgetInDeployed("tablewidget"));
_.table.WaitUntilTableLoad(0, 0, "v1");
// Select 1st row
cy.isSelectRow(2);
cy.wait(2000);
@ -32,7 +33,8 @@ describe("Table Widget property pane feature validation", function () {
cy.openPropertyPane("tablewidget");
// Select show message in the "on selected row" dropdown
cy.getAlert("onPageChange", "Page Changed");
_.deployMode.DeployApp();
_.deployMode.DeployApp(_.locators._widgetInDeployed("tablewidget"));
_.table.WaitUntilTableLoad(0, 0, "v1");
cy.wait(2000);
// Change the page
cy.get(widgetsPage.nextPageButton).click({ force: true });
@ -46,7 +48,8 @@ describe("Table Widget property pane feature validation", function () {
cy.openPropertyPane("tablewidget");
// Show Message on Search text change Action
cy.getAlert("onSearchTextChanged", "Search Text Changed");
_.deployMode.DeployApp();
_.deployMode.DeployApp(_.locators._widgetInDeployed("tablewidget"));
_.table.WaitUntilTableLoad(0, 0, "v1");
// Change the Search text
cy.get(widgetsPage.searchField).type("Hello");
cy.wait(2000);
@ -268,7 +271,8 @@ describe("Table Widget property pane feature validation", function () {
cy.backFromPropertyPanel();
// Chage deat search text value to "data"
cy.testJsontext("defaultsearchtext", "data");
_.deployMode.DeployApp();
_.deployMode.DeployApp(_.locators._widgetInDeployed("tablewidget"));
_.table.WaitUntilTableLoad(0, 0, "v1");
// Verify the deaullt search text
cy.get(widgetsPage.searchField).should("have.value", "data");
_.deployMode.NavigateBacktoEditor();
@ -282,7 +286,8 @@ describe("Table Widget property pane feature validation", function () {
// Change default selected row value to 1
cy.get(widgetsPage.defaultSelectedRowField).type("1");
cy.wait(2000);
_.deployMode.DeployApp();
_.deployMode.DeployApp(_.locators._widgetInDeployed("tablewidget"));
_.table.WaitUntilTableLoad(0, 0, "v1");
// Verify the default selected row
cy.get(widgetsPage.selectedRow).should(
"have.css",

View File

@ -4,6 +4,8 @@ import {
propPane,
agHelper,
deployMode,
draggableWidgets,
locators,
} from "../../../../../support/Objects/ObjectsCore";
const widgetsPage = require("../../../../../locators/Widgets.json");
const commonlocators = require("../../../../../locators/commonlocators.json");
@ -68,7 +70,8 @@ describe("Table Widget V2 property pane feature validation", function () {
cy.openPropertyPane("tablewidgetv2");
// Select show message in the "on selected row" dropdown
cy.getAlert("onRowSelected", "Row is selected");
deployMode.DeployApp();
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
table.WaitUntilTableLoad(0, 0, "v2");
// Select 1st row
cy.isSelectRow(2);
cy.wait(2000);
@ -82,7 +85,8 @@ describe("Table Widget V2 property pane feature validation", function () {
cy.openPropertyPane("tablewidgetv2");
// Show Message on Search text change Action
cy.getAlert("onSearchTextChanged", "Search Text Changed");
deployMode.DeployApp();
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
table.WaitUntilTableLoad(0, 0, "v2");
// Change the Search text
cy.get(widgetsPage.searchField).type("Hello");
cy.wait(2000);
@ -99,7 +103,8 @@ describe("Table Widget V2 property pane feature validation", function () {
});
// Select show message in the "on selected row" dropdown
cy.getAlert("onPageChange", "Page Changed");
deployMode.DeployApp();
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
table.WaitUntilTableLoad(0, 0, "v2");
cy.wait(2000);
// Change the page
cy.get(widgetsPage.nextPageButton).click({ force: true });
@ -335,7 +340,8 @@ describe("Table Widget V2 property pane feature validation", function () {
// Chage deat search text value to "data"
cy.backFromPropertyPanel();
cy.testJsontext("defaultsearchtext", "data");
deployMode.DeployApp();
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
table.WaitForTableEmpty("v2");
// Verify the deaullt search text
cy.get(widgetsPage.searchField).should("have.value", "data");
deployMode.NavigateBacktoEditor();

View File

@ -21,7 +21,6 @@ describe("Block Action Execution when no field is present", () => {
agHelper.Sleep(1000);
dataSources.CreateQueryAfterDSSaved();
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery("SELECT * from users");
dataSources.AssertRunButtonDisability(false);
dataSources.EnterQuery("");
@ -37,7 +36,6 @@ describe("Block Action Execution when no field is present", () => {
agHelper.Sleep(1000);
dataSources.CreateQueryAfterDSSaved();
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery("SELECT * from users");
dataSources.AssertRunButtonDisability(false);
dataSources.EnterQuery("");

View File

@ -147,7 +147,6 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("CreateProductLines");
dataSources.EnterQuery(tableCreateQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);
@ -274,7 +273,6 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
it("9. Validate Drop of the Newly Created - Stores - Table from MySQL datasource", () => {
let deleteTblQuery = "DROP TABLE productlines;";
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("DropProductlines");
dataSources.EnterQuery(deleteTblQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -58,7 +58,6 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
INSERT INTO Stores(store_id,name,store_status,store_address,store_secret_code) VALUES (2188,'Kind''s Jack and Jill Food Center','I','110 S Main Sigourney, IA 525910000 (41.333550830000036, -92.20522134099997)',NULL);
INSERT INTO Stores(store_id,name,store_status,store_address,store_secret_code) VALUES (2190,'Central City Liquor, Inc.','A','1460 2nd Ave Des Moines, IA 503140000 (41.60557033500004, -93.61982683699995)',NULL);`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("CreateStores");
dataSources.EnterQuery(tableCreateQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);
@ -364,7 +363,6 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => {
it("12. Validate Drop of the Newly Created - Stores - Table from MySQL datasource", () => {
let deleteTblQuery = "DROP TABLE Stores;";
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("DropStores");
dataSources.EnterQuery(deleteTblQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -50,7 +50,7 @@ describe("Validate Postgres Generate CRUD with JSON Form", () => {
`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("CreateVessels");
dataSources.EnterQuery(tableCreateQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);
@ -619,7 +619,6 @@ describe("Validate Postgres Generate CRUD with JSON Form", () => {
it("17. Validate Drop of the Newly Created - Vessels - Table from Postgres datasource", () => {
const deleteTblQuery = "DROP TABLE Vessels;";
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("DropVessels");
dataSources.EnterQuery(deleteTblQuery);
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -39,7 +39,6 @@ describe("JSObjects OnLoad Actions tests", function () {
);
jsEditor.EnableDisableAsyncFuncSettings("getEmployee", false, true); //Only before calling confirmation is enabled by User here
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("GetEmployee");
cy.get("@jsObjName").then((jsObjName) => {
jsName = jsObjName;

View File

@ -40,8 +40,8 @@ describe("Cyclic Dependency Informational Error Messages", function () {
//Step1 : Create Mock Users DB
dataSources.CreateMockDB("Users").then((dbName) => {
dataSources.CreateQueryFromActiveTab(dbName, false);
agHelper.GetNClick(dataSources._templateMenuOption("Select"));
dataSources.ToggleUsePreparedStatement(false);
dataSources.EnterQuery("SELECT * FROM users LIMIT 10");
});
entityExplorer.NavigateToSwitcher("Widgets");
cy.openPropertyPane("inputwidgetv2");
@ -68,7 +68,7 @@ describe("Cyclic Dependency Informational Error Messages", function () {
});
cy.wait(1000);
cy.get(datasource.createQuery).click();
agHelper.GetNClick(dataSources._templateMenuOption("Select"));
dataSources.EnterQuery("SELECT * FROM users LIMIT 10");
dataSources.ToggleUsePreparedStatement(false);
entityExplorer.NavigateToSwitcher("Widgets");
cy.openPropertyPane("inputwidgetv2");

View File

@ -61,7 +61,6 @@ describe("Test Postgres number of connections on page load + Bug 11572, Bug 1120
//Create 10 queries
for (let i = 1; i <= 10; i++) {
dataSources.NavigateFromActiveDS(dsName_2, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("Query_" + i);
const userCreateQuery = `select table_name from information_schema.tables where table_schema='public' and table_type='BASE TABLE';`;
dataSources.EnterQuery(userCreateQuery);
@ -92,7 +91,6 @@ describe("Test Postgres number of connections on page load + Bug 11572, Bug 1120
it("4. Run query to drop any open connections before deploy and then deploy app", () => {
dataSources.NavigateFromActiveDS(dsName_1, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("check_number_of_connections_1");
const userName = "test_conn_user_" + guid;
const dropConnections =
@ -115,7 +113,6 @@ describe("Test Postgres number of connections on page load + Bug 11572, Bug 1120
it("5. Run query to check number of open connections after deploy", () => {
dataSources.NavigateFromActiveDS(dsName_2, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("check_number_of_connections_2");
const checkNoOfConnQuery =
`select count(*) from pg_stat_activity where usename='test_conn_user_` +

View File

@ -1,7 +1,11 @@
const publishPage = require("../../../../locators/publishWidgetspage.json");
const queryLocators = require("../../../../locators/QueryEditor.json");
const datasource = require("../../../../locators/DatasourcesEditor.json");
import { agHelper, deployMode } from "../../../../support/Objects/ObjectsCore";
import {
agHelper,
deployMode,
dataSources,
} from "../../../../support/Objects/ObjectsCore";
describe("API Panel Test Functionality", function () {
let datasourceName;
@ -25,17 +29,12 @@ describe("API Panel Test Functionality", function () {
it("2. Create and runs query", () => {
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click();
cy.get(queryLocators.settings).click({ force: true });
cy.get(queryLocators.switch).last().click({ force: true });
cy.xpath(queryLocators.query).click({ force: true });
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("select * from {{ this.params.tableName || 'users' }} limit 10", {
force: true,
parseSpecialCharSequences: false,
});
dataSources.EnterQuery(
"select * from {{ this.params.tableName || 'users' }} limit 10",
);
cy.WaitAutoSave();
cy.runQuery();
});

View File

@ -28,7 +28,6 @@ describe("Array Datatype tests", function () {
it("1. Creating table query - arraytypes + Bug 14493", () => {
query = `CREATE TABLE arraytypes (serialId SERIAL not null primary key, name text, pay_by_quarter integer[], schedule text[][]);`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
dataSources.RunQuery();
@ -174,7 +173,6 @@ describe("Array Datatype tests", function () {
agHelper.RenameWithInPane("verifyArrayFunctions");
query = `SELECT name FROM arraytypes WHERE pay_by_quarter[1] <> pay_by_quarter[2];`;
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
dataSources.RunQuery();
dataSources.AssertQueryResponseHeaders(["name"]);

View File

@ -254,7 +254,6 @@ describe.skip("Binary Datatype tests", function () {
//Validating zero octet
query = `select encode('\\000'::bytea, 'hex') as "zero octet Hex", encode('\\000'::bytea, 'escape') as "zero octet Escape";`;
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
dataSources.RunQuery();
dataSources.AssertQueryResponseHeaders([

View File

@ -164,7 +164,6 @@ describe("Boolean & Enum Datatype tests", function () {
entityExplorer.ExpandCollapseEntity("Queries/JS");
entityExplorer.CreateNewDsQuery(dsName);
agHelper.RenameWithInPane("verifyEnumOrdering");
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
dataSources.RunQuery();
dataSources.ReadQueryTableResponse(1).then(($cellData) => {

View File

@ -26,7 +26,6 @@ describe("Character Datatype tests", function () {
it("1. Creating table - chartypes", () => {
query = `create table charTypes(serialid serial primary key, "One(1)" char, "AsMany" varchar, "Limited(4)" varchar(4), "Unlimited" text)`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -29,7 +29,6 @@ describe("DateTime Datatype tests", function () {
tstz TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, dater date NOT NULL, timer time NOT NULL,
timertz time with time zone not null default now(), intervaler interval not null);`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -38,7 +38,6 @@ describe("Json & JsonB Datatype tests", function () {
it("1. Creating table query - jsonbooks", () => {
query = `CREATE TABLE jsonbooks(serialId SERIAL PRIMARY KEY, details JSON)`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
dataSources.RunQuery();
@ -64,33 +63,28 @@ describe("Json & JsonB Datatype tests", function () {
it("3. Creating all queries - jsonbooks", () => {
query = `INSERT INTO jsonbooks(details) VALUES('{"customer": "{{InsertJSONForm.formData.customer}}", "title": "{{InsertJSONForm.formData.title}}", "type": {{InsertJSONForm.formData.type}}, "info": {"published": {{InsertJSONForm.formData.info.published}}, "price": {{InsertJSONForm.formData.info.price}}}}');`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("insertRecord");
dataSources.ToggleUsePreparedStatement(false);
query = `UPDATE public."jsonbooks" SET "details" = '{"customer": "{{UpdateJSONForm.formData.customer}}", "title": "{{UpdateJSONForm.formData.title}}", "type": {{UpdateJSONForm.formData.type}}, "info": {"published": {{UpdateJSONForm.formData.info.published}}, "price": {{UpdateJSONForm.formData.info.price}}}}' WHERE serialid = {{Table1.selectedRow.serialid}};`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("updateRecord");
dataSources.ToggleUsePreparedStatement(false);
query = `DELETE FROM public."jsonbooks" WHERE serialId ={{Table1.selectedRow.serialid}}`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteRecord");
query = `DELETE FROM public."jsonbooks"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteAllRecords");
query = `drop table public."jsonbooks"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("dropTable");
@ -194,7 +188,6 @@ describe("Json & JsonB Datatype tests", function () {
//Verifying -> - returns results in json format
query = `SELECT details -> 'title' AS "BookTitle" FROM jsonbooks;`;
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("verifyJsonFunctions");
dataSources.RunQuery();
@ -361,14 +354,12 @@ describe("Json & JsonB Datatype tests", function () {
it("15. Creating enum & table queries - jsonBbooks", () => {
query = `CREATE TYPE genres AS ENUM ('Fiction', 'Thriller', 'Horror', 'Marketing & Sales', 'Self-Help', 'Psychology', 'Law', 'Politics', 'Productivity', 'Reference', 'Spirituality');`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createEnum");
dataSources.RunQuery();
query = `CREATE TABLE "jsonBbooks" (serialId SERIAL PRIMARY KEY, details JSONB)`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
dataSources.RunQuery();
@ -399,45 +390,38 @@ describe("Json & JsonB Datatype tests", function () {
it("17. Creating all queries - jsonBbooks", () => {
query = `INSERT INTO "jsonBbooks"(details) VALUES('{"title": "{{InsertJSONForm.formData.title}}", "genres": {{InsertJSONForm.formData.genres}}, "info": {"published": {{InsertJSONForm.formData.info.published}}, "publishedDate": "{{InsertJSONForm.formData.info.publishedDate}}"}}');`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("insertRecord");
dataSources.ToggleUsePreparedStatement(false);
query = `UPDATE public."jsonBbooks" SET "details" = '{"title": "{{UpdateJSONForm.formData.title}}", "genres": {{UpdateJSONForm.formData.genres}}, "info": {"published": {{UpdateJSONForm.formData.info.published}}, "publishedDate": "{{UpdateJSONForm.formData.info.publishedDate}}"}}' WHERE serialid = {{Table1.selectedRow.serialid}};`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("updateRecord");
dataSources.ToggleUsePreparedStatement(false);
query = `SELECT * from enum_range(NULL::genres)`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("getEnum");
query = `DELETE FROM public."jsonBbooks" WHERE serialId ={{Table1.selectedRow.serialid}}`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteRecord");
query = `DELETE FROM public."jsonBbooks"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteAllRecords");
query = `drop table public."jsonBbooks"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("dropTable");
query = `drop type genres`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("dropEnum");
@ -569,7 +553,6 @@ describe("Json & JsonB Datatype tests", function () {
//Verifying @> contains
query = `SELECT '["Fiction", "Thriller", "Horror"]'::jsonb @> '["Fiction", "Horror"]'::jsonb as "Result1", '["Fiction", "Horror"]'::jsonb @> '["Fiction", "Thriller", "Horror"]'::jsonb as "Result2", '{"name": "Alice", "agent": {"bot": true} }'::jsonb -> 'agent' ->> 'bot' is not null as "Filter"`;
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
dataSources.RunQuery();
dataSources.AssertQueryResponseHeaders(["Result1", "Result2", "Filter"]);

View File

@ -26,7 +26,6 @@ describe("Numeric Datatype tests", function () {
it("1. Creating table - numerictypes", () => {
query = `create table numerictypes (serialId SERIAL not null primary key, bigintId bigint not null, decimalId decimal not null, numericId numeric not null)`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
agHelper.FocusElement(locators._codeMirrorTextArea);

View File

@ -47,7 +47,6 @@ describe("UUID Datatype tests", function () {
it("2. Creating table query - uuidtype", () => {
query = `CREATE table uuidtype (serialid SERIAL primary key, v1 uuid, v4 uuid, guid uuid, nil uuid);`;
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("createTable");
dataSources.RunQuery();
@ -73,31 +72,26 @@ describe("UUID Datatype tests", function () {
it("4. Creating all queries - uuidtype", () => {
query = `INSERT INTO public."uuidtype" ("v1", "v4", "guid", "nil") VALUES ('{{version1.data[0]}}', '{{version4.data}}', '{{guid.data}}', '{{nill.data}}');`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("insertRecord");
query = `UPDATE public."uuidtype" SET "v1" ='{{version1.data[0] ? version1.data[0] : Table1.selectedRow.v1}}', "v4" ='{{version4.data ? version4.data : Table1.selectedRow.v4}}', "guid" ='{{guid.data ? guid.data : Table1.selectedRow.guid}}', "nil" ='{{nill.data ? nill.data : Table1.selectedRow.nil}}' WHERE serialid = {{Table1.selectedRow.serialid}};`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("updateRecord");
query = `DELETE FROM public."uuidtype"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteAllRecords");
query = `drop table public."uuidtype"`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("dropTable");
query = `DELETE FROM public."uuidtype" WHERE serialId = {{Table1.selectedRow.serialid}}`;
entityExplorer.CreateNewDsQuery(dsName);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
agHelper.RenameWithInPane("deleteRecord");
@ -273,7 +267,6 @@ describe("UUID Datatype tests", function () {
//Validating use of extention
query = `CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pgcrypto"`;
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(query);
dataSources.RunQueryNVerifyResponseViews(1);
dataSources.AssertQueryResponseHeaders(["affectedRows"]);

View File

@ -1,5 +1,6 @@
const queryLocators = require("../../../../locators/QueryEditor.json");
const queryEditor = require("../../../../locators/QueryEditor.json");
import { dataSources } from "../../../../support/Objects/ObjectsCore";
let datasourceName;
@ -14,12 +15,7 @@ describe("Add widget - Postgress DataSource", function () {
it("1. Verify 'Add to widget [Widget Suggestion]' functionality - Postgress", () => {
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click();
cy.wait(500);
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("select * from public.configs");
dataSources.EnterQuery("select * from public.configs");
cy.WaitAutoSave();
cy.runQuery();
cy.get(queryEditor.suggestedTableWidget).click();

View File

@ -15,7 +15,6 @@ describe("Validate MySQL query UI flows - Bug 14054", () => {
it("2. Validate Describe & verify query response", () => {
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("verifyDescribe");
runQueryNValidate("Describe customers;", [
"Field",
@ -49,7 +48,6 @@ describe("Validate MySQL query UI flows - Bug 14054", () => {
it("3. Validate SHOW & verify query response", () => {
dataSources.NavigateFromActiveDS(dsName, true);
agHelper.GetNClick(dataSources._templateMenu);
agHelper.RenameWithInPane("verifyShow");
runQueryNValidate("SHOW tables;", ["Tables_in_fakeapi"]);
runQueryNValidate("SHOW databases", ["Database"]);

View File

@ -29,7 +29,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
entityExplorer.NavigateToSwitcher("Widgets");
cy.dragAndDropToCanvas("tablewidgetv2", { x: 100, y: 100 });
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
agHelper.TypeDynamicInputValueNValidate(
"select * from users limit {{Table1.pageSize}} OFFSET {{((Table1.pageNo - 1)*Table1.pageSize)}}",
".CodeEditorTarget",
@ -83,7 +82,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
(29, 'CRUD User29', 'IN PROGRESS', 'Male','cruduser29@ihg.com', '19624 Scofield Way', 'Editor'),
(30, 'CRUD User30', 'APPROVED', 'Female','cruduser30@ihg.com', '19624 Scofield Way', 'Admin');`;
cy.get(queryLocators.templateMenu).click({ force: true });
//cy.typeValueNValidate(tableCreateQuery);//Since type method is slow for such big text - using paste!
cy.get(".CodeMirror textarea").focus().paste(tableCreateQuery);
cy.EvaluateCurrentValue(tableCreateQuery);
@ -94,7 +92,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
it("4. Validate Select record from Postgress datasource", () => {
let selectQuery = "select * from public.users_crud";
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.typeValueNValidate(selectQuery);
// cy.xpath(queryLocators.codeTextArea).paste(selectQuery);
@ -107,7 +104,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
let insertQuery =
"INSERT INTO public.users_crud (id, name, gender, email) VALUES (31, 'CRUD User11','Male','cruduser31@ihg.com');";
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.typeValueNValidate(insertQuery);
cy.runAndDeleteQuery();
});
@ -116,7 +112,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
let updateQuery =
"UPDATE public.users_crud SET status = 'PENDING', role = 'Viewer' WHERE id = 31;";
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.typeValueNValidate(updateQuery);
cy.runAndDeleteQuery();
});
@ -124,7 +119,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
it("7. Validate Delete record from Postgress datasource", () => {
let deleteQuery = "DELETE FROM public.users_crud WHERE id = 31;";
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.typeValueNValidate(deleteQuery);
cy.runAndDeleteQuery();
});
@ -289,7 +283,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
it("10. Validate Drop of the Newly Created Table from Postgress datasource", () => {
let deleteTblQuery = "DROP TABLE public.users_crud;";
dataSources.NavigateFromActiveDS(datasourceName, true);
agHelper.GetNClick(dataSources._templateMenu);
dataSources.EnterQuery(deleteTblQuery);
dataSources.RunQuery();
entityExplorer.ExpandCollapseEntity("Datasources");
@ -303,7 +296,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
it("11. Bug 9425: The application is breaking when user run the query with wrong table name", function () {
dataSources.NavigateFromActiveDS(datasourceName, true);
agHelper.GetNClick(dataSources._templateMenu);
cy.typeValueNValidate("select * from public.users limit 10");
cy.runQuery();
cy.typeValueNValidate("select * from public.users_crud limit 10");
@ -320,7 +312,6 @@ describe("Validate CRUD queries for Postgres along with UI flow verifications",
it("12. Bug 14493: The application is breaking when user runs the query with result as empty array", function () {
cy.NavigateToActiveDSQueryPane(datasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.typeValueNValidate(
"select * from public.users where name='Ayush1234' ORDER BY id LIMIT 10",
);

View File

@ -63,11 +63,6 @@ describe("Switch datasource", function () {
it("4. By switching datasources execute a query with both the datasources", function () {
cy.NavigateToActiveDSQueryPane(postgresDatasourceName);
cy.get(queryLocators.templateMenu).click({ force: true });
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("select * from public.users limit 10");
cy.wait(3000);
cy.runQuery();
cy.wait("@saveAction").should(

View File

@ -43,7 +43,7 @@ describe(
dataSources.CreateMockDB("Users").then((mockDBName) => {
dsName = mockDBName;
dataSources.CreateQueryFromActiveTab(mockDBName, false);
agHelper.GetNClick(dataSources._templateMenuOption("Select"));
dataSources.EnterQuery("SELECT * FROM users LIMIT 10");
dataSources.RunQueryNVerifyResponseViews(10);
dataSources.NavigateToActiveTab();
agHelper
@ -53,7 +53,7 @@ describe(
);
entityExplorer.CreateNewDsQuery(mockDBName);
agHelper.GetNClick(dataSources._templateMenuOption("Select"));
dataSources.EnterQuery("SELECT * FROM users LIMIT 10");
dataSources.RunQueryNVerifyResponseViews(10, false);
dataSources.NavigateToActiveTab();
agHelper

View File

@ -1,6 +1,6 @@
const queryLocators = require("../../../locators/QueryEditor.json");
const datasourceEditor = require("../../../locators/DatasourcesEditor.json");
import { agHelper } from "../../../support/Objects/ObjectsCore";
import { agHelper, dataSources } from "../../../support/Objects/ObjectsCore";
const commonlocators = require("../../../locators/commonlocators.json");
describe("MySQL noise test", function () {
@ -29,15 +29,10 @@ describe("MySQL noise test", function () {
cy.NavigateToActiveDSQueryPane(datasourceName);
});
cy.get(queryLocators.queryNameField).type("NoiseTestQuery");
cy.get(queryLocators.templateMenu).click();
// mySQL query to fetch data
cy.get(".CodeMirror textarea")
.first()
.focus()
.type("SELECT * FROM users where role = 'Admin' ORDER BY id LIMIT 10", {
force: true,
parseSpecialCharSequences: false,
});
dataSources.EnterQuery(
"SELECT * FROM users where role = 'Admin' ORDER BY id LIMIT 10",
);
cy.WaitAutoSave();
cy.runQuery();
cy.NavigateToAPI_Panel();

View File

@ -793,7 +793,6 @@ export class DataSources {
);
if (queryName) this.agHelper.RenameWithInPane(queryName);
if (query) {
this.agHelper.GetNClick(this._templateMenu);
this.EnterQuery(query);
}
}
@ -997,7 +996,6 @@ export class DataSources {
this.agHelper.RemoveEvaluatedPopUp(); //to close the evaluated pop-up
this.ee.CreateNewDsQuery(dsName);
if (query) {
this.agHelper.GetNClick(this._templateMenu);
this.EnterQuery(query, sleep);
}
if (queryName) this.agHelper.RenameWithInPane(queryName);

View File

@ -165,9 +165,6 @@ Cypress.Commands.add("CreateMockQuery", (queryName) => {
force: true,
});
cy.assertPageSave();
cy.get(queryEditor.templateMenu + " div")
.contains("Select")
.click({ force: true });
cy.runQuery();
// cy.wait(3000);
// cy.get(queryEditor.runQuery)

View File

@ -25,3 +25,6 @@ export const DatasourceEditEntryPoints = {
DATASOURCE_CARD_EDIT: "DATASOURCE_CARD_EDIT",
DATASOURCE_FORM_EDIT: "DATASOURCE_FORM_EDIT",
};
export const DB_QUERY_DEFAULT_TABLE_NAME = "<<your_table_name>>";
export const DB_QUERY_DEFAULT_TEMPLATE_TYPE = "SELECT";

View File

@ -1,79 +0,0 @@
import React from "react";
import { render, screen } from "test/testUtils";
import FormControl from "./FormControl";
import { reduxForm } from "redux-form";
import { mockCodemirrorRender } from "test/__mocks__/CodeMirrorEditorMock";
import { PluginPackageName, PluginType } from "entities/Action";
import { waitFor } from "@testing-library/dom";
import userEvent from "@testing-library/user-event";
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
import { DatasourceComponentTypes, UIComponentTypes } from "api/PluginApi";
function TestForm(props: any) {
return <div>{props.children}</div>;
}
const ReduxFormDecorator = reduxForm({
form: "TestForm",
initialValues: { name: "TestAction", datasource: { pluginId: "123" } },
})(TestForm);
describe("DynamicTextFieldControl", () => {
beforeEach(() => {
mockCodemirrorRender();
});
it("renders template menu correctly", () => {
const config = {
actionName: "TestAction",
configProperty: "actionConfiguration.body",
controlType: "DYNAMIC_TEXT_FIELD_CONTROL",
evaluationSubstitutionType: EvaluationSubstitutionType.TEMPLATE,
formName: "TestForm",
id: "test",
isValid: true,
label: "TestAction body",
onPropertyChange: jest.fn(),
pluginId: "123",
responseType: "TABLE",
};
render(
<ReduxFormDecorator>
<FormControl config={config} formName={"TestForm"} />
</ReduxFormDecorator>,
{
url: "/?showTemplate=true",
initialState: {
entities: {
// @ts-expect-error: Types are not available
plugins: {
list: [
{
id: "123",
name: "testPlugin",
type: PluginType.DB,
packageName: PluginPackageName.POSTGRES,
templates: {
CREATE: "test plugin template",
},
uiComponent: UIComponentTypes.DbEditorForm,
datasourceComponent: DatasourceComponentTypes.AutoForm,
},
],
},
},
},
},
);
const createTemplateButton = screen.getByText("Create");
userEvent.click(createTemplateButton);
waitFor(async () => {
await expect(screen.findByText("Create")).toBeNull();
// Test each word separately because they are in different spans
expect(screen.getByText("test")).toBeDefined();
expect(screen.getByText("plugin")).toBeDefined();
expect(screen.getByText("template")).toBeDefined();
});
});
});

View File

@ -1,4 +1,4 @@
import React, { memo, useMemo, useState } from "react";
import React, { memo, useEffect, useMemo, useState } from "react";
import type { ControlProps } from "components/formControls/BaseControl";
import {
getViewType,
@ -19,9 +19,19 @@ import { QUERY_BODY_FIELDS } from "constants/QueryEditorConstants";
import { convertObjectToQueryParams, getQueryParams } from "utils/URLUtils";
import { QUERY_EDITOR_FORM_NAME } from "@appsmith/constants/forms";
import history from "utils/history";
import TemplateMenu from "pages/Editor/QueryEditor/TemplateMenu";
import { getAction } from "selectors/entitiesSelector";
import {
getAction,
getDatasourceFirstTableName,
getPluginNameFromId,
getPluginTemplates,
} from "selectors/entitiesSelector";
import { get } from "lodash";
import {
DB_QUERY_DEFAULT_TABLE_NAME,
DB_QUERY_DEFAULT_TEMPLATE_TYPE,
} from "constants/Datasource";
import TemplateMenu from "./QueryEditor/TemplateMenu";
import { SQL_DATASOURCES } from "../../constants/QueryEditorConstants";
export interface FormControlProps {
config: ControlProps;
@ -52,6 +62,19 @@ function FormControl(props: FormControlProps) {
}),
shallowEqual,
);
const datasourceTableName: string = useSelector((state: AppState) =>
getDatasourceFirstTableName(state, (formValues?.datasource as any)?.id),
);
const pluginTemplates: Record<string, any> = useSelector((state: AppState) =>
getPluginTemplates(state),
);
const pluginTemplate = !!formValues?.datasource?.pluginId
? pluginTemplates[formValues?.datasource?.pluginId]
: undefined;
const pluginId: string = formValues?.pluginId || "";
const pluginName: string = useSelector((state: AppState) =>
getPluginNameFromId(state, pluginId),
);
// moving creation of template to the formControl layer, this way any formControl created can potentially have a template system.
const isNewQuery =
@ -103,16 +126,28 @@ function FormControl(props: FormControlProps) {
}
}
const createTemplate = (
template: string,
formName: string,
configProperty: string,
) => {
updateQueryParams();
dispatch(
change(formName || QUERY_EDITOR_FORM_NAME, configProperty, template),
);
};
useEffect(() => {
if (
showTemplate &&
!convertFormToRaw &&
SQL_DATASOURCES.includes(pluginName)
) {
const defaultTemplate = !!pluginTemplate
? pluginTemplate[DB_QUERY_DEFAULT_TEMPLATE_TYPE]
: "";
const smartTemplate = defaultTemplate
.replace(DB_QUERY_DEFAULT_TABLE_NAME, datasourceTableName)
.split("--")[0];
dispatch(
change(
props?.formName || QUERY_EDITOR_FORM_NAME,
props.config.configProperty,
!!datasourceTableName ? smartTemplate : defaultTemplate,
),
);
updateQueryParams();
}
}, [showTemplate]);
const FormControlRenderMethod = (config = props.config) => {
return FormControlFactory.createControl(
@ -130,6 +165,17 @@ function FormControl(props: FormControlProps) {
viewTypes.push(...props.config.alternateViewTypes);
}
const createTemplate = (
template: string,
formName: string,
configProperty: string,
) => {
updateQueryParams();
dispatch(
change(formName || QUERY_EDITOR_FORM_NAME, configProperty, template),
);
};
return useMemo(
() =>
!hidden ? (
@ -146,7 +192,9 @@ function FormControl(props: FormControlProps) {
className={`t--form-control-${props.config.controlType}`}
data-replay-id={btoa(props.config.configProperty)}
>
{showTemplate && !convertFormToRaw ? (
{showTemplate &&
!convertFormToRaw &&
!SQL_DATASOURCES.includes(pluginName) ? (
<TemplateMenu
createTemplate={(templateString: string) =>
createTemplate(

View File

@ -279,6 +279,9 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
const { editorConfigs, settingConfigs } = plugins;
const action = getAction(state, actionId) as QueryAction | SaaSAction;
const formData = getFormValues(QUERY_EDITOR_FORM_NAME)(state) as
| QueryAction
| SaaSAction;
let pluginId;
if (action) {
pluginId = action.pluginId;
@ -319,10 +322,6 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
let uiComponent = UIComponentTypes.DbEditorForm;
if (!!pluginId) uiComponent = getUIComponent(pluginId, allPlugins);
const formData = getFormValues(QUERY_EDITOR_FORM_NAME)(state) as
| QueryAction
| SaaSAction;
return {
actionId,
pluginId,
@ -344,7 +343,7 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
uiComponent,
applicationId: getCurrentApplicationId(state),
actionObjectDiff,
datasourceId: action.datasource?.id,
datasourceId: action?.datasource?.id,
};
};

View File

@ -319,7 +319,6 @@ function* handleQueryCreatedSaga(actionPayload: ReduxAction<QueryAction>) {
actionPayload.payload;
const pageId: string = yield select(getCurrentPageId);
if (pluginType !== PluginType.DB && pluginType !== PluginType.REMOTE) return;
yield put(initialize(QUERY_EDITOR_FORM_NAME, actionPayload.payload));
const pluginTemplates: Record<string, unknown> = yield select(
getPluginTemplates,
);

View File

@ -93,6 +93,23 @@ export const getDatasourceTablePrimaryColumn =
}
};
export const getDatasourceFirstTableName = (
state: AppState,
datasourceId: string,
) => {
if (!datasourceId) {
return "";
}
const structure = getDatasourceStructureById(state, datasourceId);
if (structure) {
if (!!structure.tables && structure.tables.length > 0) {
return structure.tables[0].name;
}
}
return "";
};
export const getIsFetchingDatasourceStructure = (state: AppState): boolean => {
return state.entities.datasources.fetchingDatasourceStructure;
};

View File

@ -1 +1,3 @@
SELECT TOP 10 * FROM users where role = {{ roleDropdown.selectedOptionValue }} ORDER BY id;
SELECT TOP 10 * FROM <<your_table_name>>;
-- Please enter a valid table name and hit RUN

View File

@ -1 +1,3 @@
SELECT * FROM users where role = 'Admin' ORDER BY id LIMIT 10
SELECT * FROM <<your_table_name>> LIMIT 10
-- Please enter a valid table name and hit RUN

View File

@ -1 +1,3 @@
SELECT* FROM users WHERE ROWNUM < 10
SELECT* FROM <<your_table_name>> WHERE ROWNUM < 10;
-- Please enter a valid table name and hit RUN

View File

@ -1 +1,3 @@
SELECT * FROM users ORDER BY id LIMIT 10;
SELECT * FROM <<your_table_name>> LIMIT 10;
-- Please enter a valid table name and hit RUN

View File

@ -1 +1,3 @@
SELECT * FROM users where role = 'Admin' ORDER BY id LIMIT 10;
SELECT * FROM <<your_table_name>> LIMIT 10;
-- Please enter a valid table name and hit RUN

View File

@ -1 +1,3 @@
SELECT * FROM users where role = 'Admin' ORDER BY id LIMIT 10;
SELECT * FROM <<your_table_name>> LIMIT 10;
-- Please enter a valid table name and hit RUN