diff --git a/.gitignore b/.gitignore index 1b51701..5d64c57 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ coverage/ node_modules/ npm-debug.log +debug.log \ No newline at end of file diff --git a/model/processModel.js b/model/processModel.js index afbed0c..5bfe3e3 100644 --- a/model/processModel.js +++ b/model/processModel.js @@ -1,6 +1,7 @@ -import { ProcessV1 } from "../pages/processV1"; +import { ProcessV1 } from "#pages/processV1" +import { ProcessAPI } from "#pages/processAPI" const processPage = new ProcessV1() - +const processAPI = new ProcessAPI() export class ProcessModel { /** * Publishes a process with optional version data @@ -52,4 +53,14 @@ export class ProcessModel { processPage.pressDiscardButtonModal() } + openCreatedRequest(processData){ + processData.then(processData => { + processPage.openRequestByID(processData.id) + }) + } + + createRequestAPI(processId, nodeId, data = {}){ + return processAPI.returnDataStartProcessAPI(processId, nodeId, data) + } + } \ No newline at end of file diff --git a/model/savedSearchModel.js b/model/savedSearchModel.js new file mode 100644 index 0000000..2a780b0 --- /dev/null +++ b/model/savedSearchModel.js @@ -0,0 +1,48 @@ +import savedSearchAPI from "@pages/savedSearchAPI"; +import savedSearchAction from "@pages/savedSearchV1"; + +class savedSearchModel { + + createSavedSearchAPI(data) { + return savedSearchAPI.createSavedSearchAPI(data) + } + + deleteSavedSearchByIdAPI(id) { + return savedSearchAPI.deleteSavedSearchByIdAPI(id) + } + + openSavedSearchByObject(objSS, type) { + savedSearchAction.openSavedSearchByObject(objSS, type) + } + + openSavedSearchById(id, type){ + savedSearchAction.gotoSavedSearchByID(type, id) + } + + searchSavedSearch(criteria) { + savedSearchAction.searchSavedSearch(criteria) + } + + pressNotificationButton(){ + savedSearchAction.pressNotificationButton() + } + + pressConfigurationButton(){ + savedSearchAction.pressConfigurationButton() + } + + pressColumnTabSavedSearchById(){ + savedSearchAction.pressColumnsButton() + } + + pressTab(name){ + savedSearchAction.pressTab(name); + } + + createChartAPI(savedSearchID, payload){ + savedSearchAPI.createChartAPI(savedSearchID, payload) + } + +} + +export default new savedSearchModel(); diff --git a/package.json b/package.json index a706137..a7e3891 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "#pages/*": "./pages/*", "#selectors/*": "./selectors/*", "#support/*": "./support/*", - "#model/*": "./model/*" + "#model/*": "./model/*", + "#verify/*": "./verify/*" }, "devDependencies": { "@4tw/cypress-drag-drop": "^2.2.5", diff --git a/pages/processAPI.js b/pages/processAPI.js index 9026c54..8ccf7fb 100644 --- a/pages/processAPI.js +++ b/pages/processAPI.js @@ -165,4 +165,26 @@ export class ProcessAPI { }); }); } + + + /** + * Starts a process instance using the ProcessMaker API + * @param {string|number} processId - The ID of the process to start + * @param {string} nodeId - The node ID where the process should start + * @param {Object} data - Optional data to pass to the process instance + * @returns {Promise} - A promise that resolves to the process data + */ + returnDataStartProcessAPI(processId, nodeId, data = {}) { + return cy.window().then(win => { + return win.ProcessMaker.apiClient.post( + 'process_events/' + processId, + data, + { + params: { event: nodeId } + } + ).then(response => { + return response.data; + }); + }) + } } diff --git a/pages/processV1.js b/pages/processV1.js index e95fc9c..2bc8f73 100644 --- a/pages/processV1.js +++ b/pages/processV1.js @@ -96,4 +96,8 @@ export class ProcessV1 { cy.get(selectors.discardButton).contains(optionButton).click() }) } + + openRequestByID(id){ + cy.visit(`/requests/${id}`) + } } diff --git a/pages/savedSearchAPI.js b/pages/savedSearchAPI.js new file mode 100644 index 0000000..afae3b9 --- /dev/null +++ b/pages/savedSearchAPI.js @@ -0,0 +1,37 @@ +class SavedSearchAPI { + + createSavedSearchAPI(data) { + return cy.window().then(win => { + return win.ProcessMaker.apiClient.post( + '/saved-searches', + data + ).then(response => { + console.log(">>>"+response.data) + return response.data + }); + }); + } + + deleteSavedSearchByIdAPI(savedSearchID) { + return cy.window().then(win => { + return win.ProcessMaker.apiClient.delete( + '/saved-searches/'+savedSearchID + ).then(response => { + console.log(`saved search by ID ${savedSearchID} was deleted > `+response) + }); + }); + } + + createChartAPI(savedSearchID, payload){ + return cy.window().then(win => { + return win.ProcessMaker.apiClient.post( + `/saved-searches/${savedSearchID}/charts`, + payload + ).then(response => { + return response.data + }); + }); + } +} + +export default new SavedSearchAPI(); \ No newline at end of file diff --git a/pages/savedSearchV1.js b/pages/savedSearchV1.js new file mode 100644 index 0000000..a3f0a7f --- /dev/null +++ b/pages/savedSearchV1.js @@ -0,0 +1,116 @@ +import selector from "#selectors/savedSearchV1"; + +class savedSearchAction { + + gotoSavedSearchByID(type="requets", id) { + let url + if(type = "requests") + url = `/requests/saved-searches/${id}` + else + url = `/tasks/saved-searches/${id}` + cy.visit(url) + } + + openSavedSearchByObject(objSS, type) { + objSS.then((objSS) => { + this.gotoSavedSearchByID(type, objSS.id) + }) + } + + getSaveSearchTab() { + return cy.get(selector.tabList) + } + + getColumnTabSaveSearch(){ + return cy.get(selector.columnTab) + } + + getSearchSavedSeachField() { + return cy.get(selector.searchField) + } + + getPressSendReportButton() { + return cy.get(selector.sendReportBtn) + } + + getPressScheduleReportsButton() { + return cy.get(selector.scheduleReportBtn) + } + + getNotificationButton() { + return cy.get(selector.notificationBtn) + } + + getConfigurationButton() { + return cy.get(selector.configurationBtn) + } + //accepts "Data" or "Charts" + pressTab(tabName) { + const index = (tabName == "Data") ? 0 : 1; + this.getSaveSearchTab().eq(index).click() + } + + searchSavedSearch(criteria) { + this.getSearchSavedSeachField().clear().type(criteria) + this.getSearchSavedSeachField().type('{enter}') + } + pressSendReportButton() { + this.getPressSendReportButton().click() + } + pressScheduleReportsButton() { + this.getPressScheduleReportsButton().click() + } + pressNotificationButton() { + this.getNotificationButton().click() + } + pressConfigurationButton() { + this.getConfigurationButton().click() + } + + pressColumnsButton(){ + this.getColumnTabSaveSearch().click() + } + + addNameChartConfig(nameChart){ + cy.get("div[class='saved-search-chart-config'] input[name='title']").type(nameChart) + } + selectChartTypeConfig(type){ + let chartType + switch(type){ + case "vertical": + chartType = cy.get("div[class='saved-search-chart-config'] canvas[id='bar-chart']") + break + case "Line": + chartType = cy.get("div[class='saved-search-chart-config'] canvas[id='line-chart']") + break + case "Pie": + chartType = cy.get("div[class='saved-search-chart-config'] canvas[id='pie-chart']") + break + case "Doughnut": + chartType = cy.get("div[class='saved-search-chart-config'] canvas[id='doughnut-chart']") + break + case "Count": + chartType = cy.get("div[class='saved-search-chart-config'] div.count-chart-preview") + break + case "List": + chartType = cy.get("div[class='saved-search-chart-config'] div.list-chart-preview") + break + default: + //"bar (horizontal)" + chartType = cy.get("div[class='saved-search-chart-config'] canvas[id='horizontalbar-chart']") + break + } + chartType.click() + } + selectGeneralTabChartConfig(){ + cy.get("div[class='saved-search-chart-config'] a[id='general-tab']").click() + } + selectSourceTabChartConfig(){ + cy.get("div[class='saved-search-chart-config'] a[id='data-tab']").click() + } + selectDisplayTabChartConfig(){ + cy.get("div[class='saved-search-chart-config'] a[id='display-tab']").click() + } +} + +export default new savedSearchAction(); \ No newline at end of file diff --git a/selectors/savedSearchV1.js b/selectors/savedSearchV1.js new file mode 100644 index 0000000..b7da1f0 --- /dev/null +++ b/selectors/savedSearchV1.js @@ -0,0 +1,9 @@ +export default { + tabList: '[role="tablist"] li a', + searchField: 'textarea[placeholder="Search here"]', + sendReportBtn: 'button[title="Send Report"]', + scheduleReportBtn: 'a[title="Scheduled Reports"]', + notificationBtn: 'button[title="Enable Notifications"]', + configurationBtn: 'a[title="Configure Saved Search"]', + columnTab: "[id='nav-columns-tab']", +} \ No newline at end of file diff --git a/verify/qaShould.js b/verify/qaShould.js new file mode 100644 index 0000000..403ecbc --- /dev/null +++ b/verify/qaShould.js @@ -0,0 +1,38 @@ +class qaShould { + + returnElement(type, element){ + switch (type) { + case "css": + return cy.get(element) + case "xpath": + return cy.xpath(element) + default: + cy.log(`Error: The type ${type} or ${element} is not defined`); + } + } + elementIsVisible(type, element) { + this.returnElement(type, element).should("be.visible") + } + + elementHaveText(type, element, value) { + this.returnElement(type, element).invoke('text').should("have.text", value); + } + + elementToEqual(type, element, value) { + this.returnElement(type, element).should($el=>{ + expect($el.text().trim()).to.equal(value); + }) + } + + elementToContain(type, element, value) { + this.returnElement(type, element).should($el=>{ + expect($el.text().trim()).to.contain(value) + }) + } + + elementContainText(type, element, subString){ + this.returnElement(type, element).should("contain.text", subString) + } +} + +export default new qaShould();