Merge remote-tracking branch 'origin/release' into fix-11468_dropdown_performance
This commit is contained in:
commit
f4e6341add
|
|
@ -16,8 +16,7 @@
|
|||
"**/Smoke_TestSuite/Application/PgAdmin_spec*.js",
|
||||
"**/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Table_Filter_spec*.js",
|
||||
"**/Smoke_TestSuite/ClientSideTests/Onboarding/FirstTimeUserOnboarding_spec*.js",
|
||||
"**/Smoke_TestSuite/ClientSideTests/LayoutValidation/AppPageLayout.spec.js",
|
||||
"**/Smoke_TestSuite/ClientSideTests/GitSync/*"
|
||||
"**/Smoke_TestSuite/ClientSideTests/LayoutValidation/AppPageLayout.spec.js"
|
||||
],
|
||||
"chromeWebSecurity": false,
|
||||
"viewportHeight": 900,
|
||||
|
|
|
|||
404
app/client/cypress/fixtures/noiseDsl.json
Normal file
404
app/client/cypress/fixtures/noiseDsl.json
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
{
|
||||
"dsl": {
|
||||
"widgetName": "MainContainer",
|
||||
"backgroundColor": "none",
|
||||
"rightColumn": 816,
|
||||
"snapColumns": 64,
|
||||
"detachFromLayout": true,
|
||||
"widgetId": "0",
|
||||
"topRow": 0,
|
||||
"bottomRow": 760,
|
||||
"containerStyle": "none",
|
||||
"snapRows": 73,
|
||||
"parentRowSpace": 1,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": true,
|
||||
"version": 51,
|
||||
"minHeight": 740,
|
||||
"parentColumnSpace": 1,
|
||||
"dynamicBindingPathList": [],
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Table1",
|
||||
"defaultPageSize": 0,
|
||||
"columnOrder": [
|
||||
"id",
|
||||
"name",
|
||||
"createdAt",
|
||||
"updatedAt",
|
||||
"status",
|
||||
"gender",
|
||||
"avatar",
|
||||
"email",
|
||||
"address",
|
||||
"role",
|
||||
"dob",
|
||||
"phoneNo"
|
||||
],
|
||||
"isVisibleDownload": true,
|
||||
"dynamicPropertyPathList": [],
|
||||
"displayName": "Table",
|
||||
"iconSVG": "/static/media/icon.db8a9cbd.svg",
|
||||
"topRow": 19,
|
||||
"bottomRow": 47,
|
||||
"isSortable": true,
|
||||
"parentRowSpace": 10,
|
||||
"type": "TABLE_WIDGET",
|
||||
"defaultSelectedRow": "0",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.5625,
|
||||
"dynamicTriggerPathList": [],
|
||||
"dynamicBindingPathList": [
|
||||
{
|
||||
"key": "primaryColumns.status.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "tableData"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.id.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.name.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.createdAt.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.updatedAt.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.gender.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.avatar.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.email.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.address.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.role.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.dob.computedValue"
|
||||
},
|
||||
{
|
||||
"key": "primaryColumns.phoneNo.computedValue"
|
||||
}
|
||||
],
|
||||
"leftColumn": 14,
|
||||
"primaryColumns": {
|
||||
"status": {
|
||||
"index": 2,
|
||||
"width": 150,
|
||||
"id": "status",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "status",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.status))}}",
|
||||
"buttonColor": "#03B365",
|
||||
"menuColor": "#03B365",
|
||||
"labelColor": "#FFFFFF"
|
||||
},
|
||||
"id": {
|
||||
"index": 0,
|
||||
"width": 150,
|
||||
"id": "id",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "id",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.id))}}"
|
||||
},
|
||||
"name": {
|
||||
"index": 1,
|
||||
"width": 150,
|
||||
"id": "name",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "name",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.name))}}"
|
||||
},
|
||||
"createdAt": {
|
||||
"index": 2,
|
||||
"width": 150,
|
||||
"id": "createdAt",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "createdAt",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.createdAt))}}"
|
||||
},
|
||||
"updatedAt": {
|
||||
"index": 3,
|
||||
"width": 150,
|
||||
"id": "updatedAt",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "updatedAt",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.updatedAt))}}"
|
||||
},
|
||||
"gender": {
|
||||
"index": 5,
|
||||
"width": 150,
|
||||
"id": "gender",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "gender",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.gender))}}"
|
||||
},
|
||||
"avatar": {
|
||||
"index": 6,
|
||||
"width": 150,
|
||||
"id": "avatar",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "avatar",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.avatar))}}"
|
||||
},
|
||||
"email": {
|
||||
"index": 7,
|
||||
"width": 150,
|
||||
"id": "email",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "email",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.email))}}"
|
||||
},
|
||||
"address": {
|
||||
"index": 8,
|
||||
"width": 150,
|
||||
"id": "address",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "address",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.address))}}"
|
||||
},
|
||||
"role": {
|
||||
"index": 9,
|
||||
"width": 150,
|
||||
"id": "role",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "role",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.role))}}"
|
||||
},
|
||||
"dob": {
|
||||
"index": 10,
|
||||
"width": 150,
|
||||
"id": "dob",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "dob",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.dob))}}"
|
||||
},
|
||||
"phoneNo": {
|
||||
"index": 11,
|
||||
"width": 150,
|
||||
"id": "phoneNo",
|
||||
"horizontalAlignment": "LEFT",
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnType": "text",
|
||||
"textSize": "PARAGRAPH",
|
||||
"enableFilter": true,
|
||||
"enableSort": true,
|
||||
"isVisible": true,
|
||||
"isDisabled": false,
|
||||
"isCellVisible": true,
|
||||
"isDerived": false,
|
||||
"label": "phoneNo",
|
||||
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.phoneNo))}}"
|
||||
}
|
||||
},
|
||||
"delimiter": ",",
|
||||
"key": "9flri9lh3m",
|
||||
"derivedColumns": {},
|
||||
"rightColumn": 48,
|
||||
"textSize": "PARAGRAPH",
|
||||
"widgetId": "24cxf11c77",
|
||||
"isVisibleFilters": true,
|
||||
"tableData": "{{NoiseTestQuery.data}}",
|
||||
"isVisible": true,
|
||||
"label": "Data",
|
||||
"searchKey": "",
|
||||
"enableClientSideSearch": true,
|
||||
"version": 3,
|
||||
"totalRecordsCount": 0,
|
||||
"parentId": "0",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"horizontalAlignment": "LEFT",
|
||||
"isVisibleSearch": true,
|
||||
"isVisiblePagination": true,
|
||||
"verticalAlignment": "CENTER",
|
||||
"columnSizeMap": {
|
||||
"task": 245,
|
||||
"step": 62,
|
||||
"status": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"widgetName": "Button1",
|
||||
"onClick": "{{killSession.run()}}",
|
||||
"buttonColor": "#27647e",
|
||||
"displayName": "Button",
|
||||
"iconSVG": "/static/media/icon.cca02633.svg",
|
||||
"topRow": 49,
|
||||
"bottomRow": 53,
|
||||
"parentRowSpace": 10,
|
||||
"type": "BUTTON_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.5625,
|
||||
"dynamicTriggerPathList": [
|
||||
{
|
||||
"key": "onClick"
|
||||
}
|
||||
],
|
||||
"leftColumn": 14,
|
||||
"dynamicBindingPathList": [],
|
||||
"text": "Kill Session",
|
||||
"isDisabled": false,
|
||||
"key": "oyyqr9a87m",
|
||||
"rightColumn": 29,
|
||||
"isDefaultClickDisabled": true,
|
||||
"widgetId": "h1ga2gebsk",
|
||||
"isVisible": true,
|
||||
"recaptchaType": "V3",
|
||||
"version": 1,
|
||||
"parentId": "0",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"buttonVariant": "PRIMARY",
|
||||
"placement": "CENTER",
|
||||
"boxShadowColor": "#27647e"
|
||||
},
|
||||
{
|
||||
"widgetName": "Button2",
|
||||
"onClick": "{{NoiseTestQuery.run()}}",
|
||||
"buttonColor": "#27647e",
|
||||
"dynamicPropertyPathList": [],
|
||||
"displayName": "Button",
|
||||
"iconSVG": "/static/media/icon.cca02633.svg",
|
||||
"topRow": 49,
|
||||
"bottomRow": 53,
|
||||
"parentRowSpace": 10,
|
||||
"type": "BUTTON_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.5625,
|
||||
"dynamicTriggerPathList": [
|
||||
{
|
||||
"key": "onClick"
|
||||
}
|
||||
],
|
||||
"leftColumn": 33,
|
||||
"dynamicBindingPathList": [],
|
||||
"text": "Refresh Query",
|
||||
"isDisabled": false,
|
||||
"key": "r7znf2jmhk",
|
||||
"rightColumn": 48,
|
||||
"isDefaultClickDisabled": true,
|
||||
"widgetId": "ddg5ybjic1",
|
||||
"isVisible": true,
|
||||
"recaptchaType": "V3",
|
||||
"version": 1,
|
||||
"parentId": "0",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"buttonVariant": "PRIMARY",
|
||||
"placement": "CENTER"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +1,49 @@
|
|||
// import { AggregateHelper } from "../../../../support/Pages/AggregateHelper";
|
||||
// import { JSEditor } from "../../../../support/Pages/JSEditor";
|
||||
// import { CommonLocators } from "../../../../support/Objects/CommonLocators";
|
||||
import { AggregateHelper } from "../../../../support/Pages/AggregateHelper";
|
||||
import { JSEditor } from "../../../../support/Pages/JSEditor";
|
||||
import { CommonLocators } from "../../../../support/Objects/CommonLocators";
|
||||
|
||||
// const agHelper = new AggregateHelper();
|
||||
// const jsEditor = new JSEditor();
|
||||
// const locator = new CommonLocators();
|
||||
const agHelper = new AggregateHelper();
|
||||
const jsEditor = new JSEditor();
|
||||
const locator = new CommonLocators();
|
||||
|
||||
// describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
||||
// before(() => {
|
||||
// cy.fixture('formInputTableDsl').then((val: any) => {
|
||||
// agHelper.AddDsl(val)
|
||||
// });
|
||||
// });
|
||||
describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
||||
before(() => {
|
||||
cy.fixture('formInputTableDsl').then((val: any) => {
|
||||
agHelper.AddDsl(val)
|
||||
});
|
||||
});
|
||||
|
||||
// it("1. Bind Input widget with JSObject", function () {
|
||||
// jsEditor.CreateJSObject('return "Success";', false);
|
||||
// agHelper.SelectEntityByName("Widgets")//to expand widgets
|
||||
// agHelper.expandCollapseEntity("Form1")
|
||||
// agHelper.SelectEntityByName("Input2")
|
||||
// cy.get("@jsObjName").then((jsObjName) => {
|
||||
// jsEditor.EnterJSContext("defaulttext", "{{" + jsObjName + ".myFun1()}}")
|
||||
// });
|
||||
// cy.wait("@updateLayout").should(
|
||||
// "have.nested.property",
|
||||
// "response.body.responseMeta.status",
|
||||
// 200,
|
||||
// );
|
||||
// cy.get(locator._inputWidget).last().invoke("attr", "value").should("equal", 'Success');
|
||||
// // cy.get(locator._inputWidget)
|
||||
// // .last()
|
||||
// // .within(() => {
|
||||
// // cy.get("input")
|
||||
// // .invoke("attr", "value")
|
||||
// // .should("equal", 'Success');
|
||||
// // });
|
||||
// });
|
||||
it("1. Bind Input widget with JSObject", function () {
|
||||
jsEditor.CreateJSObject('return "Success";', false);
|
||||
agHelper.SelectEntityByName("WIDGETS")//to expand widgets
|
||||
agHelper.expandCollapseEntity("Form1")
|
||||
agHelper.SelectEntityByName("Input2")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext("defaulttext", "{{" + jsObjName + ".myFun1()}}")
|
||||
});
|
||||
cy.get(locator._inputWidget).last().invoke("attr", "value").should("equal", 'Success');
|
||||
// cy.get(locator._inputWidget)
|
||||
// .last()
|
||||
// .within(() => {
|
||||
// cy.get("input")
|
||||
// .invoke("attr", "value")
|
||||
// .should("equal", 'Success');
|
||||
// });
|
||||
});
|
||||
|
||||
// it.skip("2. Bug 10284, 11529 - Verify timeout issue with running JS Objects", function () {
|
||||
// jsEditor.CreateJSObject('return "Success";', true);
|
||||
// agHelper.expandCollapseEntity("Form1")
|
||||
// agHelper.SelectEntityByName("Input2")
|
||||
// cy.get("@jsObjName").then((jsObjName) => {
|
||||
// jsEditor.EnterJSContext("defaulttext", "{{" + jsObjName + ".myFun1()}}")
|
||||
// });
|
||||
// cy.wait("@updateLayout").should(
|
||||
// "have.nested.property",
|
||||
// "response.body.responseMeta.status",
|
||||
// 200,
|
||||
// );
|
||||
// cy.get(locator._inputWidget).last().invoke("attr", "value").should("equal", 'Success');
|
||||
// });
|
||||
it.skip("2. Bug 10284, 11529 - Verify timeout issue with running JS Objects", function () {
|
||||
jsEditor.CreateJSObject('return "Success";', true);
|
||||
agHelper.expandCollapseEntity("Form1")
|
||||
agHelper.SelectEntityByName("Input2")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext("defaulttext", "{{" + jsObjName + ".myFun1()}}")
|
||||
});
|
||||
cy.wait("@updateLayout").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get(locator._inputWidget).last().invoke("attr", "value").should("equal", 'Success');
|
||||
});
|
||||
|
||||
// });
|
||||
});
|
||||
|
|
@ -1,82 +1,83 @@
|
|||
// import { ApiPage } from "../../../../support/Pages/ApiPage";
|
||||
// import { AggregateHelper } from "../../../../support/Pages/AggregateHelper";
|
||||
// import { JSEditor } from "../../../../support/Pages/JSEditor";
|
||||
// import { CommonLocators } from "../../../../support/Objects/CommonLocators";
|
||||
import { ApiPage } from "../../../../support/Pages/ApiPage";
|
||||
import { AggregateHelper } from "../../../../support/Pages/AggregateHelper";
|
||||
import { JSEditor } from "../../../../support/Pages/JSEditor";
|
||||
import { CommonLocators } from "../../../../support/Objects/CommonLocators";
|
||||
|
||||
// const apiPage = new ApiPage();
|
||||
// const agHelper = new AggregateHelper();
|
||||
// const jsEditor = new JSEditor();
|
||||
// const locator = new CommonLocators();
|
||||
const apiPage = new ApiPage();
|
||||
const agHelper = new AggregateHelper();
|
||||
const jsEditor = new JSEditor();
|
||||
const locator = new CommonLocators();
|
||||
|
||||
// let dataSet: any, valueToTest: any, jsName: any;
|
||||
let dataSet: any, valueToTest: any, jsName: any;
|
||||
|
||||
// describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
||||
// before(() => {
|
||||
// cy.fixture('listwidgetdsl').then((val: any) => {
|
||||
// agHelper.AddDsl(val)
|
||||
// });
|
||||
describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
||||
before(() => {
|
||||
cy.fixture('listwidgetdsl').then((val: any) => {
|
||||
agHelper.AddDsl(val)
|
||||
});
|
||||
|
||||
// cy.fixture("example").then(function (data: any) {
|
||||
// dataSet = data;
|
||||
// });
|
||||
// });
|
||||
cy.fixture("example").then(function (data: any) {
|
||||
dataSet = data;
|
||||
});
|
||||
});
|
||||
|
||||
// it("1. Add users api and bind to JSObject", () => {
|
||||
// apiPage.CreateAndFillApi(dataSet.userApi + "/users")
|
||||
// apiPage.RunAPI()
|
||||
// apiPage.ReadApiResponsebyKey("name");
|
||||
// cy.get("@apiResp").then((value) => {
|
||||
// valueToTest = value;
|
||||
// cy.log("valueToTest to test returned is :" + valueToTest)
|
||||
// //cy.log("value to test returned is :" + value)
|
||||
// })
|
||||
// jsEditor.CreateJSObject("return Api1.data.users;", false);
|
||||
// cy.get("@jsObjName").then((jsObj) => {
|
||||
// jsName = jsObj;
|
||||
// cy.log("jsName returned is :" + jsName)
|
||||
// })
|
||||
// });
|
||||
it("1. Add users api and bind to JSObject", () => {
|
||||
apiPage.CreateAndFillApi(dataSet.userApi + "/users")
|
||||
apiPage.RunAPI()
|
||||
apiPage.ReadApiResponsebyKey("name");
|
||||
cy.get("@apiResp").then((value) => {
|
||||
valueToTest = value;
|
||||
cy.log("valueToTest to test returned is :" + valueToTest)
|
||||
//cy.log("value to test returned is :" + value)
|
||||
})
|
||||
jsEditor.CreateJSObject("return Api1.data.users;", false);
|
||||
cy.get("@jsObjName").then((jsObj) => {
|
||||
jsName = jsObj;
|
||||
cy.log("jsName returned is :" + jsName)
|
||||
})
|
||||
});
|
||||
|
||||
// it("2. Validate the Api data is updated on List widget", function () {
|
||||
// agHelper.SelectEntityByName("Widgets")//to expand widgets
|
||||
// agHelper.SelectEntityByName("List1");
|
||||
// jsEditor.EnterJSContext("items", "{{" + jsName as string + ".myFun1()}}")
|
||||
// cy.get(locator._textWidget).should("have.length", 8);
|
||||
// cy.get(locator._textWidget)
|
||||
// .first()
|
||||
// .invoke("text")
|
||||
// .then((text) => {
|
||||
// expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
// });
|
||||
// agHelper.DeployApp();
|
||||
// cy.get(locator._textWidgetInDeployed).should("have.length", 8);
|
||||
// cy.get(locator._textWidgetInDeployed)
|
||||
// .first()
|
||||
// .invoke("text")
|
||||
// .then((text) => {
|
||||
// expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
// });
|
||||
// });
|
||||
it("2. Validate the Api data is updated on List widget", function () {
|
||||
agHelper.SelectEntityByName("WIDGETS")//to expand widgets
|
||||
agHelper.SelectEntityByName("List1");
|
||||
jsEditor.EnterJSContext("items", "{{" + jsName as string + ".myFun1()}}")
|
||||
cy.get(locator._textWidget).should("have.length", 8);
|
||||
cy.get(locator._textWidget)
|
||||
.first()
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
});
|
||||
agHelper.DeployApp();
|
||||
agHelper.WaitUntilEleAppear(locator._textWidgetInDeployed)
|
||||
cy.get(locator._textWidgetInDeployed).should("have.length", 8);
|
||||
cy.get(locator._textWidgetInDeployed)
|
||||
.first()
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
});
|
||||
});
|
||||
|
||||
// it("3. Validate the List widget ", function () {
|
||||
// agHelper.NavigateBacktoEditor()
|
||||
// agHelper.SelectEntityByName("Widgets")//to expand widgets
|
||||
// agHelper.SelectEntityByName("List1");
|
||||
// jsEditor.EnterJSContext("itemspacing\\(px\\)", "50")
|
||||
// cy.get(locator._textWidget).should("have.length", 6);
|
||||
// cy.get(locator._textWidget)
|
||||
// .first()
|
||||
// .invoke("text")
|
||||
// .then((text) => {
|
||||
// expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
// });
|
||||
// agHelper.DeployApp();
|
||||
// cy.get(locator._textWidgetInDeployed).should("have.length", 6);
|
||||
// cy.get(locator._textWidgetInDeployed).first()
|
||||
// .invoke("text")
|
||||
// .then((text) => {
|
||||
// expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
// });
|
||||
// agHelper.NavigateBacktoEditor()
|
||||
// });
|
||||
// });
|
||||
it("3. Validate the List widget ", function () {
|
||||
agHelper.NavigateBacktoEditor()
|
||||
agHelper.SelectEntityByName("WIDGETS")//to expand widgets
|
||||
agHelper.SelectEntityByName("List1");
|
||||
jsEditor.EnterJSContext("itemspacing\\(px\\)", "50")
|
||||
cy.get(locator._textWidget).should("have.length", 6);
|
||||
cy.get(locator._textWidget)
|
||||
.first()
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
});
|
||||
agHelper.DeployApp();
|
||||
cy.get(locator._textWidgetInDeployed).should("have.length", 6);
|
||||
cy.get(locator._textWidgetInDeployed).first()
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text).to.equal((valueToTest as string).trimEnd());
|
||||
});
|
||||
agHelper.NavigateBacktoEditor()
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ describe("Migration Validate", function() {
|
|||
|
||||
//Validating Latitude & Longitude are hidden columns:
|
||||
cy.xpath(
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']/div[text()='latitude']",
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']//div[text()='latitude']/parent::div/parent::div",
|
||||
)
|
||||
.invoke("attr", "class")
|
||||
.then((classes) => {
|
||||
|
|
@ -52,7 +52,7 @@ describe("Migration Validate", function() {
|
|||
});
|
||||
|
||||
cy.xpath(
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']/div[text()='longitude']",
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']//div[text()='longitude']/parent::div/parent::div",
|
||||
)
|
||||
.invoke("attr", "class")
|
||||
.then((classes) => {
|
||||
|
|
@ -74,7 +74,7 @@ describe("Migration Validate", function() {
|
|||
|
||||
//Validating Id column sorting happens as Datatype is Number in app!
|
||||
cy.xpath(
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']/div[text()='id']",
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']//div[text()='id']",
|
||||
)
|
||||
.click()
|
||||
.wait(2000);
|
||||
|
|
@ -93,7 +93,7 @@ describe("Migration Validate", function() {
|
|||
|
||||
//Revert the Id column sorting!
|
||||
cy.xpath(
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']/div[text()='id']",
|
||||
"//div[@class='tableWrap']//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']//div[text()='id']",
|
||||
)
|
||||
.click()
|
||||
.wait(2000);
|
||||
|
|
@ -112,7 +112,7 @@ describe("Migration Validate", function() {
|
|||
|
||||
//Validating image column is present:
|
||||
cy.getTableDataSelector("0", "10").then((selector) => {
|
||||
cy.get(selector + " div div")
|
||||
cy.get(selector + " div")
|
||||
.invoke("attr", "class")
|
||||
.then((classes) => {
|
||||
cy.log("classes are:" + classes);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
const widgetsPage = require("../../../../locators/Widgets.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const publish = require("../../../../locators/publishWidgetspage.json");
|
||||
const dsl = require("../../../../fixtures/tableNewDsl.json");
|
||||
const pages = require("../../../../locators/Pages.json");
|
||||
const testdata = require("../../../../fixtures/testdata.json");
|
||||
|
||||
describe("Table Widget property pane feature validation", function() {
|
||||
|
|
@ -185,67 +183,71 @@ describe("Table Widget property pane feature validation", function() {
|
|||
cy.get(".draggable-header:contains('Email Address')").should("be.visible");
|
||||
cy.get(commonlocators.editPropBackButton).click({ force: true });
|
||||
});
|
||||
it("Edit Row height and test table for changes", function() {
|
||||
cy.openPropertyPane("tablewidget");
|
||||
cy.get(widgetsPage.rowHeight)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.get(".t--dropdown-option")
|
||||
.contains("Short")
|
||||
.click({ force: true });
|
||||
cy.wait(1000);
|
||||
cy.readTabledataValidateCSS("0", "0", "height", "19px");
|
||||
});
|
||||
it("Test to validate text color and text background", function() {
|
||||
// Open property pane
|
||||
cy.openPropertyPane("tablewidget");
|
||||
// Click on text color input field
|
||||
cy.get(widgetsPage.textColor)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
// Select green color
|
||||
cy.xpath(widgetsPage.greenColor).click();
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
cy.wait("@updateLayout");
|
||||
// Verify the text color is green
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(3, 179, 101)");
|
||||
// Change the text color and enter purple in input field
|
||||
cy.get(widgetsPage.textColor)
|
||||
.clear({ force: true })
|
||||
.type("purple", { force: true });
|
||||
cy.wait("@updateLayout");
|
||||
// Verify the text color is purple
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(128, 0, 128)");
|
||||
// Click on cell background color
|
||||
cy.get(`${widgetsPage.cellBackground} input`)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
// select the green color
|
||||
cy.xpath(widgetsPage.greenColor)
|
||||
.first()
|
||||
.click();
|
||||
cy.wait("@updateLayout");
|
||||
// Verify the cell background color is green
|
||||
cy.readTabledataValidateCSS(
|
||||
"1",
|
||||
"0",
|
||||
"background",
|
||||
"rgb(3, 179, 101) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
);
|
||||
// Change the cell background color and enter purple in input field
|
||||
cy.get(`${widgetsPage.cellBackground} input`)
|
||||
.clear({ force: true })
|
||||
.type("purple", { force: true });
|
||||
cy.wait("@updateLayout");
|
||||
// Verify the cell background color is purple
|
||||
cy.readTabledataValidateCSS(
|
||||
"1",
|
||||
"0",
|
||||
"background",
|
||||
"rgb(128, 0, 128) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
);
|
||||
});
|
||||
|
||||
// it("Edit Row height and test table for changes", function() {
|
||||
// cy.openPropertyPane("tablewidget");
|
||||
// cy.get(widgetsPage.rowHeight)
|
||||
// .last()
|
||||
// .click({ force: true });
|
||||
// cy.get(".t--dropdown-option")
|
||||
// .contains("Short")
|
||||
// .click({ force: true });
|
||||
// cy.wait(1000);
|
||||
// cy.readTabledataValidateCSS("0", "1", "height", "19px", true);
|
||||
// });
|
||||
|
||||
// it("Test to validate text color and text background", function() {
|
||||
// // Open property pane
|
||||
// cy.openPropertyPane("tablewidget");
|
||||
// // Click on text color input field
|
||||
// cy.get(widgetsPage.textColor)
|
||||
// .first()
|
||||
// .click({ force: true });
|
||||
// // Select green color
|
||||
// cy.xpath(widgetsPage.greenColor).click();
|
||||
// // eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
// cy.wait(500);
|
||||
// cy.wait("@updateLayout");
|
||||
// // Verify the text color is green
|
||||
// cy.readTabledataValidateCSS("1", "0", "color", "rgb(3, 179, 101)");
|
||||
// // Change the text color and enter purple in input field
|
||||
// cy.get(widgetsPage.textColor)
|
||||
// .scrollIntoView()
|
||||
// .clear({ force: true })
|
||||
// .type("purple", { force: true });
|
||||
// cy.wait("@updateLayout");
|
||||
// // Verify the text color is purple
|
||||
// cy.readTabledataValidateCSS("1", "0", "color", "rgb(128, 0, 128)");
|
||||
// // Click on cell background color
|
||||
// cy.get(`${widgetsPage.cellBackground} input`)
|
||||
// .first()
|
||||
// .scrollIntoView()
|
||||
// .click({ force: true });
|
||||
// // eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
// cy.wait(500);
|
||||
// // select the green color
|
||||
// cy.xpath(widgetsPage.greenColor)
|
||||
// .first()
|
||||
// .click();
|
||||
// cy.wait("@updateLayout");
|
||||
// // Verify the cell background color is green
|
||||
// cy.readTabledataValidateCSS(
|
||||
// "1",
|
||||
// "0",
|
||||
// "background",
|
||||
// "rgb(3, 179, 101) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
// );
|
||||
// // Change the cell background color and enter purple in input field
|
||||
// cy.get(`${widgetsPage.cellBackground} input`)
|
||||
// .clear({ force: true })
|
||||
// .type("purple", { force: true });
|
||||
// cy.wait("@updateLayout");
|
||||
// // Verify the cell background color is purple
|
||||
// cy.readTabledataValidateCSS(
|
||||
// "1",
|
||||
// "0",
|
||||
// "background",
|
||||
// "rgb(128, 0, 128) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
// );
|
||||
// });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -126,10 +126,12 @@ describe("Table Widget property pane feature validation", function() {
|
|||
});
|
||||
|
||||
it("Column Detail - Edit column name and validate test for computed value based on column type selected", function() {
|
||||
cy.wait(1000);
|
||||
cy.makeColumnVisible("email");
|
||||
cy.makeColumnVisible("userName");
|
||||
cy.makeColumnVisible("productName");
|
||||
cy.makeColumnVisible("orderAmount");
|
||||
cy.openPropertyPane("tablewidget");
|
||||
|
||||
// Open column detail to be edited by draggable id
|
||||
cy.editColumn("id");
|
||||
|
|
@ -210,8 +212,8 @@ describe("Table Widget property pane feature validation", function() {
|
|||
cy.changeColumnType("URL");
|
||||
// "Image" to "url"
|
||||
cy.updateComputedValue(testdata.currentRowEmail);
|
||||
cy.readTabledataPublish("1", "0").then((tabData2) => {
|
||||
expect(tabData2).to.not.equal("lindsay.ferguson@reqres.in");
|
||||
cy.readTabledataPublish("1", "0", true).then((tabData2) => {
|
||||
expect(tabData2).not.to.equal("lindsay.ferguson@reqres.in");
|
||||
cy.log("computed value of URL is " + tabData2);
|
||||
});
|
||||
});
|
||||
|
|
@ -222,19 +224,25 @@ describe("Table Widget property pane feature validation", function() {
|
|||
cy.get(widgetsPage.centerAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTabledataValidateCSS("1", "0", "justify-content", "center");
|
||||
cy.readTabledataValidateCSS("1", "0", "justify-content", "center", true);
|
||||
|
||||
// Verifying Right Alignment
|
||||
cy.get(widgetsPage.rightAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTabledataValidateCSS("1", "0", "justify-content", "flex-end");
|
||||
cy.readTabledataValidateCSS("1", "0", "justify-content", "flex-end", true);
|
||||
|
||||
// Verifying Left Alignment
|
||||
cy.get(widgetsPage.leftAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTabledataValidateCSS("0", "0", "justify-content", "flex-start");
|
||||
cy.readTabledataValidateCSS(
|
||||
"0",
|
||||
"0",
|
||||
"justify-content",
|
||||
"flex-start",
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("Test to validate text format", function() {
|
||||
|
|
@ -249,17 +257,17 @@ describe("Table Widget property pane feature validation", function() {
|
|||
it("Test to validate vertical allignment", function() {
|
||||
// Validate vertical alignemnt of Cell text to TOP
|
||||
cy.get(widgetsPage.verticalTop).click({ force: true });
|
||||
cy.readTabledataValidateCSS("1", "0", "align-items", "flex-start");
|
||||
cy.readTabledataValidateCSS("1", "0", "align-items", "flex-start", true);
|
||||
// Validate vertical alignemnt of Cell text to Center
|
||||
cy.get(widgetsPage.verticalCenter)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.readTabledataValidateCSS("1", "0", "align-items", "center");
|
||||
cy.readTabledataValidateCSS("1", "0", "align-items", "center", true);
|
||||
// Validate vertical alignemnt of Cell text to Bottom
|
||||
cy.get(widgetsPage.verticalBottom)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.readTabledataValidateCSS("0", "0", "align-items", "flex-end");
|
||||
cy.readTabledataValidateCSS("0", "0", "align-items", "flex-end", true);
|
||||
});
|
||||
|
||||
it("Test to validate text color and text background", function() {
|
||||
|
|
@ -271,12 +279,12 @@ describe("Table Widget property pane feature validation", function() {
|
|||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(5000);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(3, 179, 101)");
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(3, 179, 101)", true);
|
||||
// Changing text color to PURPLE and validate using JS
|
||||
cy.get(widgetsPage.toggleJsColor).click();
|
||||
cy.testCodeMirrorLast("purple");
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(128, 0, 128)");
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(128, 0, 128)", true);
|
||||
// Changing Cell backgroud color to GREEN and validate
|
||||
cy.get(widgetsPage.backgroundColor)
|
||||
.first()
|
||||
|
|
@ -288,6 +296,7 @@ describe("Table Widget property pane feature validation", function() {
|
|||
"0",
|
||||
"background",
|
||||
"rgb(3, 179, 101) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
true,
|
||||
);
|
||||
// Changing Cell backgroud color to PURPLE and validate using JS
|
||||
cy.get(widgetsPage.toggleJsBcgColor).click();
|
||||
|
|
@ -298,6 +307,7 @@ describe("Table Widget property pane feature validation", function() {
|
|||
"0",
|
||||
"background",
|
||||
"rgb(128, 0, 128) none repeat scroll 0% 0% / auto padding-box border-box",
|
||||
true,
|
||||
);
|
||||
// close property pane
|
||||
cy.closePropertyPane();
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ describe("Git sync:", function() {
|
|||
cy.get("[data-cy=t--tab-DEPLOY]")
|
||||
.invoke("attr", "aria-selected")
|
||||
.should("eq", "true");
|
||||
cy.get(gitSyncLocators.closeGitSyncModal).click();
|
||||
cy.get(gitSyncLocators.closeGitSyncModal).click({ force: true });
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
// import gitSyncLocators from "../../../../locators/gitSyncLocators";
|
||||
import gitSyncLocators from "../../../../locators/gitSyncLocators";
|
||||
|
||||
// let repoName1, repoName2, repoName3, repoName4, windowOpenSpy;
|
||||
// describe("Repo Limit Exceeded Error Modal", function() {
|
||||
// before(() => {
|
||||
// const uuid = require("uuid");
|
||||
// repoName1 = uuid.v4().split("-")[0];
|
||||
// repoName2 = uuid.v4().split("-")[0];
|
||||
// repoName3 = uuid.v4().split("-")[0];
|
||||
// repoName4 = uuid.v4().split("-")[0];
|
||||
// });
|
||||
let repoName1, repoName2, repoName3, repoName4, windowOpenSpy;
|
||||
describe("Repo Limit Exceeded Error Modal", function() {
|
||||
before(() => {
|
||||
const uuid = require("uuid");
|
||||
repoName1 = uuid.v4().split("-")[0];
|
||||
repoName2 = uuid.v4().split("-")[0];
|
||||
repoName3 = uuid.v4().split("-")[0];
|
||||
repoName4 = uuid.v4().split("-")[0];
|
||||
});
|
||||
|
||||
// it.only("modal should be opened with proper components", function() {
|
||||
// cy.createAppAndConnectGit(repoName1, false);
|
||||
// cy.createAppAndConnectGit(repoName2, false);
|
||||
// cy.createAppAndConnectGit(repoName3, false);
|
||||
// cy.createAppAndConnectGit(repoName4, false, true);
|
||||
it("modal should be opened with proper components", function() {
|
||||
cy.createAppAndConnectGit(repoName1, false);
|
||||
cy.createAppAndConnectGit(repoName2, false);
|
||||
cy.createAppAndConnectGit(repoName3, false);
|
||||
cy.createAppAndConnectGit(repoName4, false, true);
|
||||
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).should("exist");
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).should("exist");
|
||||
|
||||
// // title and info text checking
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
// Cypress.env("MESSAGES").REPOSITORY_LIMIT_REACHED(),
|
||||
// );
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
// Cypress.env("MESSAGES").REPOSITORY_LIMIT_REACHED_INFO(),
|
||||
// );
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
// Cypress.env("MESSAGES").CONTACT_SUPPORT_TO_UPGRADE(),
|
||||
// );
|
||||
// cy.get(gitSyncLocators.contactSalesButton).should("exist");
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
// Cypress.env("MESSAGES").DISCONNECT_CAUSE_APPLICATION_BREAK(),
|
||||
// );
|
||||
// title and info text checking
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
Cypress.env("MESSAGES").REPOSITORY_LIMIT_REACHED(),
|
||||
);
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
Cypress.env("MESSAGES").REPOSITORY_LIMIT_REACHED_INFO(),
|
||||
);
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
Cypress.env("MESSAGES").CONTACT_SUPPORT_TO_UPGRADE(),
|
||||
);
|
||||
cy.get(gitSyncLocators.contactSalesButton).should("exist");
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).contains(
|
||||
Cypress.env("MESSAGES").DISCONNECT_CAUSE_APPLICATION_BREAK(),
|
||||
);
|
||||
|
||||
// // learn more link checking
|
||||
// cy.window().then((window) => {
|
||||
// windowOpenSpy = cy.stub(window, "open").callsFake((url) => {
|
||||
// expect(url.startsWith("https://docs.appsmith.com/")).to.be.true;
|
||||
// windowOpenSpy.restore();
|
||||
// });
|
||||
// });
|
||||
// cy.get(gitSyncLocators.learnMoreOnRepoLimitModal).click();
|
||||
// learn more link checking
|
||||
cy.window().then((window) => {
|
||||
windowOpenSpy = cy.stub(window, "open").callsFake((url) => {
|
||||
expect(url.startsWith("https://docs.appsmith.com/")).to.be.true;
|
||||
windowOpenSpy.restore();
|
||||
});
|
||||
});
|
||||
cy.get(gitSyncLocators.learnMoreOnRepoLimitModal).click();
|
||||
|
||||
// cy.get(gitSyncLocators.connectedApplication).should("have.length", 3);
|
||||
// cy.get(gitSyncLocators.diconnectLink)
|
||||
// .first()
|
||||
// .click();
|
||||
cy.get(gitSyncLocators.connectedApplication).should("have.length", 3);
|
||||
cy.get(gitSyncLocators.diconnectLink)
|
||||
.first()
|
||||
.click();
|
||||
|
||||
// cy.get(gitSyncLocators.repoLimitExceededErrorModal).should("not.exist");
|
||||
// cy.get(gitSyncLocators.disconnectGitModal).should("exist");
|
||||
cy.get(gitSyncLocators.repoLimitExceededErrorModal).should("not.exist");
|
||||
cy.get(gitSyncLocators.disconnectGitModal).should("exist");
|
||||
|
||||
// cy.request({
|
||||
// method: "DELETE",
|
||||
// url: "api/v1/applications/" + repoName1,
|
||||
// failOnStatusCode: false,
|
||||
// });
|
||||
// cy.request({
|
||||
// method: "DELETE",
|
||||
// url: "api/v1/applications/" + repoName2,
|
||||
// failOnStatusCode: false,
|
||||
// });
|
||||
// cy.request({
|
||||
// method: "DELETE",
|
||||
// url: "api/v1/applications/" + repoName3,
|
||||
// failOnStatusCode: false,
|
||||
// });
|
||||
// cy.request({
|
||||
// method: "DELETE",
|
||||
// url: "api/v1/applications/" + repoName4,
|
||||
// failOnStatusCode: false,
|
||||
// });
|
||||
// cy.deleteTestGithubRepo(repoName1);
|
||||
// cy.deleteTestGithubRepo(repoName2);
|
||||
// cy.deleteTestGithubRepo(repoName3);
|
||||
// cy.deleteTestGithubRepo(repoName4);
|
||||
// });
|
||||
// });
|
||||
cy.request({
|
||||
method: "DELETE",
|
||||
url: "api/v1/applications/" + repoName1,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.request({
|
||||
method: "DELETE",
|
||||
url: "api/v1/applications/" + repoName2,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.request({
|
||||
method: "DELETE",
|
||||
url: "api/v1/applications/" + repoName3,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.request({
|
||||
method: "DELETE",
|
||||
url: "api/v1/applications/" + repoName4,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.deleteTestGithubRepo(repoName1);
|
||||
cy.deleteTestGithubRepo(repoName2);
|
||||
cy.deleteTestGithubRepo(repoName3);
|
||||
cy.deleteTestGithubRepo(repoName4);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
const queryLocators = require("../../../../locators/QueryEditor.json");
|
||||
const datasourceEditor = require("../../../../locators/DatasourcesEditor.json");
|
||||
const dsl = require("../../../../fixtures/noiseDsl.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
describe("MySQL noise test", function() {
|
||||
let datasourceName;
|
||||
beforeEach(() => {
|
||||
cy.addDsl(dsl);
|
||||
cy.startRoutesForDatasource();
|
||||
});
|
||||
|
||||
it("Verify after killing MySQL session, app should not crash", function() {
|
||||
cy.NavigateToDatasourceEditor();
|
||||
cy.get(datasourceEditor.MySQL).click();
|
||||
cy.generateUUID().then((uid) => {
|
||||
datasourceName = uid;
|
||||
cy.get(".t--edit-datasource-name").click();
|
||||
cy.get(".t--edit-datasource-name input")
|
||||
.clear()
|
||||
.type(datasourceName, { force: true })
|
||||
.should("have.value", datasourceName)
|
||||
.blur();
|
||||
cy.getPluginFormsAndCreateDatasource();
|
||||
cy.fillMySQLDatasourceForm();
|
||||
cy.testSaveDatasource();
|
||||
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,
|
||||
});
|
||||
cy.WaitAutoSave();
|
||||
cy.runQuery();
|
||||
cy.NavigateToAPI_Panel();
|
||||
cy.log("Navigation to API Panel screen successful");
|
||||
// API for killing mySQL session
|
||||
cy.CreateAPI("killSession");
|
||||
cy.enterDatasourceAndPath("http://localhost:5001/", "v1/noise/killmysql");
|
||||
cy.SaveAndRunAPI();
|
||||
cy.ResponseCheck("killed");
|
||||
cy.get('.t--entity-name:contains("Page1")').click({ force: true });
|
||||
cy.wait(2000);
|
||||
// run kill query
|
||||
cy.get(".bp3-button-text:contains('Kill Session')").should("be.visible");
|
||||
cy.get(".bp3-button-text:contains('Kill Session')").click({ force: true });
|
||||
// run refresh query
|
||||
cy.get(".bp3-button-text:contains('Refresh Query')").click({ force: true });
|
||||
cy.wait(2000);
|
||||
cy.get(commonlocators.toastmsg).contains(
|
||||
"UncaughtPromiseRejection: NoiseTestQuery failed to execute",
|
||||
);
|
||||
cy.wait("@postExecute", { timeout: 8000 }).then(({ response }) => {
|
||||
expect(response.body.data.statusCode).to.eq("200 OK");
|
||||
});
|
||||
cy.wait("@postExecute", { timeout: 8000 }).then(({ response }) => {
|
||||
expect(response.body.data.statusCode).to.eq("200 OK");
|
||||
});
|
||||
cy.wait("@postExecute", { timeout: 8000 }).then(({ response }) => {
|
||||
expect(response.body.data.statusCode).to.eq("5004");
|
||||
expect(response.body.data.title).to.eq(
|
||||
"Datasource configuration is invalid",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
import { AggregateHelper } from "../../../../support/Pages/AggregateHelper";
|
||||
import { JSEditor } from "../../../../support/Pages/JSEditor";
|
||||
import { DataSources } from "../../../../support/Pages/DataSources";
|
||||
import { CommonLocators } from "../../../../support/Objects/CommonLocators";
|
||||
|
||||
const agHelper = new AggregateHelper();
|
||||
const jsEditor = new JSEditor();
|
||||
const dataSources = new DataSources();
|
||||
const locator = new CommonLocators();
|
||||
|
||||
describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
||||
describe("[Bug] - 10784 - Passing params from JS to SQL query should not break", () => {
|
||||
before(() => {
|
||||
cy.fixture('paramsDsl').then((val: any) => {
|
||||
agHelper.AddDsl(val)
|
||||
|
|
@ -15,7 +17,7 @@ describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
|||
|
||||
let guid: any;
|
||||
|
||||
it("1. [Bug] - 10784 : Passing params from JS to SQL query should not break", function () {
|
||||
it("1. With Optional chaining : {{ this?.params?.condition }}", function () {
|
||||
agHelper.NavigateToDSCreateNew()
|
||||
dataSources.CreatePlugIn('PostgreSQL')
|
||||
dataSources.FillPostgresDSForm();
|
||||
|
|
@ -27,18 +29,297 @@ describe("Validate Create Api and Bind to Table widget via JSObject", () => {
|
|||
cy.log("ds name is :" + guid)
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params")
|
||||
agHelper.RenameWithInPane("Params1")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{this?.params?.condition || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
jsEditor.CreateJSObject('Params1.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
})
|
||||
agHelper.SelectEntityByName("WIDGETS")
|
||||
agHelper.SelectEntityByName("Table1") //tabledata
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params.data}}");
|
||||
agHelper.SelectEntityByName("WIDGETS")
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params1.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '7')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
});
|
||||
|
||||
it("2. With Optional chaining : {{ (function() { return this?.params?.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params2")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(function() { return this?.params?.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params2.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params2.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '9')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
});
|
||||
|
||||
it("3. With Optional chaining : {{ (() => { return this?.params?.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params3")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(() => { return this?.params?.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params3.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params3.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '8')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
});
|
||||
|
||||
it("4. With Optional chaining : {{ this?.params.condition }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params4")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{this?.params.condition || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params4.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params4.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '7')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
});
|
||||
|
||||
it("5. With Optional chaining : {{ (function() { return this?.params.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params5")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(function() { return this?.params.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params5.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params5.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '9')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
});
|
||||
|
||||
it("6. With Optional chaining : {{ (() => { return this?.params.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params6")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(() => { return this?.params.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params6.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params6.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '8')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
});
|
||||
|
||||
it("7. With No Optional chaining : {{ this.params.condition }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params7")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{this.params.condition || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params7.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params7.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '7')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
});
|
||||
|
||||
it("8. With No Optional chaining : {{ (function() { return this.params.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params8")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(function() { return this.params.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params8.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params8.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '9')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
});
|
||||
|
||||
it("9. With No Optional chaining : {{ (() => { return this.params.condition })() }}", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params9")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(() => { return this.params.condition })() || '1=1'}} order by id");
|
||||
jsEditor.CreateJSObject('Params9.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params9.data}}");
|
||||
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('9');
|
||||
});
|
||||
|
||||
agHelper.SelectDropDown("selectwidget", '8')
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('8');
|
||||
});
|
||||
});
|
||||
|
||||
it("10. With Optional chaining : {{ this?.params?.condition }} && no optional paramter passed", function () {
|
||||
dataSources.NavigateToActiveDSQueryPane(guid);
|
||||
agHelper.GetNClick(dataSources._templateMenu)
|
||||
agHelper.RenameWithInPane("Params10")
|
||||
agHelper.EnterValue("SELECT * FROM public.users where id = {{(() => { return this.params.condition })() || '7'}} order by id");
|
||||
jsEditor.CreateJSObject('Params10.run(() => {},() => {},{"condition": selRecordFilter.selectedOptionValue})');
|
||||
|
||||
agHelper.SelectEntityByName("Button1")
|
||||
cy.get("@jsObjName").then((jsObjName) => {
|
||||
jsEditor.EnterJSContext('onclick', "{{" + jsObjName + ".myFun1()}}", true, true);
|
||||
});
|
||||
agHelper.SelectEntityByName("Table1")
|
||||
jsEditor.EnterJSContext('tabledata', "{{Params10.data}}");
|
||||
|
||||
//When No selected option passed
|
||||
cy.xpath(locator._selectWidgetDropdown("selectwidget")).within(() => cy.get(locator._crossBtn).click())
|
||||
agHelper.ClickButton("Submit")
|
||||
agHelper.Sleep(2000)
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
agHelper.ReadTableRowColumnData(0, 0).then((cellData) => {
|
||||
expect(cellData).to.be.equal('7');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -37,7 +37,7 @@ export class CommonLocators {
|
|||
_entityNameEditing = (entityNameinLeftSidebar: string) => "//span[text()='" + entityNameinLeftSidebar + "']/parent::div[contains(@class, 't--entity-name editing')]/input"
|
||||
_jsToggle = (controlToToggle: string) => ".t--property-control-" + controlToToggle + " .t--js-toggle"
|
||||
_spanButton = (btnVisibleText: string) => "//span[text()='" + btnVisibleText + "']/parent::button"
|
||||
_selectDropdown = (ddName: string) => "//div[contains(@class, 't--property-control-" + ddName + "')]//button"
|
||||
_selectPropDropdown = (ddName: string) => "//div[contains(@class, 't--property-control-" + ddName + "')]//button"
|
||||
_dropDownValue = (ddOption: string) => ".single-select:contains('" + ddOption + "')"
|
||||
_actionTextArea = (actionName: string) => "//label[text()='" + actionName + "']/following-sibling::div//div[contains(@class, 'CodeMirror')]//textarea"
|
||||
_existingDefaultTextInput = ".t--property-control-defaulttext .CodeMirror-code"
|
||||
|
|
@ -46,8 +46,12 @@ export class CommonLocators {
|
|||
_widgetInDeployed = (widgetType: string) => `.t--widget-${widgetType}`
|
||||
_propertyToggle = (controlToToggle: string) => ".t--property-control-" + controlToToggle + " input[type='checkbox']"
|
||||
_openNavigationTab = (tabToOpen: string) => `#switcher--${tabToOpen}`
|
||||
_selectWidgetDropdown = (widgetType: string) => "//div[contains(@class, 't--draggable-" + widgetType + "')]//button"
|
||||
_createNewPlgin = (pluginName: string) => ".t--plugin-name:contains('" + pluginName + "')"
|
||||
_inputFieldByName = (fieldName: string) => "//p[text()='" + fieldName + "']/parent::label/following-sibling::div"
|
||||
_evaluatedCurrentValue = "div:last-of-type .t--CodeEditor-evaluatedValue > div:last-of-type pre"
|
||||
_tableRowColumn = (rowNum: number, colNum: number) => `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div div`
|
||||
_crossBtn = "span.cancel-icon"
|
||||
_createNew = ".t--entity-add-btn.group.files"
|
||||
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ export class AggregateHelper {
|
|||
}
|
||||
|
||||
public NavigateToDSAdd() {
|
||||
cy.get(locator._addNewDataSource).last()
|
||||
cy.get(locator._addNewDataSource).last().scrollIntoView()
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ export class AggregateHelper {
|
|||
}
|
||||
|
||||
public SelectEntityByName(entityNameinLeftSidebar: string) {
|
||||
cy.xpath(locator._entityNameInExplorer(entityNameinLeftSidebar))
|
||||
cy.xpath(locator._entityNameInExplorer(entityNameinLeftSidebar), {timeout: 30000})
|
||||
.last()
|
||||
.click({ multiple: true })
|
||||
this.Sleep()
|
||||
|
|
@ -164,7 +164,7 @@ export class AggregateHelper {
|
|||
}).then(() => this.Sleep(timeout))
|
||||
}
|
||||
|
||||
public ValidateNetworkCallRespPost(aliasName: string, expectedRes = true) {
|
||||
public ValidateNetworkExecutionSuccess(aliasName: string, expectedRes = true) {
|
||||
cy.wait(aliasName).should(
|
||||
"have.nested.property",
|
||||
"response.body.data.isExecutionSuccess",
|
||||
|
|
@ -172,6 +172,14 @@ export class AggregateHelper {
|
|||
)
|
||||
}
|
||||
|
||||
public ValidateNetworkStatus(aliasName: string, expectedRes = 200) {
|
||||
cy.wait(aliasName).should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
expectedRes,
|
||||
)
|
||||
}
|
||||
|
||||
public ValidateNetworkCallRespPut(aliasName: string, expectedStatus = 200) {
|
||||
cy.wait(aliasName).should(
|
||||
"have.nested.property",
|
||||
|
|
@ -181,13 +189,22 @@ export class AggregateHelper {
|
|||
}
|
||||
|
||||
public SelectPropertiesDropDown(endp: string, ddOption: string,) {
|
||||
cy.xpath(locator._selectDropdown(endp))
|
||||
cy.xpath(locator._selectPropDropdown(endp))
|
||||
.first()
|
||||
.scrollIntoView()
|
||||
.click()
|
||||
cy.get(locator._dropDownValue(ddOption)).click()
|
||||
}
|
||||
|
||||
public SelectDropDown(endp: string, ddOption: string,) {
|
||||
cy.xpath(locator._selectWidgetDropdown(endp))
|
||||
.first()
|
||||
.scrollIntoView()
|
||||
.click()
|
||||
cy.get(locator._dropDownValue(ddOption)).click({ force: true })
|
||||
this.Sleep(2000)
|
||||
}
|
||||
|
||||
public EnterActionValue(actionName: string, value: string, paste = true) {
|
||||
cy.xpath(locator._actionTextArea(actionName))
|
||||
.first()
|
||||
|
|
@ -274,7 +291,8 @@ export class AggregateHelper {
|
|||
}
|
||||
|
||||
public GetObjectName() {
|
||||
cy.get(locator._queryName).invoke("text").then((text) => cy.wrap(text).as("queryName"));
|
||||
//cy.get(locator._queryName).invoke("text").then((text) => cy.wrap(text).as("queryName")); or below syntax
|
||||
return cy.get(locator._queryName).invoke("text");
|
||||
}
|
||||
|
||||
public Sleep(timeout = 1000) {
|
||||
|
|
@ -288,7 +306,6 @@ export class AggregateHelper {
|
|||
cy.get(locator._homePageAppCreateBtn)
|
||||
.should("be.visible")
|
||||
.should("be.enabled");
|
||||
//cy.get(this._homePageAppCreateBtn);
|
||||
}
|
||||
|
||||
public CreateNewApplication() {
|
||||
|
|
@ -364,4 +381,8 @@ export class AggregateHelper {
|
|||
if ($text.text()) expect($text.text()).to.eq(currentValue);
|
||||
});
|
||||
}
|
||||
|
||||
public ReadTableRowColumnData(rowNum: number, colNum: number) {
|
||||
return cy.get(locator._tableRowColumn(rowNum, colNum)).invoke("text");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { AggregateHelper } from "./AggregateHelper";
|
||||
import explorer from "../../locators/explorerlocators.json";
|
||||
import { CommonLocators } from "../Objects/CommonLocators";
|
||||
|
||||
const agHelper = new AggregateHelper();
|
||||
const locator = new CommonLocators()
|
||||
|
||||
export class ApiPage {
|
||||
|
||||
|
|
@ -15,16 +17,14 @@ export class ApiPage {
|
|||
private _queryTimeout = "//input[@name='actionConfiguration.timeoutInMillisecond']"
|
||||
private _apiTab = (tabValue: string) => "span:contains('" + tabValue + "')"
|
||||
_responseBody = ".CodeMirror-code span.cm-string.cm-property"
|
||||
private _blankAPI = "span:contains('New Blank API')"
|
||||
|
||||
|
||||
CreateAndFillApi(url: string, apiname: string = "", queryTimeout = 30000) {
|
||||
cy.get(explorer.createNew).click({ force: true });
|
||||
cy.get(explorer.blankAPI).click({ force: true });
|
||||
cy.wait("@createNewApi").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
201,
|
||||
);
|
||||
cy.get(locator._createNew).click({ force: true });
|
||||
cy.get(this._blankAPI).click({ force: true });
|
||||
agHelper.ValidateNetworkStatus("@createNewApi", 201)
|
||||
|
||||
// cy.get("@createNewApi").then((response: any) => {
|
||||
// expect(response.response.body.responseMeta.success).to.eq(true);
|
||||
// cy.get(agHelper._actionName)
|
||||
|
|
@ -35,6 +35,7 @@ export class ApiPage {
|
|||
// expect(someText).to.equal(response.response.body.data.name);
|
||||
// });
|
||||
// }); // to check if Api1 = Api1 when Create Api invoked
|
||||
|
||||
if (apiname)
|
||||
agHelper.RenameWithInPane(apiname)
|
||||
cy.get(this._resourceUrl).should("be.visible");
|
||||
|
|
@ -83,11 +84,7 @@ export class ApiPage {
|
|||
|
||||
RunAPI() {
|
||||
cy.get(this._apiRunBtn).click({ force: true });
|
||||
cy.wait("@postExecute").should(
|
||||
"have.nested.property",
|
||||
"response.body.data.isExecutionSuccess",
|
||||
true,
|
||||
);
|
||||
agHelper.ValidateNetworkExecutionSuccess("@postExecute")
|
||||
}
|
||||
|
||||
SetAPITimeout(timeout: number) {
|
||||
|
|
@ -109,15 +106,15 @@ export class ApiPage {
|
|||
}
|
||||
|
||||
ReadApiResponsebyKey(key: string) {
|
||||
let apiResp: string = "";
|
||||
cy.get(this._responseBody)
|
||||
.contains(key)
|
||||
.siblings("span")
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
apiResp = `${text.match(/"(.*)"/)![0].split('"').join("") } `;
|
||||
cy.log("Key value in api response is :" + apiResp);
|
||||
cy.wrap(apiResp).as("apiResp")
|
||||
});
|
||||
let apiResp: string = "";
|
||||
cy.get(this._responseBody)
|
||||
.contains(key)
|
||||
.siblings("span")
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
apiResp = `${text.match(/"(.*)"/)![0].split('"').join("")} `;
|
||||
cy.log("Key value in api response is :" + apiResp);
|
||||
cy.wrap(apiResp).as("apiResp")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,15 @@ const agHelper = new AggregateHelper();
|
|||
const locator = new CommonLocators();
|
||||
|
||||
export class JSEditor {
|
||||
private _runButton =
|
||||
"//li//*[local-name() = 'svg' and @class='run-button']/parent::li";
|
||||
private _outputConsole = ".CodeEditorTarget";
|
||||
private _jsObjName = ".t--js-action-name-edit-field span";
|
||||
private _jsObjTxt = ".t--js-action-name-edit-field input";
|
||||
private _addEntityJSEditor = ".t--entity-add-btn.group.files"
|
||||
private _runButton = "//li//*[local-name() = 'svg' and @class='run-button']/parent::li"
|
||||
private _outputConsole = ".CodeEditorTarget"
|
||||
private _jsObjName = ".t--js-action-name-edit-field span"
|
||||
private _jsObjTxt = ".t--js-action-name-edit-field input"
|
||||
private _newJSobj = "span:contains('New JS Object')"
|
||||
private _bindingsClose = ".t--entity-property-close"
|
||||
|
||||
public NavigateToJSEditor() {
|
||||
cy.get(this._addEntityJSEditor)
|
||||
cy.get(locator._createNew)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.get(this._newJSobj).click({ force: true });
|
||||
|
|
@ -46,8 +44,10 @@ export class JSEditor {
|
|||
}
|
||||
});
|
||||
|
||||
agHelper.WaitAutoSave()//Ample wait due to open bug # 10284
|
||||
agHelper.Sleep(5000)//Ample wait due to open bug # 10284
|
||||
//clicking 2 times each with interval of 1 second!
|
||||
|
||||
//clicking 1 times & waits for 3 second for result to be populated!
|
||||
Cypress._.times(1, () => {
|
||||
cy.xpath(this._runButton)
|
||||
.first()
|
||||
|
|
@ -62,8 +62,14 @@ export class JSEditor {
|
|||
public EnterJSContext(endp: string, value: string, paste = true, toToggleOnJS = false) {
|
||||
if (toToggleOnJS) {
|
||||
cy.get(locator._jsToggle(endp))
|
||||
.first()
|
||||
.click({ force: true });
|
||||
.invoke("attr", "class")
|
||||
.then((classes: any) => {
|
||||
if (!classes.includes("is-active")) {
|
||||
cy.get(locator._jsToggle(endp))
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
cy.get(locator._propertyControl + endp + " " + locator._codeMirrorTextArea)
|
||||
.first()
|
||||
|
|
@ -140,5 +146,5 @@ export class JSEditor {
|
|||
});
|
||||
cy.get(this._bindingsClose).click({ force: true });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1721,8 +1721,10 @@ Cypress.Commands.add("editColumn", (colId) => {
|
|||
|
||||
Cypress.Commands.add(
|
||||
"readTabledataValidateCSS",
|
||||
(rowNum, colNum, cssProperty, cssValue) => {
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div`;
|
||||
(rowNum, colNum, cssProperty, cssValue, shouldNotGotOneLeveDeeper) => {
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div ${
|
||||
!shouldNotGotOneLeveDeeper ? "div" : ""
|
||||
}`;
|
||||
cy.get(selector).should("have.css", cssProperty, cssValue);
|
||||
},
|
||||
);
|
||||
|
|
@ -2862,7 +2864,7 @@ Cypress.Commands.add("isSelectRow", (index) => {
|
|||
|
||||
Cypress.Commands.add("readTabledata", (rowNum, colNum) => {
|
||||
// const selector = `.t--draggable-tablewidget .e-gridcontent.e-lib.e-droppable td[index=${rowNum}][aria-colindex=${colNum}]`;
|
||||
const selector = `.tbody .td[data-rowindex="${rowNum}"][data-colindex="${colNum}"] div`;
|
||||
const selector = `.tbody .td[data-rowindex="${rowNum}"][data-colindex="${colNum}"] div div`;
|
||||
const tabVal = cy.get(selector).invoke("text");
|
||||
return tabVal;
|
||||
});
|
||||
|
|
@ -3059,16 +3061,21 @@ Cypress.Commands.add("ExportVerify", (togglecss, name) => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add("getTableDataSelector", (rowNum, colNum) => {
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div`;
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div div`;
|
||||
return selector;
|
||||
});
|
||||
|
||||
Cypress.Commands.add("readTabledataPublish", (rowNum, colNum) => {
|
||||
// const selector = `.t--widget-tablewidget .e-gridcontent.e-lib.e-droppable td[index=${rowNum}][aria-colindex=${colNum}]`;
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div`;
|
||||
const tabVal = cy.get(selector).invoke("text");
|
||||
return tabVal;
|
||||
});
|
||||
Cypress.Commands.add(
|
||||
"readTabledataPublish",
|
||||
(rowNum, colNum, shouldNotGotOneLeveDeeper) => {
|
||||
// const selector = `.t--widget-tablewidget .e-gridcontent.e-lib.e-droppable td[index=${rowNum}][aria-colindex=${colNum}]`;
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div ${
|
||||
!shouldNotGotOneLeveDeeper ? "div" : ""
|
||||
}`;
|
||||
const tabVal = cy.get(selector).invoke("text");
|
||||
return tabVal;
|
||||
},
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
"readTabledataFromSpecificIndex",
|
||||
|
|
@ -3095,7 +3102,7 @@ Cypress.Commands.add("tablefirstdataRow", () => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add("scrollTabledataPublish", (rowNum, colNum) => {
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div`;
|
||||
const selector = `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}] div div`;
|
||||
const tabVal = cy
|
||||
.get(selector)
|
||||
.scrollIntoView()
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ module.exports = {
|
|||
enableGithubOAuth: parseConfig("__APPSMITH_OAUTH2_GITHUB_CLIENT_ID__"),
|
||||
disableLoginForm: parseConfig("__APPSMITH_FORM_LOGIN_DISABLED__"),
|
||||
disableSignup: parseConfig("__APPSMITH_SIGNUP_DISABLED__"),
|
||||
disableTelemetry: parseConfig("__APPSMITH_DISABLE_TELEMETRY__"),
|
||||
enableRapidAPI: parseConfig("__APPSMITH_MARKETPLACE_ENABLED__"),
|
||||
segment: {
|
||||
apiKey: parseConfig("__APPSMITH_SEGMENT_KEY__"),
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@
|
|||
enableGithubOAuth: parseConfig("__APPSMITH_OAUTH2_GITHUB_CLIENT_ID__"),
|
||||
disableLoginForm: parseConfig("__APPSMITH_FORM_LOGIN_DISABLED__"),
|
||||
disableSignup: parseConfig("__APPSMITH_SIGNUP_DISABLED__"),
|
||||
disableTelemetry: parseConfig("__APPSMITH_DISABLE_TELEMETRY__"),
|
||||
enableRapidAPI: parseConfig("__APPSMITH_MARKETPLACE_ENABLED__"),
|
||||
segment: {
|
||||
apiKey: parseConfig("__APPSMITH_SEGMENT_KEY__"),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export interface INJECTED_CONFIGS {
|
|||
enableGithubOAuth: boolean;
|
||||
disableLoginForm: boolean;
|
||||
disableSignup: boolean;
|
||||
disableTelemetry: boolean;
|
||||
enableRapidAPI: boolean;
|
||||
segment: {
|
||||
apiKey: string;
|
||||
|
|
@ -77,6 +78,9 @@ export const getConfigsFromEnvVars = (): INJECTED_CONFIGS => {
|
|||
disableSignup: process.env.APPSMITH_SIGNUP_DISABLED
|
||||
? process.env.APPSMITH_SIGNUP_DISABLED.length > 0
|
||||
: false,
|
||||
disableTelemetry: process.env.APPSMITH_DISABLE_TELEMETRY
|
||||
? process.env.APPSMITH_DISABLE_TELEMETRY.length > 0
|
||||
: false,
|
||||
segment: {
|
||||
apiKey: process.env.REACT_APP_SEGMENT_KEY || "",
|
||||
ceKey: process.env.REACT_APP_SEGMENT_CE_KEY || "",
|
||||
|
|
@ -246,6 +250,8 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => {
|
|||
ENV_CONFIG.disableLoginForm || APPSMITH_FEATURE_CONFIGS.disableLoginForm,
|
||||
disableSignup:
|
||||
ENV_CONFIG.disableSignup || APPSMITH_FEATURE_CONFIGS.disableSignup,
|
||||
disableTelemetry:
|
||||
ENV_CONFIG.disableTelemetry || APPSMITH_FEATURE_CONFIGS.disableTelemetry,
|
||||
enableGoogleOAuth:
|
||||
ENV_CONFIG.enableGoogleOAuth ||
|
||||
APPSMITH_FEATURE_CONFIGS.enableGoogleOAuth,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export interface AppsmithUIConfigs {
|
|||
enableGithubOAuth: boolean;
|
||||
disableLoginForm: boolean;
|
||||
disableSignup: boolean;
|
||||
disableTelemetry: boolean;
|
||||
enableMixpanel: boolean;
|
||||
enableTNCPP: boolean;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
} from "constants/ThirdPartyConstants";
|
||||
import {
|
||||
SettingCategories,
|
||||
SettingSubCategories,
|
||||
SettingTypes,
|
||||
SettingSubtype,
|
||||
AdminConfigType,
|
||||
|
|
@ -34,7 +35,7 @@ const Form_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_FORM_LOGIN_DISABLED",
|
||||
category: SettingCategories.FORM_AUTH,
|
||||
subCategory: "form login",
|
||||
subCategory: SettingSubCategories.FORMLOGIN,
|
||||
controlType: SettingTypes.TOGGLE,
|
||||
label: "Form Login Option",
|
||||
toggleText: (value: boolean) => {
|
||||
|
|
@ -48,12 +49,12 @@ const Form_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_SIGNUP_DISABLED",
|
||||
category: SettingCategories.FORM_AUTH,
|
||||
subCategory: "form signup",
|
||||
subCategory: SettingSubCategories.FORMLOGIN,
|
||||
controlType: SettingTypes.TOGGLE,
|
||||
label: "Signup",
|
||||
toggleText: (value: boolean) => {
|
||||
if (value) {
|
||||
return "Allow only invited users to signup";
|
||||
return "Restrict Signups";
|
||||
} else {
|
||||
return " Allow all users to signup";
|
||||
}
|
||||
|
|
@ -62,7 +63,7 @@ const Form_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_FORM_CALLOUT_BANNER",
|
||||
category: SettingCategories.FORM_AUTH,
|
||||
subCategory: "form signup",
|
||||
subCategory: SettingSubCategories.FORMLOGIN,
|
||||
controlType: SettingTypes.LINK,
|
||||
label:
|
||||
"User emails are not verified. This can lead to a breach in your application.",
|
||||
|
|
@ -83,7 +84,7 @@ const Google_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GOOGLE_READ_MORE",
|
||||
category: SettingCategories.GOOGLE_AUTH,
|
||||
subCategory: "google signup",
|
||||
subCategory: SettingSubCategories.GOOGLE,
|
||||
controlType: SettingTypes.LINK,
|
||||
label: "How to configure?",
|
||||
url: GOOGLE_SIGNUP_SETUP_DOC,
|
||||
|
|
@ -91,7 +92,7 @@ const Google_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GOOGLE_CLIENT_ID",
|
||||
category: SettingCategories.GOOGLE_AUTH,
|
||||
subCategory: "google signup",
|
||||
subCategory: SettingSubCategories.GOOGLE,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Client ID",
|
||||
|
|
@ -99,7 +100,7 @@ const Google_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET",
|
||||
category: SettingCategories.GOOGLE_AUTH,
|
||||
subCategory: "google signup",
|
||||
subCategory: SettingSubCategories.GOOGLE,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Client Secret",
|
||||
|
|
@ -107,7 +108,7 @@ const Google_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_SIGNUP_ALLOWED_DOMAINS",
|
||||
category: SettingCategories.GOOGLE_AUTH,
|
||||
subCategory: "google signup",
|
||||
subCategory: SettingSubCategories.GOOGLE,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Allowed Domains",
|
||||
|
|
@ -128,7 +129,7 @@ const Github_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GITHUB_READ_MORE",
|
||||
category: SettingCategories.GITHUB_AUTH,
|
||||
subCategory: "github signup",
|
||||
subCategory: SettingSubCategories.GITHUB,
|
||||
controlType: SettingTypes.LINK,
|
||||
label: "How to configure?",
|
||||
url: GITHUB_SIGNUP_SETUP_DOC,
|
||||
|
|
@ -136,7 +137,7 @@ const Github_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GITHUB_CLIENT_ID",
|
||||
category: SettingCategories.GITHUB_AUTH,
|
||||
subCategory: "github signup",
|
||||
subCategory: SettingSubCategories.GITHUB,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Client ID",
|
||||
|
|
@ -144,7 +145,7 @@ const Github_Auth: AdminConfigType = {
|
|||
{
|
||||
id: "APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET",
|
||||
category: SettingCategories.GITHUB_AUTH,
|
||||
subCategory: "github signup",
|
||||
subCategory: SettingSubCategories.GITHUB,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Client Secret",
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ export const SettingCategories = {
|
|||
GITHUB_AUTH: "github-auth",
|
||||
};
|
||||
|
||||
export const SettingSubCategories = {
|
||||
GOOGLE: "google signup",
|
||||
GITHUB: "github signup",
|
||||
FORMLOGIN: "form login",
|
||||
};
|
||||
|
||||
export type AdminConfigType = {
|
||||
type: string;
|
||||
controlType: SettingTypes;
|
||||
|
|
|
|||
|
|
@ -11,18 +11,21 @@ export const connectedMethods = [
|
|||
!disableLoginForm,
|
||||
].filter(Boolean);
|
||||
|
||||
/* settings is the updated & unsaved settings on Admin settings page */
|
||||
export const saveAllowed = (settings: any) => {
|
||||
if (
|
||||
connectedMethods.length >= 2 ||
|
||||
(connectedMethods.length === 1 &&
|
||||
((!("APPSMITH_FORM_LOGIN_DISABLED" in settings) && !disableLoginForm) ||
|
||||
(settings["APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"] !== "" &&
|
||||
enableGoogleOAuth) ||
|
||||
(settings["APPSMITH_OAUTH2_GITHUB_CLIENT_ID"] !== "" &&
|
||||
enableGithubOAuth)))
|
||||
) {
|
||||
return true;
|
||||
if (connectedMethods.length === 1) {
|
||||
const checkFormLogin = !(
|
||||
"APPSMITH_FORM_LOGIN_DISABLED" in settings || disableLoginForm
|
||||
),
|
||||
checkGoogleAuth =
|
||||
settings["APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"] !== "" &&
|
||||
enableGoogleOAuth,
|
||||
checkGithubAuth =
|
||||
settings["APPSMITH_OAUTH2_GITHUB_CLIENT_ID"] !== "" &&
|
||||
enableGithubOAuth;
|
||||
|
||||
return checkFormLogin || checkGoogleAuth || checkGithubAuth;
|
||||
} else {
|
||||
return false;
|
||||
return connectedMethods.length >= 2;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ import Settings2LineIcon from "remixicon-react/Settings2LineIcon";
|
|||
import FileListLineIcon from "remixicon-react/FileListLineIcon";
|
||||
import HamburgerIcon from "remixicon-react/MenuLineIcon";
|
||||
import MagicLineIcon from "remixicon-react/MagicLineIcon";
|
||||
import UserHeartLineIcon from "remixicon-react/UserHeartLineIcon";
|
||||
|
||||
export enum IconSize {
|
||||
XXS = "extraExtraSmall",
|
||||
|
|
@ -294,6 +295,7 @@ const ICON_LOOKUP = {
|
|||
"trending-flat": <TrendingFlat />,
|
||||
"unread-pin": <UnreadPin />,
|
||||
"user-2": <UserV2Icon />,
|
||||
"user-heart-line": <UserHeartLineIcon />,
|
||||
"view-all": <RightArrowIcon />,
|
||||
"view-less": <LeftArrowIcon />,
|
||||
"warning-line": <WarningLineIcon />,
|
||||
|
|
@ -333,6 +335,7 @@ const ICON_LOOKUP = {
|
|||
loader: <LoaderLineIcon />,
|
||||
logout: <LogoutIcon />,
|
||||
manage: <ManageIcon />,
|
||||
member: <UserHeartLineIcon />,
|
||||
mobile: <MobileIcon />,
|
||||
open: <OpenIcon />,
|
||||
pin: <Pin />,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const InputCopyWrapper = styled.div`
|
|||
align-items: center;
|
||||
|
||||
svg {
|
||||
margin-left: 10px;
|
||||
margin-left: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
import React from "react";
|
||||
import "@testing-library/jest-dom";
|
||||
import {
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
} from "@testing-library/react";
|
||||
import IconSelectControl from "./IconSelectControl";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { noop } from "lodash";
|
||||
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
|
||||
|
||||
describe("<IconSelectControl /> - Keyboard navigation", () => {
|
||||
const getTestComponent = (
|
||||
onPropertyChange: (
|
||||
propertyName: string,
|
||||
propertyValue: string,
|
||||
) => void = noop,
|
||||
) => (
|
||||
<IconSelectControl
|
||||
additionalDynamicData={{
|
||||
dummy: {
|
||||
dummy: 1,
|
||||
},
|
||||
}}
|
||||
controlType="add"
|
||||
deleteProperties={noop}
|
||||
evaluatedValue={undefined}
|
||||
isBindProperty={false}
|
||||
isTriggerProperty={false}
|
||||
label="Icon"
|
||||
onPropertyChange={onPropertyChange}
|
||||
openNextPanel={noop}
|
||||
parentPropertyName="iconName"
|
||||
parentPropertyValue="add"
|
||||
propertyName="iconName"
|
||||
theme={EditorTheme.LIGHT}
|
||||
widgetProperties={undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
it("Pressing tab should focus the component", () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
expect(screen.getByRole("button")).toHaveFocus();
|
||||
});
|
||||
|
||||
it.each(["{Enter}", " ", "{ArrowDown}", "{ArrowUp}"])(
|
||||
"Pressing '%s' should open the icon selector",
|
||||
async (key) => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
expect(screen.queryByRole("list")).toBeNull();
|
||||
userEvent.keyboard(key);
|
||||
expect(screen.queryByRole("list")).toBeInTheDocument();
|
||||
|
||||
// Makes sure search bar is having focus
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("Pressing '{Escape}' should close the icon selector", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
expect(screen.queryByRole("list")).toBeNull();
|
||||
userEvent.keyboard("{Enter}");
|
||||
expect(screen.queryByRole("list")).toBeInTheDocument();
|
||||
userEvent.keyboard("{Escape}");
|
||||
await waitForElementToBeRemoved(screen.getAllByRole("list"));
|
||||
});
|
||||
|
||||
it("Pressing '{ArrowDown}' while search is in focus should remove the focus", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
expect(screen.queryByRole("list")).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
expect(screen.queryByRole("textbox")).not.toHaveFocus();
|
||||
});
|
||||
|
||||
it("Pressing '{Shift} + {ArrowUp}' while search is not in focus should focus search box", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
expect(screen.queryByRole("list")).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
expect(screen.queryByRole("textbox")).not.toHaveFocus();
|
||||
userEvent.keyboard("{Shift}{ArrowUp}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
Icon Arrangement
|
||||
|
||||
(none) add add-column-left add-column-right
|
||||
add-row-bottom add-row-top add-to-artifact add-to-folder
|
||||
airplane align-center align-justify align-left
|
||||
*/
|
||||
it("Pressing '{ArrowDown}' should navigate the icon selection downwards", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-(none)",
|
||||
);
|
||||
// used to shift the focus from search
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add-row-bottom",
|
||||
);
|
||||
});
|
||||
|
||||
it("Pressing '{ArrowUp}' should navigate the icon selection upwards", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-(none)",
|
||||
);
|
||||
// used to shift the focus from search
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-align-right",
|
||||
);
|
||||
|
||||
userEvent.keyboard("{ArrowUp}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-airplane",
|
||||
);
|
||||
});
|
||||
|
||||
it("Pressing '{ArrowRight}' should navigate the icon selection towards right", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-(none)",
|
||||
);
|
||||
// used to shift the focus from search
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add",
|
||||
);
|
||||
});
|
||||
|
||||
it("Pressing '{ArrowLeft}' should navigate the icon selection towards left", async () => {
|
||||
render(getTestComponent());
|
||||
userEvent.tab();
|
||||
userEvent.keyboard("{Enter}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-(none)",
|
||||
);
|
||||
// used to shift the focus from search
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add-column-right",
|
||||
);
|
||||
|
||||
userEvent.keyboard("{ArrowLeft}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add-column-left",
|
||||
);
|
||||
});
|
||||
|
||||
it("Pressing '{Enter}' or ' ' should select the icon", async () => {
|
||||
const handleOnSelect = jest.fn();
|
||||
render(getTestComponent(handleOnSelect));
|
||||
userEvent.tab();
|
||||
expect(screen.queryByRole("button")?.textContent).toEqual(
|
||||
"(none)caret-down",
|
||||
);
|
||||
userEvent.keyboard("{Enter}");
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-(none)",
|
||||
);
|
||||
// used to shift the focus from search
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add-row-top",
|
||||
);
|
||||
userEvent.keyboard(" ");
|
||||
expect(handleOnSelect).toHaveBeenCalledTimes(1);
|
||||
expect(handleOnSelect).toHaveBeenLastCalledWith("iconName", "add-row-top");
|
||||
await waitForElementToBeRemoved(screen.getByRole("list"));
|
||||
|
||||
userEvent.keyboard("{Enter}");
|
||||
expect(screen.queryByRole("list")).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
expect(document.querySelector("a.bp3-active")?.children[0]).toHaveClass(
|
||||
"bp3-icon-add-row-top",
|
||||
);
|
||||
userEvent.keyboard("{ArrowDown}");
|
||||
userEvent.keyboard("{ArrowRight}");
|
||||
userEvent.keyboard(" ");
|
||||
expect(handleOnSelect).toHaveBeenCalledTimes(2);
|
||||
expect(handleOnSelect).toHaveBeenLastCalledWith(
|
||||
"iconName",
|
||||
"add-to-artifact",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,13 +1,19 @@
|
|||
import * as React from "react";
|
||||
import styled, { createGlobalStyle } from "styled-components";
|
||||
import { Alignment, Button, Classes, Menu, MenuItem } from "@blueprintjs/core";
|
||||
import { Alignment, Button, Classes, MenuItem } from "@blueprintjs/core";
|
||||
import { IconName, IconNames } from "@blueprintjs/icons";
|
||||
import { ItemListRenderer, ItemRenderer, Select } from "@blueprintjs/select";
|
||||
import {
|
||||
GridListProps,
|
||||
VirtuosoGrid,
|
||||
VirtuosoGridHandle,
|
||||
} from "react-virtuoso";
|
||||
|
||||
import BaseControl, { ControlProps } from "./BaseControl";
|
||||
import TooltipComponent from "components/ads/Tooltip";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { replayHighlightClass } from "globalStyles/portals";
|
||||
import _ from "lodash";
|
||||
|
||||
const IconSelectContainerStyles = createGlobalStyle<{
|
||||
targetWidth: number | undefined;
|
||||
|
|
@ -37,7 +43,7 @@ const StyledButton = styled(Button)`
|
|||
}
|
||||
`;
|
||||
|
||||
const StyledMenu = styled(Menu)`
|
||||
const StyledMenu = styled.ul<GridListProps>`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-auto-rows: minmax(50px, auto);
|
||||
|
|
@ -54,6 +60,9 @@ const StyledMenu = styled(Menu)`
|
|||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
background-color: #939090;
|
||||
}
|
||||
& li {
|
||||
list-style: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledMenuItem = styled(MenuItem)`
|
||||
|
|
@ -82,7 +91,9 @@ export interface IconSelectControlProps extends ControlProps {
|
|||
}
|
||||
|
||||
export interface IconSelectControlState {
|
||||
activeIcon: IconType;
|
||||
popoverTargetWidth: number | undefined;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
const NONE = "(none)";
|
||||
|
|
@ -99,14 +110,44 @@ class IconSelectControl extends BaseControl<
|
|||
IconSelectControlState
|
||||
> {
|
||||
private iconSelectTargetRef: React.RefObject<HTMLButtonElement>;
|
||||
private virtuosoRef: React.RefObject<VirtuosoGridHandle>;
|
||||
private initialItemIndex: number;
|
||||
private filteredItems: Array<IconType>;
|
||||
private searchInput: React.RefObject<HTMLInputElement>;
|
||||
private timer?: number;
|
||||
|
||||
constructor(props: IconSelectControlProps) {
|
||||
super(props);
|
||||
this.iconSelectTargetRef = React.createRef();
|
||||
this.state = { popoverTargetWidth: 0 };
|
||||
this.virtuosoRef = React.createRef();
|
||||
this.searchInput = React.createRef();
|
||||
this.initialItemIndex = 0;
|
||||
this.filteredItems = [];
|
||||
this.state = {
|
||||
activeIcon: props.propertyValue ?? NONE,
|
||||
popoverTargetWidth: 0,
|
||||
isOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
// debouncedSetState is used to fix the following bug:
|
||||
// https://github.com/appsmithorg/appsmith/pull/10460#issuecomment-1022895174
|
||||
private debouncedSetState = _.debounce(
|
||||
(obj: any, callback?: () => void) => {
|
||||
this.setState((prevState: IconSelectControlState) => {
|
||||
return {
|
||||
...prevState,
|
||||
...obj,
|
||||
};
|
||||
}, callback);
|
||||
},
|
||||
300,
|
||||
{
|
||||
leading: true,
|
||||
trailing: false,
|
||||
},
|
||||
);
|
||||
|
||||
componentDidMount() {
|
||||
this.timer = setTimeout(() => {
|
||||
const iconSelectTargetElement = this.iconSelectTargetRef.current;
|
||||
|
|
@ -118,30 +159,49 @@ class IconSelectControl extends BaseControl<
|
|||
};
|
||||
});
|
||||
}, 0);
|
||||
// keydown event is attached to body so that it will not interfere with the keydown handler in GlobalHotKeys
|
||||
document.body.addEventListener("keydown", this.handleKeydown);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
document.body.removeEventListener("keydown", this.handleKeydown);
|
||||
}
|
||||
|
||||
private handleQueryChange = _.debounce(() => {
|
||||
if (this.filteredItems.length === 2)
|
||||
this.setState({ activeIcon: this.filteredItems[1] });
|
||||
}, 50);
|
||||
|
||||
public render() {
|
||||
const { defaultIconName, propertyValue: iconName } = this.props;
|
||||
const { popoverTargetWidth } = this.state;
|
||||
const { activeIcon, popoverTargetWidth } = this.state;
|
||||
return (
|
||||
<>
|
||||
<IconSelectContainerStyles targetWidth={popoverTargetWidth} />
|
||||
<TypedSelect
|
||||
activeItem={iconName || defaultIconName || NONE}
|
||||
activeItem={activeIcon || defaultIconName || NONE}
|
||||
className="icon-select-container"
|
||||
inputProps={{
|
||||
inputRef: this.searchInput,
|
||||
}}
|
||||
itemListRenderer={this.renderMenu}
|
||||
itemPredicate={this.filterIconName}
|
||||
itemRenderer={this.renderIconItem}
|
||||
items={ICON_NAMES}
|
||||
noResults={<MenuItem disabled text="No results" />}
|
||||
onItemSelect={this.handleIconChange}
|
||||
popoverProps={{ minimal: true }}
|
||||
onQueryChange={this.handleQueryChange}
|
||||
popoverProps={{
|
||||
enforceFocus: false,
|
||||
minimal: true,
|
||||
isOpen: this.state.isOpen,
|
||||
onInteraction: (state) => {
|
||||
if (this.state.isOpen !== state)
|
||||
this.debouncedSetState({ isOpen: state });
|
||||
},
|
||||
}}
|
||||
>
|
||||
<StyledButton
|
||||
alignText={Alignment.LEFT}
|
||||
|
|
@ -151,6 +211,7 @@ class IconSelectControl extends BaseControl<
|
|||
elementRef={this.iconSelectTargetRef}
|
||||
fill
|
||||
icon={iconName || defaultIconName}
|
||||
onClick={this.handleButtonClick}
|
||||
rightIcon="caret-down"
|
||||
text={iconName || defaultIconName || NONE}
|
||||
/>
|
||||
|
|
@ -159,14 +220,142 @@ class IconSelectControl extends BaseControl<
|
|||
);
|
||||
}
|
||||
|
||||
private setActiveIcon(iconIndex: number) {
|
||||
this.setState(
|
||||
{
|
||||
activeIcon: this.filteredItems[iconIndex],
|
||||
},
|
||||
() => {
|
||||
if (this.virtuosoRef.current) {
|
||||
this.virtuosoRef.current.scrollToIndex(iconIndex);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private handleKeydown = (e: KeyboardEvent) => {
|
||||
if (this.state.isOpen) {
|
||||
switch (e.key) {
|
||||
case "Tab":
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
activeIcon: this.props.propertyValue ?? NONE,
|
||||
});
|
||||
break;
|
||||
case "ArrowDown":
|
||||
case "Down": {
|
||||
if (document.activeElement === this.searchInput.current) {
|
||||
(document.activeElement as HTMLElement).blur();
|
||||
if (this.initialItemIndex < 0) this.initialItemIndex = -4;
|
||||
else break;
|
||||
}
|
||||
const nextIndex = this.initialItemIndex + 4;
|
||||
if (nextIndex < this.filteredItems.length)
|
||||
this.setActiveIcon(nextIndex);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
case "ArrowUp":
|
||||
case "Up": {
|
||||
if (document.activeElement === this.searchInput.current) {
|
||||
break;
|
||||
} else if (
|
||||
(e.shiftKey ||
|
||||
(this.initialItemIndex >= 0 && this.initialItemIndex < 4)) &&
|
||||
this.searchInput.current
|
||||
) {
|
||||
this.searchInput.current.focus();
|
||||
break;
|
||||
}
|
||||
const nextIndex = this.initialItemIndex - 4;
|
||||
if (nextIndex >= 0) this.setActiveIcon(nextIndex);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
case "ArrowRight":
|
||||
case "Right": {
|
||||
if (document.activeElement === this.searchInput.current) {
|
||||
break;
|
||||
}
|
||||
const nextIndex = this.initialItemIndex + 1;
|
||||
if (nextIndex < this.filteredItems.length)
|
||||
this.setActiveIcon(nextIndex);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
case "ArrowLeft":
|
||||
case "Left": {
|
||||
if (document.activeElement === this.searchInput.current) {
|
||||
break;
|
||||
}
|
||||
const nextIndex = this.initialItemIndex - 1;
|
||||
if (nextIndex >= 0) this.setActiveIcon(nextIndex);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
case " ":
|
||||
case "Enter": {
|
||||
if (
|
||||
this.searchInput.current === document.activeElement &&
|
||||
this.filteredItems.length !== 2
|
||||
)
|
||||
break;
|
||||
this.handleIconChange(this.filteredItems[this.initialItemIndex]);
|
||||
this.debouncedSetState({ isOpen: false });
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
break;
|
||||
}
|
||||
case "Escape": {
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
activeIcon: this.props.propertyValue ?? NONE,
|
||||
});
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
this.iconSelectTargetRef.current === document.activeElement &&
|
||||
(e.key === "ArrowUp" ||
|
||||
e.key === "Up" ||
|
||||
e.key === "ArrowDown" ||
|
||||
e.key === "Down")
|
||||
) {
|
||||
this.debouncedSetState({ isOpen: true }, this.handleButtonClick);
|
||||
}
|
||||
};
|
||||
|
||||
private handleButtonClick = () => {
|
||||
setTimeout(() => {
|
||||
if (this.virtuosoRef.current) {
|
||||
this.virtuosoRef.current.scrollToIndex(this.initialItemIndex);
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
private renderMenu: ItemListRenderer<IconType> = ({
|
||||
items,
|
||||
itemsParentRef,
|
||||
activeItem,
|
||||
filteredItems,
|
||||
renderItem,
|
||||
}) => {
|
||||
const renderedItems = items.map(renderItem).filter((item) => item != null);
|
||||
this.filteredItems = filteredItems;
|
||||
this.initialItemIndex = filteredItems.findIndex((x) => x === activeItem);
|
||||
|
||||
return <StyledMenu ulRef={itemsParentRef}>{renderedItems}</StyledMenu>;
|
||||
return (
|
||||
<VirtuosoGrid
|
||||
components={{
|
||||
List: StyledMenu,
|
||||
}}
|
||||
computeItemKey={(index) => filteredItems[index]}
|
||||
initialItemCount={16}
|
||||
itemContent={(index) => renderItem(filteredItems[index], index)}
|
||||
ref={this.virtuosoRef}
|
||||
style={{ height: "165px" }}
|
||||
tabIndex={-1}
|
||||
totalCount={filteredItems.length}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
private renderIconItem: ItemRenderer<IconName | typeof NONE> = (
|
||||
|
|
@ -184,6 +373,7 @@ class IconSelectControl extends BaseControl<
|
|||
key={icon}
|
||||
onClick={handleClick}
|
||||
text={icon === NONE ? NONE : undefined}
|
||||
textClassName={icon === NONE ? "bp3-icon-(none)" : ""}
|
||||
/>
|
||||
</TooltipComponent>
|
||||
);
|
||||
|
|
@ -199,11 +389,13 @@ class IconSelectControl extends BaseControl<
|
|||
return iconName.toLowerCase().indexOf(query.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
private handleIconChange = (icon: IconType) =>
|
||||
private handleIconChange = (icon: IconType) => {
|
||||
this.setState({ activeIcon: icon });
|
||||
this.updateProperty(
|
||||
this.props.propertyName,
|
||||
icon === NONE ? undefined : icon,
|
||||
);
|
||||
};
|
||||
|
||||
static getControlType() {
|
||||
return "ICON_SELECT";
|
||||
|
|
|
|||
|
|
@ -774,7 +774,7 @@ function ApplicationsSection(props: any) {
|
|||
</div>
|
||||
<MenuItem
|
||||
cypressSelector="t--org-setting"
|
||||
icon="general"
|
||||
icon="settings-2-line"
|
||||
onSelect={() =>
|
||||
getOnSelectAction(
|
||||
DropdownOnSelectActions.REDIRECT,
|
||||
|
|
@ -783,7 +783,7 @@ function ApplicationsSection(props: any) {
|
|||
},
|
||||
)
|
||||
}
|
||||
text="Organization Settings"
|
||||
text="Settings"
|
||||
/>
|
||||
{enableImportExport && (
|
||||
<MenuItem
|
||||
|
|
@ -816,12 +816,12 @@ function ApplicationsSection(props: any) {
|
|||
/>
|
||||
)}
|
||||
<MenuItem
|
||||
icon="share"
|
||||
icon="share-line"
|
||||
onSelect={() => setSelectedOrgId(organization.id)}
|
||||
text="Share"
|
||||
/>
|
||||
<MenuItem
|
||||
icon="user"
|
||||
icon="member"
|
||||
onSelect={() =>
|
||||
getOnSelectAction(
|
||||
DropdownOnSelectActions.REDIRECT,
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ function DatasourceCard(props: DatasourceCardProps) {
|
|||
<Queries className={`t--queries-for-${plugin.type}`}>
|
||||
{queriesWithThisDatasource
|
||||
? `${queriesWithThisDatasource} ${QUERY} on this page`
|
||||
: "No query is using this datasource"}
|
||||
: "No query in this application is using this datasource"}
|
||||
</Queries>
|
||||
</div>
|
||||
<ButtonsWrapper className="action-wrapper">
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
import React, { useCallback, useState, useMemo } from "react";
|
||||
import { Space } from "./StyledComponents";
|
||||
import {
|
||||
createMessage,
|
||||
USER_PROFILE_SETTINGS_TITLE,
|
||||
AUTHOR_NAME,
|
||||
AUTHOR_EMAIL,
|
||||
FORM_VALIDATION_INVALID_EMAIL,
|
||||
AUTHOR_NAME,
|
||||
AUTHOR_NAME_CANNOT_BE_EMPTY,
|
||||
FORM_VALIDATION_INVALID_EMAIL,
|
||||
USER_PROFILE_SETTINGS_TITLE,
|
||||
USE_DEFAULT_CONFIGURATION,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import styled from "styled-components";
|
||||
import TextInput, { emailValidator } from "components/ads/TextInput";
|
||||
import Checkbox from "components/ads/Checkbox";
|
||||
import { GIT_PROFILE_ROUTE } from "constants/routes";
|
||||
import history from "utils/history";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { ReactComponent as RightArrow } from "assets/icons/ads/arrow-right-line.svg";
|
||||
import { useSelector } from "react-redux";
|
||||
import {
|
||||
getIsFetchingGlobalGitConfig,
|
||||
getIsFetchingLocalGitConfig,
|
||||
} from "selectors/gitSyncSelectors";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { getTypographyByKey } from "constants/DefaultTheme";
|
||||
|
||||
const LabelContainer = styled.div`
|
||||
|
|
@ -48,24 +44,6 @@ const MainContainer = styled.div`
|
|||
width: calc(100% - 30px);
|
||||
`;
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-top: 2px;
|
||||
margin-left: ${(props) => props.theme.spaces[6]}px;
|
||||
cursor: pointer;
|
||||
|
||||
.edit-config-link {
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
color: ${Colors.GRAY};
|
||||
}
|
||||
`;
|
||||
|
||||
const IconWrapper = styled.div`
|
||||
margin-left: 2px;
|
||||
`;
|
||||
|
||||
const DefaultConfigContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
|
@ -126,11 +104,6 @@ type UserGitProfileSettingsProps = {
|
|||
triedSubmit: boolean;
|
||||
};
|
||||
|
||||
const goToGitProfile = () => {
|
||||
AnalyticsUtil.logEvent("GS_DEFAULT_CONFIGURATION_EDIT_BUTTON_CLICK");
|
||||
history.push(GIT_PROFILE_ROUTE);
|
||||
};
|
||||
|
||||
function UserGitProfileSettings({
|
||||
authorInfo,
|
||||
setAuthorInfo,
|
||||
|
|
@ -195,12 +168,6 @@ function UserGitProfileSettings({
|
|||
label={createMessage(USE_DEFAULT_CONFIGURATION)}
|
||||
onCheckChange={toggleUseDefaultConfig}
|
||||
/>
|
||||
<ButtonWrapper onClick={goToGitProfile}>
|
||||
<span className="edit-config-link">EDIT</span>
|
||||
<IconWrapper>
|
||||
<RightArrow width={14} />
|
||||
</IconWrapper>
|
||||
</ButtonWrapper>
|
||||
</DefaultConfigContainer>
|
||||
) : null}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { Icon, IconSize } from "components/ads";
|
|||
|
||||
const AccordionWrapper = styled.div`
|
||||
margin-top: 40px;
|
||||
max-width: 634px;
|
||||
max-width: 40rem;
|
||||
`;
|
||||
|
||||
const AccordionHeader = styled(StyledLabel)`
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import { FormGroup, SettingComponentProps } from "./Common";
|
|||
export default function TextInput({ setting }: SettingComponentProps) {
|
||||
return (
|
||||
<FormGroup
|
||||
className={`t--admin-settings-text-input t--admin-settings-${setting.name}`}
|
||||
className={`t--admin-settings-text-input t--admin-settings-${setting.name ||
|
||||
setting.id}`}
|
||||
setting={setting}
|
||||
>
|
||||
<FormTextField
|
||||
|
|
|
|||
|
|
@ -193,9 +193,9 @@ export function SettingsForm(
|
|||
const validate = (values: Record<string, any>) => {
|
||||
const errors: any = {};
|
||||
_.filter(values, (value, name) => {
|
||||
const message = AdminConfig.validate(name, value);
|
||||
if (message) {
|
||||
errors[name] = message;
|
||||
const err_message = AdminConfig.validate(name, value);
|
||||
if (err_message) {
|
||||
errors[name] = err_message;
|
||||
}
|
||||
});
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const config: AdminConfigType = {
|
|||
settings: [
|
||||
{
|
||||
id: "APPSMITH_MONGODB_URI",
|
||||
category: "advanced",
|
||||
category: SettingCategories.ADVANCED,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "MongoDB URI",
|
||||
|
|
@ -21,7 +21,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_REDIS_URL",
|
||||
category: "advanced",
|
||||
category: SettingCategories.ADVANCED,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Redis URL",
|
||||
|
|
@ -30,7 +30,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_CUSTOM_DOMAIN",
|
||||
category: "advanced",
|
||||
category: SettingCategories.ADVANCED,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Custom Domain",
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ export const config: AdminConfigType = {
|
|||
settings: [
|
||||
{
|
||||
id: "APPSMITH_MAIL_READ_MORE",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.LINK,
|
||||
label: "How to configure?",
|
||||
url: EMAIL_SETUP_DOC,
|
||||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_HOST",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "SMTP Host",
|
||||
|
|
@ -36,7 +36,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_PORT",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.NUMBER,
|
||||
placeholder: "25",
|
||||
|
|
@ -50,7 +50,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_FROM",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "From Address",
|
||||
|
|
@ -65,13 +65,13 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_SMTP_TLS_ENABLED",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TOGGLE,
|
||||
label: "TLS Protected Connection",
|
||||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_USERNAME",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "SMTP Username",
|
||||
|
|
@ -81,7 +81,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_PASSWORD",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.PASSWORD,
|
||||
label: "SMTP Password",
|
||||
|
|
@ -91,7 +91,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_MAIL_TEST_EMAIL",
|
||||
category: "email",
|
||||
category: SettingCategories.EMAIL,
|
||||
action: (dispatch: Dispatch<ReduxAction<any>>, settings: any = {}) => {
|
||||
dispatch &&
|
||||
dispatch({
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export const config: AdminConfigType = {
|
|||
settings: [
|
||||
{
|
||||
id: "APPSMITH_INSTANCE_NAME",
|
||||
category: "general",
|
||||
category: SettingCategories.GENERAL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Instance Name",
|
||||
|
|
@ -24,7 +24,7 @@ export const config: AdminConfigType = {
|
|||
},
|
||||
{
|
||||
id: "APPSMITH_ADMIN_EMAILS",
|
||||
category: "general",
|
||||
category: SettingCategories.GENERAL,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.EMAIL,
|
||||
label: "Admin Email",
|
||||
|
|
@ -51,14 +51,14 @@ export const config: AdminConfigType = {
|
|||
"_blank",
|
||||
);
|
||||
},
|
||||
category: "general",
|
||||
category: SettingCategories.GENERAL,
|
||||
controlType: SettingTypes.BUTTON,
|
||||
label: "Generated Docker Compose File",
|
||||
text: "Download",
|
||||
},
|
||||
{
|
||||
id: "APPSMITH_DISABLE_TELEMETRY",
|
||||
category: "general",
|
||||
category: SettingCategories.GENERAL,
|
||||
controlType: SettingTypes.TOGGLE,
|
||||
label: "Disable Sharing Anonymous Usage Data",
|
||||
subText: "Share anonymous usage data to help improve the product",
|
||||
|
|
@ -66,7 +66,7 @@ export const config: AdminConfigType = {
|
|||
if (value) {
|
||||
return "Don't share any data";
|
||||
} else {
|
||||
return "Share data & make appsmith better!";
|
||||
return "Share Anonymous Telemetry";
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ export const config: AdminConfigType = {
|
|||
settings: [
|
||||
{
|
||||
id: "APPSMITH_GOOGLE_MAPS_READ_MORE",
|
||||
category: "google-maps",
|
||||
category: SettingCategories.GOOGLE_MAPS,
|
||||
controlType: SettingTypes.LINK,
|
||||
label: "How to configure?",
|
||||
url: GOOGLE_MAPS_SETUP_DOC,
|
||||
},
|
||||
{
|
||||
id: "APPSMITH_GOOGLE_MAPS_API_KEY",
|
||||
category: "google-maps",
|
||||
category: SettingCategories.GOOGLE_MAPS,
|
||||
controlType: SettingTypes.TEXTINPUT,
|
||||
controlSubType: SettingSubtype.TEXT,
|
||||
label: "Google Maps API Key",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const config: AdminConfigType = {
|
|||
settings: [
|
||||
{
|
||||
id: "APPSMITH_CURRENT_VERSION",
|
||||
category: "version",
|
||||
category: SettingCategories.VERSION,
|
||||
controlType: SettingTypes.TEXT,
|
||||
label: "Current version",
|
||||
},
|
||||
|
|
@ -27,7 +27,7 @@ export const config: AdminConfigType = {
|
|||
payload: true,
|
||||
});
|
||||
},
|
||||
category: "version",
|
||||
category: SettingCategories.VERSION,
|
||||
controlType: SettingTypes.LINK,
|
||||
label: "Release Notes",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ function* createNewQueryForDatasourceSaga(
|
|||
const createActionPayload = {
|
||||
name: newQueryName,
|
||||
pageId,
|
||||
pluginId: datasource?.pluginId,
|
||||
datasource: {
|
||||
id: datasourceId,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ function* SendTestEmail(action: ReduxAction<SendTestEmailPayload>) {
|
|||
});
|
||||
} catch (e) {
|
||||
Toaster.show({
|
||||
text: createMessage(TEST_EMAIL_FAILURE),
|
||||
text: e?.message || createMessage(TEST_EMAIL_FAILURE),
|
||||
hideProgressBar: true,
|
||||
variant: Variant.danger,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ export const getDifferenceInJSCollection = (
|
|||
organizationId: jsAction.organizationId,
|
||||
actionConfiguration: {
|
||||
body: action.body,
|
||||
isAsync: false,
|
||||
isAsync: action.isAsync,
|
||||
timeoutInMilliseconds: 0,
|
||||
jsArguments: [],
|
||||
},
|
||||
|
|
@ -206,8 +206,8 @@ export const createDummyJSCollectionActions = (
|
|||
organizationId,
|
||||
executeOnLoad: false,
|
||||
actionConfiguration: {
|
||||
body: "() => {\n\t\t//write code here\n\t}",
|
||||
isAsync: false,
|
||||
body: "async () => {\n\t\t//write code here\n\t}",
|
||||
isAsync: true,
|
||||
timeoutInMilliseconds: 0,
|
||||
jsArguments: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import { ReactComponent as ExitFullScreenIcon } from "assets/icons/widget/camera
|
|||
|
||||
const overlayerMixin = css`
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
top: 50%;
|
||||
|
|
@ -81,6 +82,7 @@ const CameraContainer = styled.div<CameraContainerProps>`
|
|||
}
|
||||
|
||||
video {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { createRef, useEffect, useState } from "react";
|
||||
import { Tooltip } from "@blueprintjs/core";
|
||||
import { CellWrapper } from "./TableStyledWrappers";
|
||||
import { CellWrapper, ColumnWrapper } from "./TableStyledWrappers";
|
||||
import { CellLayoutProperties, ColumnTypes } from "./Constants";
|
||||
import { ReactComponent as OpenNewTabIcon } from "assets/icons/control/open-new-tab.svg";
|
||||
import styled from "styled-components";
|
||||
|
|
@ -19,6 +19,7 @@ export const OpenNewTabIconWrapper = styled.div`
|
|||
interface Props {
|
||||
isHidden?: boolean;
|
||||
isCellVisible?: boolean;
|
||||
noPadding?: boolean;
|
||||
children: React.ReactNode;
|
||||
title: string;
|
||||
cellProperties?: CellLayoutProperties;
|
||||
|
|
@ -89,30 +90,34 @@ function AutoToolTipComponent(props: Props) {
|
|||
return <LinkWrapper {...props} />;
|
||||
}
|
||||
return (
|
||||
<CellWrapper
|
||||
cellProperties={props.cellProperties}
|
||||
isCellVisible={props.isCellVisible}
|
||||
isHidden={props.isHidden}
|
||||
isTextType
|
||||
ref={ref}
|
||||
>
|
||||
{useToolTip && props.children ? (
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
content={
|
||||
<TooltipContentWrapper width={(props.tableWidth || 300) - 32}>
|
||||
{props.title}
|
||||
</TooltipContentWrapper>
|
||||
}
|
||||
hoverOpenDelay={1000}
|
||||
position="top"
|
||||
>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
) : (
|
||||
props.children
|
||||
)}
|
||||
</CellWrapper>
|
||||
<ColumnWrapper>
|
||||
<CellWrapper
|
||||
cellProperties={props.cellProperties}
|
||||
isCellVisible={props.isCellVisible}
|
||||
isHidden={props.isHidden}
|
||||
isPadding={!props.noPadding}
|
||||
isTextType
|
||||
ref={ref}
|
||||
>
|
||||
{useToolTip && props.children ? (
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
content={
|
||||
<TooltipContentWrapper width={(props.tableWidth || 300) - 32}>
|
||||
{props.title}
|
||||
</TooltipContentWrapper>
|
||||
}
|
||||
hoverOpenDelay={1000}
|
||||
position="top"
|
||||
>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
) : (
|
||||
props.children
|
||||
)}
|
||||
</CellWrapper>
|
||||
{useToolTip && props.children && "..."}
|
||||
</ColumnWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@ export function Table(props: TableProps) {
|
|||
isSortable={props.isSortable}
|
||||
key={columnIndex}
|
||||
sortTableColumn={props.sortTableColumn}
|
||||
width={props.width}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export const TableWrapper = styled.div<{
|
|||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
height: 32px;
|
||||
&.reorder-line {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
|
|
@ -353,6 +353,7 @@ export const DraggableHeaderWrapper = styled.div<{
|
|||
|
||||
export const CellWrapper = styled.div<{
|
||||
isHidden?: boolean;
|
||||
isPadding?: boolean;
|
||||
cellProperties?: CellLayoutProperties;
|
||||
isHyperLink?: boolean;
|
||||
useLinkToolTip?: boolean;
|
||||
|
|
@ -360,17 +361,16 @@ export const CellWrapper = styled.div<{
|
|||
isTextType?: boolean;
|
||||
}>`
|
||||
display: ${(props) => (props.isCellVisible !== false ? "flex" : "none")};
|
||||
|
||||
align-items: center;
|
||||
align-items: ${(props) => (props.isPadding ? "center" : "flex-start")};
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
width: ${(props) => (props.isPadding ? "100%" : "calc(100% - 10px)")};
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
opacity: ${(props) => (props.isHidden ? "0.6" : "1")};
|
||||
${TableStyles};
|
||||
padding: 0 10px;
|
||||
padding: ${(props) => (props.isPadding ? "0 10px" : " 0px")};
|
||||
line-height: 28px;
|
||||
.image-cell-wrapper {
|
||||
width: 100%;
|
||||
|
|
@ -574,3 +574,8 @@ export const MenuCategoryWrapper = styled.div`
|
|||
export const MenuStyledOptionHeader = styled.div`
|
||||
font-weight: 600;
|
||||
`;
|
||||
|
||||
export const ColumnWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -580,8 +580,9 @@ export function TableHeaderCell(props: {
|
|||
column: any;
|
||||
editMode?: boolean;
|
||||
isSortable?: boolean;
|
||||
width: number;
|
||||
}) {
|
||||
const { column, editMode, isSortable } = props;
|
||||
const { column, editMode, isSortable, width } = props;
|
||||
const handleSortColumn = () => {
|
||||
if (props.isResizingColumn) return;
|
||||
let columnIndex = props.columnIndex;
|
||||
|
|
@ -604,7 +605,13 @@ export function TableHeaderCell(props: {
|
|||
className={!props.isHidden ? `draggable-header` : "hidden-header"}
|
||||
horizontalAlignment={column.columnProperties.horizontalAlignment}
|
||||
>
|
||||
{props.columnName}
|
||||
<AutoToolTipComponent
|
||||
noPadding
|
||||
tableWidth={width}
|
||||
title={props.columnName}
|
||||
>
|
||||
{props.columnName}
|
||||
</AutoToolTipComponent>
|
||||
</DraggableHeaderWrapper>
|
||||
{props.isAscOrder !== undefined ? (
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import static com.appsmith.server.constants.Url.ACTION_COLLECTION_URL;
|
|||
import static com.appsmith.server.constants.Url.ACTION_URL;
|
||||
import static com.appsmith.server.constants.Url.APPLICATION_URL;
|
||||
import static com.appsmith.server.constants.Url.PAGE_URL;
|
||||
import static com.appsmith.server.constants.Url.THEME_URL;
|
||||
import static com.appsmith.server.constants.Url.USER_URL;
|
||||
import static java.time.temporal.ChronoUnit.DAYS;
|
||||
|
||||
|
|
@ -124,6 +125,7 @@ public class SecurityConfig {
|
|||
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, ACTION_COLLECTION_URL + "/view"),
|
||||
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, PAGE_URL + "/**"),
|
||||
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, APPLICATION_URL + "/**"),
|
||||
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, THEME_URL + "/**"),
|
||||
ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, ACTION_URL + "/execute")
|
||||
)
|
||||
.permitAll()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.appsmith.server.controllers.ce;
|
|||
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.ApplicationMode;
|
||||
import com.appsmith.server.dtos.ApplicationPagesDTO;
|
||||
import com.appsmith.server.dtos.CRUDPageResourceDTO;
|
||||
import com.appsmith.server.dtos.CRUDPageResponseDTO;
|
||||
|
|
@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.PutMapping;
|
|||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
@ -147,4 +149,24 @@ public class PageControllerCE {
|
|||
return newPageService.updatePageByDefaultPageIdAndBranch(defaultPageId, resource, branchName)
|
||||
.map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of pages. It takes either Application ID or a Page ID and mode as input.
|
||||
* If Application ID is present, it'll fetch all pages of that application in the provided mode.
|
||||
* if Page ID is present, it'll fetch all pages of the corresponding Application.
|
||||
* If both IDs are present, it'll use the Application ID only and ignore the Page ID
|
||||
* @param applicationId Id of the application
|
||||
* @param pageId id of a page
|
||||
* @param mode In which mode it's in
|
||||
* @param branchName name of the current branch
|
||||
* @return List of ApplicationPagesDTO along with other meta data
|
||||
*/
|
||||
@GetMapping
|
||||
public Mono<ResponseDTO<ApplicationPagesDTO>> getAllPages(@RequestParam(required = false) String applicationId,
|
||||
@RequestParam(required = false) String pageId,
|
||||
@RequestParam(required = true, defaultValue = "EDIT") ApplicationMode mode,
|
||||
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
|
||||
return newPageService.findApplicationPages(applicationId, pageId, branchName, mode)
|
||||
.map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,8 +127,12 @@ public class UserControllerCE extends BaseController<UserService, User, String>
|
|||
public Mono<ResponseDTO<Boolean>> forgotPasswordRequest(@RequestBody ResetUserPasswordDTO userPasswordDTO,
|
||||
@RequestHeader("Origin") String originHeader) {
|
||||
userPasswordDTO.setBaseUrl(originHeader);
|
||||
// We shouldn't leak information on whether this operation was successful or not to the client. This can enable
|
||||
// username scraping, where the response of this API can prove whether an email has an account or not.
|
||||
return service.forgotPasswordTokenGenerate(userPasswordDTO)
|
||||
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
|
||||
.defaultIfEmpty(true)
|
||||
.onErrorReturn(true)
|
||||
.thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null));
|
||||
}
|
||||
|
||||
@GetMapping("/verifyPasswordResetToken")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.appsmith.server.dtos;
|
||||
|
||||
import com.appsmith.server.domains.Application;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
|
@ -11,6 +12,8 @@ public class ApplicationPagesDTO {
|
|||
|
||||
String organizationId;
|
||||
|
||||
Application application;
|
||||
|
||||
List<PageNameIdDTO> pages;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2061,6 +2061,9 @@ public class GitServiceCEImpl implements GitServiceCE {
|
|||
.flatMap(application -> {
|
||||
GitApplicationMetadata gitApplicationMetadata = application.getGitApplicationMetadata();
|
||||
Path repoPath = Paths.get(application.getOrganizationId(), defaultApplicationId, gitApplicationMetadata.getRepoName());
|
||||
if(branchName.equals(gitApplicationMetadata.getDefaultBranchName())) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.GIT_ACTION_FAILED, " delete branch", "Cannot delete default branch"));
|
||||
}
|
||||
return gitExecutor.deleteBranch(repoPath, branchName)
|
||||
.flatMap(isBranchDeleted -> {
|
||||
if(Boolean.FALSE.equals(isBranchDeleted)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.appsmith.server.services.ce;
|
||||
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.domains.ApplicationMode;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.domains.NewPage;
|
||||
import com.appsmith.server.dtos.ApplicationPagesDTO;
|
||||
|
|
@ -38,6 +39,8 @@ public interface NewPageServiceCE extends CrudService<NewPage, String> {
|
|||
Boolean view,
|
||||
boolean markApplicationAsRecentlyAccessed);
|
||||
|
||||
Mono<ApplicationPagesDTO> findApplicationPages(String applicationId, String pageId, String branchName, ApplicationMode mode);
|
||||
|
||||
Mono<ApplicationPagesDTO> findApplicationPagesByApplicationIdViewMode(
|
||||
String applicationId, Boolean view, boolean markApplicationAsRecentlyAccessed
|
||||
);
|
||||
|
|
@ -70,6 +73,8 @@ public interface NewPageServiceCE extends CrudService<NewPage, String> {
|
|||
|
||||
Mono<String> findBranchedPageId(String branchName, String defaultPageId, AclPermission permission);
|
||||
|
||||
Mono<String> findBranchedApplicationIdFromNewPage(String branchName, String defaultPageId);
|
||||
|
||||
Mono<NewPage> findByGitSyncIdAndDefaultApplicationId(String defaultApplicationId, String gitSyncId, AclPermission permission);
|
||||
|
||||
Flux<NewPage> findPageSlugsByApplicationIds(List<String> applicationIds, AclPermission aclPermission);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.appsmith.external.models.DefaultResources;
|
|||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.ApplicationMode;
|
||||
import com.appsmith.server.domains.ApplicationPage;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.domains.NewPage;
|
||||
|
|
@ -46,6 +47,7 @@ import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNewFieldValues
|
|||
import static com.appsmith.server.acl.AclPermission.MANAGE_PAGES;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_PAGES;
|
||||
import static com.appsmith.server.exceptions.AppsmithError.INVALID_PARAMETER;
|
||||
|
||||
|
||||
@Slf4j
|
||||
|
|
@ -333,10 +335,13 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
|
|||
return Mono.zip(applicationMono, pagesListMono)
|
||||
.map(tuple -> {
|
||||
Application application = tuple.getT1();
|
||||
application.setPages(null);
|
||||
application.setPublishedPages(null);
|
||||
List<PageNameIdDTO> nameIdDTOList = tuple.getT2();
|
||||
ApplicationPagesDTO applicationPagesDTO = new ApplicationPagesDTO();
|
||||
applicationPagesDTO.setOrganizationId(application.getOrganizationId());
|
||||
applicationPagesDTO.setPages(nameIdDTOList);
|
||||
applicationPagesDTO.setApplication(application);
|
||||
return applicationPagesDTO;
|
||||
});
|
||||
}
|
||||
|
|
@ -525,6 +530,24 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
|
|||
.map(NewPage::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> findBranchedApplicationIdFromNewPage(String branchName, String defaultPageId) {
|
||||
Mono<NewPage> getPageMono;
|
||||
if (!StringUtils.hasLength(branchName)) {
|
||||
if (!StringUtils.hasLength(defaultPageId)) {
|
||||
return Mono.error(new AppsmithException(INVALID_PARAMETER, FieldName.PAGE_ID, defaultPageId));
|
||||
}
|
||||
getPageMono = repository.findById(defaultPageId, READ_PAGES);
|
||||
} else {
|
||||
getPageMono = repository.findPageByBranchNameAndDefaultPageId(branchName, defaultPageId, READ_PAGES);
|
||||
}
|
||||
return getPageMono
|
||||
.switchIfEmpty(Mono.error(
|
||||
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.PAGE_ID, defaultPageId + ", " + branchName))
|
||||
)
|
||||
.map(NewPage::getApplicationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<NewPage> findByGitSyncIdAndDefaultApplicationId(String defaultApplicationId, String gitSyncId, AclPermission permission) {
|
||||
return repository.findByGitSyncIdAndDefaultApplicationId(defaultApplicationId, gitSyncId, permission);
|
||||
|
|
@ -534,4 +557,29 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
|
|||
public Flux<NewPage> findPageSlugsByApplicationIds(List<String> applicationIds, AclPermission aclPermission) {
|
||||
return repository.findSlugsByApplicationIds(applicationIds, aclPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of pages of an Application.
|
||||
* If Application ID is present, it'll fetch all pages of that application in the provided mode.
|
||||
* if Page ID is present, it'll fetch all pages of the corresponding Application.
|
||||
* If both IDs are present, it'll use the Application ID only and ignore the Page ID
|
||||
* @param applicationId Id of the application
|
||||
* @param pageId id of a page
|
||||
* @param branchName name of the current branch
|
||||
* @param mode In which mode it's in
|
||||
* @return List of ApplicationPagesDTO
|
||||
*/
|
||||
@Override
|
||||
public Mono<ApplicationPagesDTO> findApplicationPages(String applicationId, String pageId, String branchName, ApplicationMode mode) {
|
||||
boolean isViewMode = (mode == ApplicationMode.PUBLISHED);
|
||||
if(StringUtils.hasLength(applicationId)) {
|
||||
return findApplicationPagesByApplicationIdViewModeAndBranch(applicationId, branchName, isViewMode, true);
|
||||
} else if(StringUtils.hasLength(pageId)) {
|
||||
return findBranchedApplicationIdFromNewPage(branchName, pageId)
|
||||
.flatMap(branchedApplicationId -> findApplicationPagesByApplicationIdViewMode(branchedApplicationId, isViewMode, true))
|
||||
.map(responseUtils::updateApplicationPagesDTOWithDefaultResources);
|
||||
} else {
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.APPLICATION_ID + " or " + FieldName.PAGE_ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2523,6 +2523,8 @@ public class GitServiceTest {
|
|||
@WithUserDetails(value ="api_user")
|
||||
public void deleteBranch_staleBranchNotInDB_Success() throws IOException {
|
||||
Application application = createApplicationConnectedToGit("deleteBranch_staleBranchNotInDB_Success", "master");
|
||||
application.getGitApplicationMetadata().setDefaultBranchName("master");
|
||||
applicationService.save(application).block();
|
||||
Mockito.when(gitExecutor.deleteBranch(Mockito.any(Path.class), Mockito.anyString()))
|
||||
.thenReturn(Mono.just(true));
|
||||
|
||||
|
|
@ -2541,6 +2543,8 @@ public class GitServiceTest {
|
|||
@WithUserDetails(value ="api_user")
|
||||
public void deleteBranch_existsInDB_Success() throws IOException {
|
||||
Application application = createApplicationConnectedToGit("deleteBranch_existsInDB_Success", "master");
|
||||
application.getGitApplicationMetadata().setDefaultBranchName("test");
|
||||
applicationService.save(application).block();
|
||||
Mockito.when(gitExecutor.deleteBranch(Mockito.any(Path.class), Mockito.anyString()))
|
||||
.thenReturn(Mono.just(true));
|
||||
|
||||
|
|
@ -2559,6 +2563,8 @@ public class GitServiceTest {
|
|||
@WithUserDetails(value = "api_user")
|
||||
public void deleteBranch_branchDoesNotExist_ThrowError() throws IOException {
|
||||
Application application = createApplicationConnectedToGit("deleteBranch_branchDoesNotExist_ThrowError", "master");
|
||||
application.getGitApplicationMetadata().setDefaultBranchName("test");
|
||||
applicationService.save(application).block();
|
||||
Mockito.when(gitExecutor.deleteBranch(Mockito.any(Path.class), Mockito.anyString()))
|
||||
.thenReturn(Mono.just(false));
|
||||
|
||||
|
|
@ -2570,4 +2576,22 @@ public class GitServiceTest {
|
|||
throwable.getMessage().contains("delete branch. Branch does not exists in the repo"))
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void deleteBranch_defaultBranch_ThrowError() throws IOException {
|
||||
Application application = createApplicationConnectedToGit("deleteBranch_defaultBranch_ThrowError", "master");
|
||||
application.getGitApplicationMetadata().setDefaultBranchName("master");
|
||||
applicationService.save(application).block();
|
||||
Mockito.when(gitExecutor.deleteBranch(Mockito.any(Path.class), Mockito.anyString()))
|
||||
.thenReturn(Mono.just(false));
|
||||
|
||||
Mono<Application> applicationMono = gitService.deleteBranch(application.getId(), "master");
|
||||
|
||||
StepVerifier
|
||||
.create(applicationMono)
|
||||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
|
||||
throwable.getMessage().contains("Cannot delete default branch"))
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.ApplicationMode;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.dtos.ApplicationPagesDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithUserDetails;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@SpringBootTest
|
||||
@RunWith(SpringRunner.class)
|
||||
class NewPageServiceTest {
|
||||
|
||||
@Autowired
|
||||
NewPageService newPageService;
|
||||
|
||||
@Autowired
|
||||
ApplicationPageService applicationPageService;
|
||||
|
||||
@Autowired
|
||||
OrganizationService organizationService;
|
||||
|
||||
@Test
|
||||
@WithUserDetails("api_user")
|
||||
void findApplicationPages_WhenApplicationIdAndPageIdNotPresent_ThrowsException() {
|
||||
StepVerifier.create(
|
||||
newPageService.findApplicationPages(null, null, "master", ApplicationMode.EDIT)
|
||||
)
|
||||
.expectError(AppsmithException.class)
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails("api_user")
|
||||
void findApplicationPages_WhenApplicationIdPresent_ReturnsPages() {
|
||||
String randomId = UUID.randomUUID().toString();
|
||||
Organization organization = new Organization();
|
||||
organization.setName("org_" + randomId);
|
||||
Mono<ApplicationPagesDTO> applicationPagesDTOMono = organizationService.create(organization).flatMap(createdOrg -> {
|
||||
Application application = new Application();
|
||||
application.setName("app_" + randomId);
|
||||
return applicationPageService.createApplication(application, createdOrg.getId());
|
||||
}).flatMap(application -> {
|
||||
PageDTO pageDTO = new PageDTO();
|
||||
pageDTO.setName("page_" + randomId);
|
||||
pageDTO.setApplicationId(application.getId());
|
||||
return applicationPageService.createPage(pageDTO);
|
||||
}).flatMap(pageDTO ->
|
||||
newPageService.findApplicationPages(pageDTO.getApplicationId(), null, null, ApplicationMode.EDIT)
|
||||
);
|
||||
|
||||
StepVerifier.create(applicationPagesDTOMono).assertNext(applicationPagesDTO -> {
|
||||
assertThat(applicationPagesDTO.getApplication()).isNotNull();
|
||||
assertThat(applicationPagesDTO.getApplication().getName()).isEqualTo("app_"+randomId);
|
||||
assertThat(applicationPagesDTO.getPages()).isNotEmpty();
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails("api_user")
|
||||
void findApplicationPages_WhenPageIdPresent_ReturnsPages() {
|
||||
String randomId = UUID.randomUUID().toString();
|
||||
Organization organization = new Organization();
|
||||
organization.setName("org_" + randomId);
|
||||
Mono<ApplicationPagesDTO> applicationPagesDTOMono = organizationService.create(organization).flatMap(createdOrg -> {
|
||||
Application application = new Application();
|
||||
application.setName("app_" + randomId);
|
||||
return applicationPageService.createApplication(application, createdOrg.getId());
|
||||
}).flatMap(application -> {
|
||||
PageDTO pageDTO = new PageDTO();
|
||||
pageDTO.setName("page_" + randomId);
|
||||
pageDTO.setApplicationId(application.getId());
|
||||
return applicationPageService.createPage(pageDTO);
|
||||
}).flatMap(pageDTO ->
|
||||
newPageService.findApplicationPages(null, pageDTO.getId(), null, ApplicationMode.EDIT)
|
||||
);
|
||||
|
||||
StepVerifier.create(applicationPagesDTOMono).assertNext(applicationPagesDTO -> {
|
||||
assertThat(applicationPagesDTO.getApplication()).isNotNull();
|
||||
assertThat(applicationPagesDTO.getApplication().getName()).isEqualTo("app_"+randomId);
|
||||
assertThat(applicationPagesDTO.getPages()).isNotEmpty();
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user