diff --git a/jest.config.js b/jest.config.js
index d472a26..638e343 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -3,4 +3,6 @@ module.exports = {
moduleNameMapper: {
quasar: "quasar/dist/quasar.umd.min.js"
},
+ //"collectCoverage": true,
+ //"collectCoverageFrom": ["**/*.{js,vue}", "!**/node_modules/**"]
}
diff --git a/package-lock.json b/package-lock.json
index 7f7bb4c..487c5e2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2100,9 +2100,9 @@
"dev": true
},
"@vue/test-utils": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.2.tgz",
- "integrity": "sha512-pnRWJbb0cLqjSJIKRpqoSISeYtufEn8D16VmhlCrDWIVt4iAY4Og4JpOPmFytvtQVz96p6n7T6ERI55ue6n0Ew==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.3.tgz",
+ "integrity": "sha512-mmsKXZSGfvd0bH05l4SNuczZ2MqlJH2DWhiul5wJXFxbf/gRRd2UL4QZgozEMQ30mRi9i4/+p4JJat8S4Js64Q==",
"dev": true,
"requires": {
"dom-event-types": "^1.0.0",
@@ -5941,6 +5941,12 @@
"locate-path": "^2.0.0"
}
},
+ "flush-promises": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz",
+ "integrity": "sha512-G0sYfLQERwKz4+4iOZYQEZVpOt9zQrlItIxQAAYAWpfby3gbHrx0osCHz5RLl/XoXevXk0xoN4hDFky/VV9TrA==",
+ "dev": true
+ },
"flush-write-stream": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@@ -13178,9 +13184,9 @@
}
},
"vue-router": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.6.tgz",
- "integrity": "sha512-GYhn2ynaZlysZMkFE5oCHRUTqE8BWs/a9YbKpNLi0i7xD6KG1EzDqpHQmv1F5gXjr8kL5iIVS8EOtRaVUEXTqA=="
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.2.0.tgz",
+ "integrity": "sha512-khkrcUIzMcI1rDcNtqkvLwfRFzB97GmJEsPAQdj7t/VvpGhmXLOkUfhc+Ah8CvpSXGXwuWuQO+x8Sy/xDhXZIA=="
},
"vue-style-loader": {
"version": "4.1.2",
@@ -13217,9 +13223,9 @@
"dev": true
},
"vuex": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.3.0.tgz",
- "integrity": "sha512-1MfcBt+YFd20DPwKe0ThhYm1UEXZya4gVKUvCy7AtS11YAOUR+9a6u4fsv1Rr6ePZCDNxW/M1zuIaswp6nNv8Q=="
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.4.0.tgz",
+ "integrity": "sha512-ajtqwEW/QhnrBZQsZxCLHThZZaa+Db45c92Asf46ZDXu6uHXgbfVuBaJ4gzD2r4UX0oMJHstFwd2r2HM4l8umg=="
},
"w3c-hr-time": {
"version": "1.0.2",
diff --git a/package.json b/package.json
index d3d903b..6be732a 100644
--- a/package.json
+++ b/package.json
@@ -13,8 +13,8 @@
"core-js": "^3.6.5",
"quasar": "^1.11.3",
"vue": "^2.6.11",
- "vue-router": "^3.1.6",
- "vuex": "^3.3.0"
+ "vue-router": "^3.2.0",
+ "vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.3.1",
@@ -22,8 +22,9 @@
"@vue/cli-plugin-unit-jest": "^4.3.1",
"@vue/cli-plugin-vuex": "~4.3.1",
"@vue/cli-service": "~4.3.1",
- "@vue/test-utils": "~1.0.2",
+ "@vue/test-utils": "^1.0.3",
"babel-plugin-transform-imports": "1.5.0",
+ "flush-promises": "^1.0.2",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"vue-cli-plugin-quasar": "^2.0.2",
diff --git a/src/components/automation/AutomationManager.vue b/src/components/automation/AutomationManager.vue
index e2c5027..0760e76 100644
--- a/src/components/automation/AutomationManager.vue
+++ b/src/components/automation/AutomationManager.vue
@@ -21,30 +21,6 @@
icon="add"
@click="showAddPolicyModal"
/>
-
-
+
+
+
+
+
+
+
+ Edit
+
+
+
+
+
+ Delete
+
+
+
+
+
+
+
+
+ Show Relations
+
+
+
+
+
+ Close
+
+
+
{{ props.row.name }}
{{ props.row.desc }}
{{ props.row.active }}
@@ -104,13 +127,19 @@
-
+
-
+
-
+
@@ -133,6 +162,7 @@ export default {
showPolicyOverviewModal: false,
showRelationsViewModal: false,
policy: null,
+ editPolicyId: null,
selected: [],
pagination: {
rowsPerPage: 0,
@@ -189,7 +219,7 @@ export default {
this.$store.commit("automation/setPolicyChecks", {});
this.$store.commit("automation/setPolicyAutomatedTasks", {});
},
- deletePolicy() {
+ deletePolicy(id) {
this.$q
.dialog({
title: "Delete policy?",
@@ -198,7 +228,7 @@ export default {
})
.onOk(() => {
this.$store
- .dispatch("automation/deletePolicy", this.selectedRow)
+ .dispatch("automation/deletePolicy", id)
.then(response => {
this.notifySuccess(`Policy was deleted!`);
})
@@ -215,8 +245,15 @@ export default {
this.policy = null;
this.showRelationsViewModal = false;
},
+ showEditPolicyModal(id) {
+ this.editPolicyId = id;
+ this.showPolicyFormModal = true;
+ },
+ closeEditPolicyModal() {
+ this.showPolicyFormModal = false;
+ this.editPolicyId = null;
+ },
showAddPolicyModal() {
- this.clearRow();
this.showPolicyFormModal = true;
}
},
@@ -227,7 +264,7 @@ export default {
})
},
mounted() {
- this.getPolicies();
+ this.clearRow();
}
};
\ No newline at end of file
diff --git a/src/components/automation/PolicyChecksTab.vue b/src/components/automation/PolicyChecksTab.vue
index 0d0223c..03e627d 100644
--- a/src/components/automation/PolicyChecksTab.vue
+++ b/src/components/automation/PolicyChecksTab.vue
@@ -99,7 +99,22 @@
Delete
+
+
+
+
+
+
+ Status
+
+
+
+
Close
@@ -120,13 +135,6 @@
v-model="props.row.email_alert"
/>
-
-
-
-
-
-
-
Disk Space Drive {{ props.row.disk }} > {{props.row.threshold }}%
@@ -145,27 +153,18 @@
Service Check - {{ props.row.svc_display_name }}
- Awaiting First Synchronization
-
- Passing
+
+
-
- Failing
-
-
- output
-
-
- output
-
- {{ props.row.more_info }}
- {{ props.row.last_run }}
@@ -202,7 +201,6 @@
:policypk="checks.id"
/>
-
@@ -213,7 +211,6 @@
:policypk="checks.id"
/>
-
@@ -235,6 +232,12 @@
:policypk="checks.id"
/>
+
+
+
@@ -254,6 +257,7 @@ import AddWinSvcCheck from "@/components/modals/checks/AddWinSvcCheck";
import EditWinSvcCheck from "@/components/modals/checks/EditWinSvcCheck";
import AddScriptCheck from "@/components/modals/checks/AddScriptCheck";
import EditScriptCheck from "@/components/modals/checks/EditScriptCheck";
+import PolicyCheckStatus from "@/components/automation/modals/PolicyCheckStatus";
export default {
name: "PolicyChecksTab",
@@ -270,7 +274,8 @@ export default {
AddWinSvcCheck,
EditWinSvcCheck,
AddScriptCheck,
- EditScriptCheck
+ EditScriptCheck,
+ PolicyCheckStatus
},
mixins: [mixins],
data() {
@@ -287,26 +292,14 @@ export default {
showEditWinSvcCheck: false,
showAddScriptCheck: false,
showEditScriptCheck: false,
+ showPolicyCheckStatus: false,
editCheckPK: null,
- scriptInfo: {},
+ statusCheck: {},
columns: [
{ name: "smsalert", field: "text_alert", align: "left" },
{ name: "emailalert", field: "email_alert", align: "left" },
- { name: "statusicon", align: "left" },
{ name: "desc", label: "Description", align: "left" },
- { name: "status", label: "Status", field: "status", align: "left" },
- {
- name: "moreinfo",
- label: "More Info",
- field: "more_info",
- align: "left"
- },
- {
- name: "datetime",
- label: "Date / Time",
- field: "last_run",
- align: "left"
- }
+ { name: "status", label: "Status", field: "status", align: "left" }
],
pagination: {
rowsPerPage: 9999
@@ -334,19 +327,6 @@ export default {
onRefresh(id) {
this.$store.dispatch("automation/loadPolicyChecks", id);
},
- moreInfo(name, output) {
- this.$q.dialog({
- title: `${name} output`,
- style: "width: 35vw; max-width: 50vw",
- message: `${output}`,
- html: true,
- dark: true
- });
- },
- scriptMoreInfo(props) {
- this.scriptInfo = props;
- this.showScriptOutput = true;
- },
editCheck(category) {
switch (category) {
case "diskspace":
@@ -389,6 +369,14 @@ export default {
})
.catch(e => this.notifyError(e.response.data.error));
});
+ },
+ showPolicyCheckStatusModal(check) {
+ this.statusCheck = check;
+ this.showPolicyCheckStatus = true;
+ },
+ closePolicyCheckStatusModal() {
+ this.showPolicyCheckStatus = false;
+ this.statusCheck = {};
}
},
computed: {
diff --git a/src/components/automation/modals/PolicyCheckStatus.vue b/src/components/automation/modals/PolicyCheckStatus.vue
new file mode 100644
index 0000000..406f026
--- /dev/null
+++ b/src/components/automation/modals/PolicyCheckStatus.vue
@@ -0,0 +1,33 @@
+
+
+
+ Policy Name Status
+ {{ this.check.desc }}
+
+
+
+
+
+
+ Single line item
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/automation/modals/PolicyForm.vue b/src/components/automation/modals/PolicyForm.vue
index 79fa9c9..7578185 100644
--- a/src/components/automation/modals/PolicyForm.vue
+++ b/src/components/automation/modals/PolicyForm.vue
@@ -205,7 +205,7 @@ export default {
}
},
mounted() {
- //If pk prop is set that means we are editting
+ // If pk prop is set that means we are editting
if (this.pk) {
this.getPolicy();
}
diff --git a/src/components/automation/modals/RelationsView.vue b/src/components/automation/modals/RelationsView.vue
index d3f069a..7e91c39 100644
--- a/src/components/automation/modals/RelationsView.vue
+++ b/src/components/automation/modals/RelationsView.vue
@@ -17,9 +17,9 @@
narrow-indicator
no-caps
>
-
-
-
+
+
+
@@ -27,7 +27,7 @@
Clients
-
+
{{ item.client }}
@@ -38,7 +38,7 @@
Sites
-
+
{{ item.site }}
@@ -54,7 +54,7 @@
{{ item.hostname }}
- {{ item.client }} {{ item.site }}
+ {{ item.client }} {{ item.site }}
@@ -80,7 +80,6 @@ export default {
}
},
mounted() {
-
this.$q.loading.show();
this.$store
diff --git a/tests/unit/automation/automationmanager.spec.js b/tests/unit/automation/automationmanager.spec.js
index 0d72ff2..8628954 100644
--- a/tests/unit/automation/automationmanager.spec.js
+++ b/tests/unit/automation/automationmanager.spec.js
@@ -75,7 +75,8 @@ describe("AutomationManager.vue", () => {
localVue,
stubs: [
"PolicySubTableTabs",
- "PolicyForm"
+ "PolicyForm",
+ "RelationsView"
],
});
@@ -86,7 +87,9 @@ describe("AutomationManager.vue", () => {
// This is needed to remove q-dialogs since body doesn't rerender
afterEach(() => {
const dialogs = document.querySelectorAll(".q-dialog");
+ const menus = document.querySelectorAll(".q-menu");
dialogs.forEach(x => x.remove());
+ menus.forEach(x => x.remove());
});
@@ -116,17 +119,17 @@ describe("AutomationManager.vue", () => {
});
- it("shows edit policy modal on edit button press", async () => {
-
- const button = wrapper.findComponent({ ref: "edit" });
+ it("shows edit policy modal on edit context menu button press", async () => {
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
- await button.trigger("click")
- expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
- //Select Row
- await wrapper.find("tbody > tr.q-tr").trigger("click");
- await button.trigger("click");
+ // Right Click on Row
+ await wrapper.find("tbody > tr.q-tr").trigger("contextmenu");
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
+ await bodyWrapper.find("#context-edit").trigger("click");
+
+ expect(wrapper.vm.editPolicyId).toBe(1);
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
});
@@ -137,19 +140,21 @@ describe("AutomationManager.vue", () => {
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
await button.trigger("click");
+
+ expect(wrapper.vm.editPolicyId).toBe(null);
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
});
it("deletes selected policy", async () => {
- const button = wrapper.findComponent({ ref: "delete" });
-
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
- // Select Row
- await wrapper.find("tbody > tr.q-tr").trigger("click");
- await button.trigger("click");
- expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
+
+ // Right Click on Row
+ await wrapper.find("tbody > tr.q-tr").trigger("contextmenu");
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
+ await bodyWrapper.find("#context-delete").trigger("click");
//Get OK button and click it
bodyWrapper.findAll(".q-btn").wrappers[1].trigger("click");
@@ -179,4 +184,19 @@ describe("AutomationManager.vue", () => {
});
+ it("shows relation modal on context menu button press", async () => {
+
+ expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
+
+ // Right Click on Row
+ await wrapper.find("tbody > tr.q-tr").trigger("contextmenu");
+ expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
+ await bodyWrapper.find("#context-relation").trigger("click");
+
+ expect(wrapper.vm.policy).toBe(policiesData[0]);
+ expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
+
+ });
+
});
diff --git a/tests/unit/automation/automationmodals.spec.js b/tests/unit/automation/formmodal.spec.js
similarity index 80%
rename from tests/unit/automation/automationmodals.spec.js
rename to tests/unit/automation/formmodal.spec.js
index b8cfa90..7c79025 100644
--- a/tests/unit/automation/automationmodals.spec.js
+++ b/tests/unit/automation/formmodal.spec.js
@@ -1,4 +1,5 @@
-import { mount, createLocalVue } from "@vue/test-utils";
+import { mount, createLocalVue, createWrapper } from "@vue/test-utils";
+import flushPromises from "flush-promises";
import Vuex from "vuex";
import PolicyForm from "@/components/automation/modals/PolicyForm";
import "@/quasar.js"
@@ -8,17 +9,40 @@ localVue.use(Vuex);
describe("PolicyForm.vue", () => {
- const clients = [];
- const sites = [];
- const agents = [];
+ const clients = [
+ {
+ id: 1,
+ client: "Test Client"
+ },
+ {
+ id: 2,
+ client: "Test Client2"
+ },
+ {
+ id: 3,
+ client: "Test Client3"
+ }
+ ];
+ const sites = [
+ {
+ id: 1,
+ site: "Site Name",
+ client_name: "Test Client"
+ },
+ {
+ id: 2,
+ site: "Site Name2",
+ client_name: "Test Client2"
+ }
+ ];
const policy = {
id: 1,
name: "Test Policy",
active: true,
- clients: [{id: 1, client: "Test Name"}],
- sites: [{id: 1, site: "Test Name"}],
- agents: [{pk: 1, hostname: "Test Name"}]
+ clients: [],
+ sites: [],
+ agents: []
};
let methods;
@@ -34,7 +58,6 @@ describe("PolicyForm.vue", () => {
rootActions = {
loadClients: jest.fn(() => new Promise(res => res({ data: clients }))),
loadSites: jest.fn(() => new Promise(res => res({ data: sites }))),
- loadAgents: jest.fn(() => new Promise(res => res({ data: agents }))),
};
actions = {
@@ -65,7 +88,6 @@ describe("PolicyForm.vue", () => {
expect(rootActions.loadClients).toHaveBeenCalled();
expect(rootActions.loadSites).toHaveBeenCalled();
- expect(rootActions.loadAgents).toHaveBeenCalled();
// Not called unless pk prop is set
expect(actions.loadPolicy).not.toHaveBeenCalled();
@@ -74,7 +96,7 @@ describe("PolicyForm.vue", () => {
it("calls vuex actions on mount with pk prop set", () => {
- const wrapper = mount(PolicyForm, {
+ mount(PolicyForm, {
localVue,
store,
propsData: {
@@ -84,14 +106,24 @@ describe("PolicyForm.vue", () => {
expect(rootActions.loadClients).toHaveBeenCalled();
expect(rootActions.loadSites).toHaveBeenCalled();
- expect(rootActions.loadAgents).toHaveBeenCalled();
expect(actions.loadPolicy).toHaveBeenCalled();
});
- /*it("renders the client, site, and agent dropdowns correctly", async () => {
+ it("Sets client and site options correctly", async () => {
- })*/
+ const wrapper = mount(PolicyForm, {
+ localVue,
+ store
+ });
+
+ // Make sure the promises are resolved
+ await flushPromises();
+
+ expect(wrapper.vm.clientOptions).toHaveLength(3);
+ expect(wrapper.vm.siteOptions).toHaveLength(2);
+
+ });
it("sends the correct add action on submit", async () => {
diff --git a/tests/unit/automation/relationview.spec.js b/tests/unit/automation/relationview.spec.js
new file mode 100644
index 0000000..d36b219
--- /dev/null
+++ b/tests/unit/automation/relationview.spec.js
@@ -0,0 +1,121 @@
+import { mount, createLocalVue } from "@vue/test-utils";
+import Vuex from "vuex";
+import RelationsView from "@/components/automation/modals/RelationsView";
+import "@/quasar.js"
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe("Relations.vue", () => {
+
+ const policy = {
+ id: 1,
+ name: "Test Policy",
+ active: true,
+ clients: [{id: 1, client: "Test Name"}],
+ sites: [{id: 1, site: "Test Name"}],
+ agents: []
+ };
+
+ const related = {
+ agents: [
+ {
+ pk: 1,
+ hostname: "Test Name",
+ site: "Test Site",
+ client: "Test Client"},
+ {
+ pk: 2,
+ site: "Test Site",
+ hostname: "Test Name2",
+ site: "Test Site",
+ client: "Test Client"
+ }
+ ],
+ sites: [
+ {
+ id: 1,
+ client_name: "Test Name",
+ site: "Test Name"
+ }
+ ],
+ clients: [
+ {
+ id: 1,
+ client: "Test Name"
+ },
+ {
+ id: 2,
+ client: "Test Name2"
+ },
+ {
+ id: 3,
+ client: "Test Name3"
+ }
+ ]
+ };
+
+ let wrapper, actions, store;
+
+ // Runs before every test
+ beforeEach(() => {
+
+ actions = {
+ getRelated: jest.fn(() => new Promise(res => res({ data: related }))),
+ };
+
+ store = new Vuex.Store({
+ modules: {
+ automation: {
+ namespaced: true,
+ actions,
+ }
+ }
+ });
+
+ wrapper = mount(RelationsView, {
+ localVue,
+ store,
+ propsData: {
+ policy: policy
+ }
+ });
+
+ });
+
+ // The Tests
+ it("calls vuex actions on mount", () => {
+
+ expect(actions.getRelated).toHaveBeenCalledWith(expect.anything(), policy.id);
+
+ });
+
+ it("Checks the correct number of list items are rendered in clients tab", async () => {
+
+ await wrapper.findComponent({ref: "clients"}).trigger("click");
+
+ const list = wrapper.findAll(".q-item");
+ expect(list.length).toBeGreaterThanOrEqual(related.clients.length);
+
+ });
+
+ it("Checks the correct number of list items are rendered in sites tab", async () => {
+
+ await wrapper.findComponent({ref: "sites"}).trigger("click");
+
+ const list = wrapper.findAll(".q-item");
+ expect(list.length).toBeGreaterThanOrEqual(related.sites.length);
+
+ });
+
+ it("Checks the correct number of list items are rendered in agents tab", async () => {
+
+ await wrapper.findComponent({ref: "agents"}).trigger("click");
+
+ const list = wrapper.findAll(".q-item");
+ expect(list.length).toBeGreaterThanOrEqual(related.agents.length);
+
+ });
+
+});
+