mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-03-05 13:24:04 +00:00
reworked policy add for client, site, and agent. removed vue unit tests, added alertign to auto tasks, added edit autotask capabilities for certain fields, moved policy generation logic to save method on Client, Site, Agent, Policy models
This commit is contained in:
@@ -665,12 +665,16 @@ export default {
|
||||
}
|
||||
},
|
||||
showPolicyAdd(agent) {
|
||||
this.$q.dialog({
|
||||
component: PolicyAdd,
|
||||
parent: this,
|
||||
type: "agent",
|
||||
object: agent,
|
||||
});
|
||||
this.$q
|
||||
.dialog({
|
||||
component: PolicyAdd,
|
||||
parent: this,
|
||||
type: "agent",
|
||||
object: agent,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.$emit("refreshEdit");
|
||||
});
|
||||
},
|
||||
toggleMaintenance(agent) {
|
||||
let data = {
|
||||
|
||||
@@ -33,6 +33,21 @@
|
||||
<small>Enabled</small>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-smsalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="phone_android" size="1.5em">
|
||||
<q-tooltip>SMS Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
<template v-slot:header-cell-emailalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="email" size="1.5em">
|
||||
<q-tooltip>Email Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
<template v-slot:header-cell-policystatus="props">
|
||||
<q-th auto-width :props="props"></q-th>
|
||||
</template>
|
||||
@@ -48,13 +63,7 @@
|
||||
</q-item-section>
|
||||
<q-item-section>Run task now</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="showEditAutomatedTask = true"
|
||||
v-if="!props.row.managed_by_policy"
|
||||
v-show="false"
|
||||
>
|
||||
<q-item clickable v-close-popup @click="showEditTask(props.row)" v-if="!props.row.managed_by_policy">
|
||||
<q-item-section side>
|
||||
<q-icon name="edit" />
|
||||
</q-item-section>
|
||||
@@ -86,6 +95,24 @@
|
||||
:disable="props.row.managed_by_policy"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- text alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="taskAlert(props.row.id, 'Text', props.row.text_alert, props.row.managed_by_policy)"
|
||||
v-model="props.row.text_alert"
|
||||
:disable="props.row.managed_by_policy"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- email alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="taskAlert(props.row.id, 'Email', props.row.email_alert, props.row.managed_by_policy)"
|
||||
v-model="props.row.email_alert"
|
||||
:disable="props.row.managed_by_policy"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- policy check icon -->
|
||||
<q-td v-if="props.row.managed_by_policy">
|
||||
<q-icon style="font-size: 1.3rem" name="policy">
|
||||
@@ -139,6 +166,7 @@ import { mapState } from "vuex";
|
||||
import { mapGetters } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import AddAutomatedTask from "@/components/modals/tasks/AddAutomatedTask";
|
||||
import EditAutomatedTask from "@/components/modals/tasks/EditAutomatedTask";
|
||||
import ScriptOutput from "@/components/modals/checks/ScriptOutput";
|
||||
|
||||
export default {
|
||||
@@ -155,6 +183,8 @@ export default {
|
||||
scriptInfo: {},
|
||||
columns: [
|
||||
{ name: "enabled", align: "left", field: "enabled" },
|
||||
{ name: "smsalert", field: "text_alert", align: "left" },
|
||||
{ name: "emailalert", field: "email_alert", align: "left" },
|
||||
{ name: "policystatus", align: "left" },
|
||||
{ name: "name", label: "Name", field: "name", align: "left" },
|
||||
{ name: "sync_status", label: "Sync Status", field: "sync_status", align: "left" },
|
||||
@@ -202,6 +232,34 @@ export default {
|
||||
})
|
||||
.catch(e => this.notifyError("Something went wrong"));
|
||||
},
|
||||
taskAlert(pk, alert_type, action, managed_by_policy) {
|
||||
if (managed_by_policy) {
|
||||
return;
|
||||
}
|
||||
this.$q.loading.show();
|
||||
|
||||
const data = {
|
||||
id: pk,
|
||||
};
|
||||
|
||||
if (alert_type === "Email") {
|
||||
data.email_alert = action;
|
||||
} else {
|
||||
data.text_alert = action;
|
||||
}
|
||||
|
||||
const act = action ? "enabled" : "disabled";
|
||||
axios
|
||||
.put(`/tasks/${pk}/automatedtasks/`, data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.notifySuccess(`${alert_type} alerts ${act}`);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an issue editing task");
|
||||
});
|
||||
},
|
||||
refreshTasks(id) {
|
||||
this.$store.dispatch("loadAutomatedTasks", id);
|
||||
},
|
||||
@@ -209,6 +267,17 @@ export default {
|
||||
this.scriptInfo = props;
|
||||
this.showScriptOutput = true;
|
||||
},
|
||||
showEditTask(task) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: EditAutomatedTask,
|
||||
parent: this,
|
||||
task: task,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.refreshTasks(this.automatedTasks.pk);
|
||||
});
|
||||
},
|
||||
runTask(pk, enabled) {
|
||||
if (!enabled) {
|
||||
this.notifyError("Task cannot be run when it's disabled. Enable it first.");
|
||||
|
||||
@@ -39,6 +39,22 @@
|
||||
<small>Enabled</small>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-smsalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="phone_android" size="1.5em">
|
||||
<q-tooltip>SMS Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-emailalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="email" size="1.5em">
|
||||
<q-tooltip>Email Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
<!-- body slots -->
|
||||
<template v-slot:body="props" :props="props">
|
||||
<q-tr @contextmenu="editTaskPk = props.row.id">
|
||||
@@ -51,6 +67,12 @@
|
||||
</q-item-section>
|
||||
<q-item-section>Run task now</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showEditTask(props.row)" v-if="!props.row.managed_by_policy">
|
||||
<q-item-section side>
|
||||
<q-icon name="edit" />
|
||||
</q-item-section>
|
||||
<q-item-section>Edit</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="deleteTask(props.row.name, props.row.id)">
|
||||
<q-item-section side>
|
||||
<q-icon name="delete" />
|
||||
@@ -78,6 +100,22 @@
|
||||
v-model="props.row.enabled"
|
||||
/>
|
||||
</q-td>
|
||||
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="taskAlert(props.row.id, 'Text', props.row.text_alert, props.row.managed_by_policy)"
|
||||
v-model="props.row.text_alert"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- email alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="taskAlert(props.row.id, 'Email', props.row.email_alert, props.row.managed_by_policy)"
|
||||
v-model="props.row.email_alert"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<q-td>{{ props.row.schedule }}</q-td>
|
||||
<q-td>
|
||||
@@ -110,8 +148,8 @@
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
import DialogWrapper from "@/components/ui/DialogWrapper";
|
||||
import AddAutomatedTask from "@/components/modals/tasks/AddAutomatedTask";
|
||||
import EditAutomatedTask from "@/components/modals/tasks/EditAutomatedTask";
|
||||
import PolicyStatus from "@/components/automation/modals/PolicyStatus";
|
||||
|
||||
export default {
|
||||
@@ -127,6 +165,8 @@ export default {
|
||||
showAddTask: false,
|
||||
columns: [
|
||||
{ name: "enabled", align: "left", field: "enabled" },
|
||||
{ name: "smsalert", field: "text_alert", align: "left" },
|
||||
{ name: "emailalert", field: "email_alert", align: "left" },
|
||||
{ name: "name", label: "Name", field: "name", align: "left" },
|
||||
{
|
||||
name: "schedule",
|
||||
@@ -188,6 +228,42 @@ export default {
|
||||
this.notifyError("There was an issue editing the task");
|
||||
});
|
||||
},
|
||||
taskAlert(pk, alert_type, action, managed_by_policy) {
|
||||
this.$q.loading.show();
|
||||
|
||||
const data = {
|
||||
id: pk,
|
||||
};
|
||||
|
||||
if (alert_type === "Email") {
|
||||
data.email_alert = action;
|
||||
} else {
|
||||
data.text_alert = action;
|
||||
}
|
||||
|
||||
const act = action ? "enabled" : "disabled";
|
||||
this.$axios
|
||||
.put(`/tasks/${pk}/automatedtasks/`, data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.notifySuccess(`${alert_type} alerts ${act}`);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an issue editing task");
|
||||
});
|
||||
},
|
||||
showEditTask(task) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: EditAutomatedTask,
|
||||
parent: this,
|
||||
task: task,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.getTasks();
|
||||
});
|
||||
},
|
||||
showStatus(task) {
|
||||
this.$q.dialog({
|
||||
component: PolicyStatus,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onHide">
|
||||
<q-card class="q-dialog-plugin" style="width: 900px; max-width: 90vw">
|
||||
<q-card class="q-dialog-plugin" style="width: 90vw; max-width: 90vw">
|
||||
<q-bar>
|
||||
<q-btn @click="getPolicyTree" class="q-mr-sm" dense flat push icon="refresh" />Policy Overview
|
||||
<q-space />
|
||||
|
||||
@@ -109,29 +109,47 @@ export default {
|
||||
}
|
||||
this.$q.loading.show();
|
||||
|
||||
let data = {
|
||||
pk: this.object.id,
|
||||
type: this.type,
|
||||
};
|
||||
|
||||
let data = {};
|
||||
let url = "";
|
||||
if (this.type === "client" || this.type === "site") {
|
||||
data.server_policy = this.selectedServerPolicy;
|
||||
data.workstation_policy = this.selectedWorkstationPolicy;
|
||||
} else if (this.type === "agent") {
|
||||
data.policy = this.selectedAgentPolicy;
|
||||
}
|
||||
data = {
|
||||
pk: this.object.id,
|
||||
server_policy: this.selectedServerPolicy,
|
||||
workstation_policy: this.selectedWorkstationPolicy,
|
||||
};
|
||||
|
||||
this.$axios
|
||||
.post(`/automation/related/`, data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.onOk();
|
||||
this.notifySuccess("Policies Updated Successfully!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an error updating policies");
|
||||
});
|
||||
if (this.type === "client") url = `/clients/${this.object.id}/client/`;
|
||||
else if (this.type === "site") url = `/clients/${this.object.id}/site/`;
|
||||
|
||||
this.$axios
|
||||
.put(url, data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.onOk();
|
||||
this.notifySuccess("Policies Updated Successfully!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an error updating policies");
|
||||
});
|
||||
} else if (this.type === "agent") {
|
||||
data = {
|
||||
id: this.object.id,
|
||||
policy: this.selectedAgentPolicy,
|
||||
};
|
||||
|
||||
this.$axios
|
||||
.patch("/agents/editagent/", data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.onOk();
|
||||
this.notifySuccess("Policies Updated Successfully!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an error updating policies");
|
||||
});
|
||||
}
|
||||
},
|
||||
getPolicies() {
|
||||
this.$q.loading.show();
|
||||
|
||||
@@ -56,11 +56,14 @@
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
v-model="autotask.alert_severity"
|
||||
:options="severityOptions"
|
||||
dense
|
||||
label="Alert Severity"
|
||||
outlined
|
||||
v-model="autotask.alert_severity"
|
||||
:options="severityOptions"
|
||||
map-options
|
||||
emit-value
|
||||
options-dense
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
@@ -180,14 +183,13 @@ export default {
|
||||
remove_if_not_scheduled: false,
|
||||
task_type: "scheduled",
|
||||
timeout: 120,
|
||||
alert_severity: null,
|
||||
severityOptions: [
|
||||
{ label: "", value: null },
|
||||
{ label: "Informational", value: "info" },
|
||||
{ label: "Warning", value: "warning" },
|
||||
{ label: "Error", value: "error" },
|
||||
],
|
||||
alert_severity: info,
|
||||
},
|
||||
severityOptions: [
|
||||
{ label: "Informational", value: "info" },
|
||||
{ label: "Warning", value: "warning" },
|
||||
{ label: "Error", value: "error" },
|
||||
],
|
||||
dayOptions: [
|
||||
{ label: "Monday", value: "Monday" },
|
||||
{ label: "Tuesday", value: "Tuesday" },
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onHide">
|
||||
<q-card class="q-dialog-plugin" style="width: 60vw">
|
||||
<q-bar>
|
||||
Edit {{ task.name }}
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form @submit="submit">
|
||||
<q-card-section>
|
||||
<q-select
|
||||
:rules="[val => !!val || '*Required']"
|
||||
dense
|
||||
options-dense
|
||||
outlined
|
||||
v-model="localTask.script"
|
||||
:options="scriptOptions"
|
||||
label="Select script"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
dense
|
||||
label="Script Arguments (press Enter after typing each argument)"
|
||||
filled
|
||||
v-model="localTask.script_args"
|
||||
use-input
|
||||
use-chips
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
:rules="[val => !!val || '*Required']"
|
||||
outlined
|
||||
dense
|
||||
v-model="localTask.name"
|
||||
label="Descriptive name of task"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
v-model="localTask.alert_severity"
|
||||
:options="severityOptions"
|
||||
dense
|
||||
label="Alert Severity"
|
||||
outlined
|
||||
map-options
|
||||
emit-value
|
||||
options-dense
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
:rules="[val => !!val || '*Required']"
|
||||
outlined
|
||||
dense
|
||||
v-model.number="localTask.timeout"
|
||||
type="number"
|
||||
label="Maximum permitted execution time (seconds)"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right">
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn flat label="Submit" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "EditAutomatedTask",
|
||||
mixins: [mixins],
|
||||
props: {
|
||||
task: !Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localTask: {
|
||||
id: null,
|
||||
name: "",
|
||||
script: null,
|
||||
script_args: [],
|
||||
alert_severity: null,
|
||||
timeout: 120,
|
||||
},
|
||||
scriptOptions: [],
|
||||
severityOptions: [
|
||||
{ label: "Informational", value: "info" },
|
||||
{ label: "Warning", value: "warning" },
|
||||
{ label: "Error", value: "error" },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$q.loading.show();
|
||||
|
||||
this.$axios
|
||||
.put(`/tasks/${this.localTask.id}/automatedtasks/`, this.localTask)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.onOk();
|
||||
this.notifySuccess("Task was edited successfully");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an issue editing the task");
|
||||
});
|
||||
},
|
||||
getScripts() {
|
||||
this.$q.loading.show();
|
||||
this.$axios
|
||||
.get("/scripts/scripts/")
|
||||
.then(r => {
|
||||
this.scriptOptions = r.data
|
||||
.map(script => ({ label: script.name, value: script.id }))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
this.$q.loading.hide();
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("There was an error getting scripts");
|
||||
});
|
||||
},
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
onHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
onOk() {
|
||||
this.$emit("ok");
|
||||
this.hide();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getScripts();
|
||||
|
||||
// copy only certain task props locally
|
||||
this.localTask.id = this.task.id;
|
||||
this.localTask.name = this.task.name;
|
||||
this.localTask.script = this.task.script;
|
||||
this.localTask.script_args = this.task.script_args;
|
||||
this.localTask.alert_severity = this.task.alert_severity;
|
||||
this.localTask.timeout = this.task.timeout;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,248 +0,0 @@
|
||||
import { mount, createWrapper, createLocalVue } from "@vue/test-utils";
|
||||
import Vuex from "vuex";
|
||||
import AutomationManager from "@/components/automation/AutomationManager";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const bodyWrapper = createWrapper(document.body);
|
||||
|
||||
// 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());
|
||||
});
|
||||
|
||||
describe("AutomationManager.vue", () => {
|
||||
|
||||
const policiesData = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Test Policy",
|
||||
desc: "Description",
|
||||
active: true,
|
||||
clients: [],
|
||||
sites: [{}, {}],
|
||||
agents: [{}]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Test Policy 2",
|
||||
desc: "Description 2",
|
||||
active: false,
|
||||
clients: [],
|
||||
sites: [{}, {}],
|
||||
agents: [{}]
|
||||
}
|
||||
];
|
||||
|
||||
let wrapper;
|
||||
let state, mutations, actions, store;
|
||||
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
selectedPolicy: null,
|
||||
checks: {},
|
||||
automatedTasks: {},
|
||||
policies: policiesData,
|
||||
};
|
||||
|
||||
mutations = {
|
||||
setSelectedPolicy: jest.fn((state, key) => { state.selectedPolicy = key }),
|
||||
setPolicyChecks: jest.fn(),
|
||||
setPolicyAutomatedTasks: jest.fn(),
|
||||
|
||||
};
|
||||
|
||||
actions = {
|
||||
loadPolicies: jest.fn(),
|
||||
loadPolicyChecks: jest.fn(),
|
||||
loadPolicyAutomatedTasks: jest.fn(),
|
||||
deletePolicy: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mount all sub components except the ones specified
|
||||
wrapper = mount(AutomationManager, {
|
||||
store,
|
||||
localVue,
|
||||
stubs: [
|
||||
"PolicySubTableTabs",,
|
||||
"PolicyOverview",
|
||||
"PolicyForm",
|
||||
"RelationsView"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// The Tests
|
||||
it("calls vuex loadPolicies action on mount", () => {
|
||||
|
||||
expect(actions.loadPolicies).toHaveBeenCalled();
|
||||
expect(mutations.setSelectedPolicy).toHaveBeenCalledWith(expect.anything(), null);
|
||||
expect(mutations.setPolicyChecks).toHaveBeenCalledWith(expect.anything(), []);
|
||||
expect(mutations.setPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), {});
|
||||
|
||||
});
|
||||
|
||||
it("renders table when policies is set from store computed", () => {
|
||||
|
||||
const rows = wrapper.findAll("tbody > tr.q-tr").wrappers;
|
||||
expect(rows).toHaveLength(2);
|
||||
|
||||
});
|
||||
|
||||
it("sends vuex mutations and actions when policy is selected", () => {
|
||||
|
||||
const row = wrapper.findAll("tbody > tr.q-tr").wrappers[1];
|
||||
|
||||
row.trigger("click");
|
||||
|
||||
expect(mutations.setSelectedPolicy).toHaveBeenCalledWith(expect.anything(), 2);
|
||||
expect(actions.loadPolicyChecks).toHaveBeenCalledWith(expect.anything(), 2);
|
||||
expect(actions.loadPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), 2);
|
||||
|
||||
});
|
||||
|
||||
it("shows edit policy modal on edit 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 > .q-tr").trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
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);
|
||||
|
||||
});
|
||||
|
||||
it("shows add policy modal on button press", async () => {
|
||||
|
||||
const button = wrapper.findComponent({ ref: "new" });
|
||||
|
||||
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("shows edit policy modal on edit button press", async () => {
|
||||
|
||||
const button = wrapper.findComponent({ ref: "edit" });
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
await button.trigger("click")
|
||||
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);
|
||||
|
||||
});
|
||||
|
||||
it("deletes selected policy on delete button press", 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);
|
||||
|
||||
//Get OK button and click it
|
||||
await bodyWrapper.findAll(".q-btn").wrappers[1].trigger("click");
|
||||
|
||||
expect(actions.deletePolicy).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
|
||||
});
|
||||
|
||||
it("deletes selected policy", 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");
|
||||
await localVue.nextTick();
|
||||
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");
|
||||
|
||||
expect(actions.deletePolicy).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
|
||||
});
|
||||
|
||||
it("shows overview modal when button clicked", async () => {
|
||||
|
||||
const button = wrapper.findComponent({ ref: "overview" });
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
await button.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
expect(mutations.setSelectedPolicy).toHaveBeenCalledWith(expect.anything(), null);
|
||||
expect(mutations.setPolicyChecks).toHaveBeenCalledWith(expect.anything(), []);
|
||||
expect(mutations.setPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), {});
|
||||
|
||||
});
|
||||
|
||||
it("calls vuex loadPolicies action when refresh button clicked and clears selected", () => {
|
||||
|
||||
const button = wrapper.findComponent({ ref: "refresh" });
|
||||
|
||||
button.trigger("click");
|
||||
expect(actions.loadPolicies).toHaveBeenCalled();
|
||||
expect(mutations.setSelectedPolicy).toHaveBeenCalledWith(expect.anything(), null);
|
||||
expect(mutations.setPolicyChecks).toHaveBeenCalledWith(expect.anything(), []);
|
||||
expect(mutations.setPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), {});
|
||||
|
||||
});
|
||||
|
||||
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");
|
||||
await localVue.nextTick();
|
||||
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);
|
||||
|
||||
});
|
||||
|
||||
// TODO Test Checkboxes on table
|
||||
|
||||
// TODO: Test @close and @hide events
|
||||
|
||||
});
|
||||
@@ -1,106 +0,0 @@
|
||||
|
||||
const common = {
|
||||
email_alert: false,
|
||||
failure_count: 0,
|
||||
failures: 5,
|
||||
history: [],
|
||||
last_run: null,
|
||||
more_info: null,
|
||||
status: "pending",
|
||||
task_on_failure: null,
|
||||
text_alert: false,
|
||||
agent: null,
|
||||
policy: 1,
|
||||
assignedtask: []
|
||||
};
|
||||
|
||||
const diskcheck = {
|
||||
id: 1,
|
||||
check_type: "diskspace",
|
||||
disk: "C:",
|
||||
threshold: 25,
|
||||
readable_desc: "Disk space check: Drive C",
|
||||
...common
|
||||
};
|
||||
|
||||
const cpuloadcheck = {
|
||||
id: 2,
|
||||
check_type: "cpuload",
|
||||
cpuload: 85,
|
||||
readable_desc: "CPU Load check: > 85%",
|
||||
...common
|
||||
};
|
||||
|
||||
const memcheck = {
|
||||
id: 3,
|
||||
check_type: "memory",
|
||||
threshold: 75,
|
||||
readable_desc: "Memory checks: > 85%",
|
||||
...common
|
||||
};
|
||||
|
||||
const scriptcheck = {
|
||||
id: 4,
|
||||
check_type: "script",
|
||||
execution_time: "0.0000",
|
||||
retcode: 0,
|
||||
script: {
|
||||
description: "Test",
|
||||
filename: "local_admin_group.bat",
|
||||
filepath: "salt://scripts//userdefined//local_admin_group.bat",
|
||||
id: 1,
|
||||
name: "Test Script",
|
||||
shell: "cmd"
|
||||
},
|
||||
stderr: null,
|
||||
stdout: null,
|
||||
timeout: 120,
|
||||
readable_desc: "Script check: Test Script",
|
||||
...common
|
||||
};
|
||||
|
||||
const winservicecheck = {
|
||||
id: 5,
|
||||
check_type: "winsvc",
|
||||
pass_if_start_pending: false,
|
||||
restart_if_stopped: false,
|
||||
svc_display_name: "Agent Activation Runtime_1232as",
|
||||
svc_name: "AarSvc_1232as",
|
||||
readable_desc: "Service check: Agent Activation Runtime_1232as",
|
||||
...common
|
||||
};
|
||||
|
||||
const pingcheck = {
|
||||
id: 6,
|
||||
name: "fghfgh",
|
||||
check_type: "ping",
|
||||
ip: "10.10.10.10",
|
||||
readable_desc: "Ping Check: Test Ping Check",
|
||||
...common
|
||||
};
|
||||
|
||||
const eventlogcheck = {
|
||||
id: 7,
|
||||
desc: "asasasa",
|
||||
check_type: "eventlog",
|
||||
log_name: "Application",
|
||||
event_id: 1456,
|
||||
event_type: "ERROR",
|
||||
fail_when: "contains",
|
||||
search_last_days: 1,
|
||||
readable_desc: "Event log check: asdsasa",
|
||||
...common,
|
||||
};
|
||||
|
||||
const tasks = [{ "id": 1, "assigned_check": null, "schedule": "Manual", "name": "fghf", "run_time_days": [], "run_time_minute": null, "task_type": "manual", "win_task_name": "TacticalRMM_UiOgoHSkrxtqWbSZVCGhvjjGdQflZlpnjkd", "timeout": 120, "retcode": null, "stdout": null, "stderr": null, "execution_time": "0.0000", "last_run": null, "enabled": true, "agent": null, "policy": 1, "script": 1 }, { "id": 2, "assigned_check": null, "schedule": "Mon,Tue at 12:03 AM", "name": "vjhkgh", "run_time_days": [0, 1], "run_time_minute": "00:03", "task_type": "scheduled", "win_task_name": "TacticalRMM_KlgPQGGgoVcGEnDXXxJSDjymyTGArTzsVSw", "timeout": 120, "retcode": null, "stdout": null, "stderr": null, "execution_time": "0.0000", "last_run": null, "enabled": true, "agent": null, "policy": 1, "script": 1 }, { "id": 3, "assigned_check": { "id": 2, "readable_desc": "Ping Check: 10.10.10.10", "script": null, "assigned_task": { "id": 1, "name": "test", "run_time_days": [], "run_time_minute": null, "task_type": "checkfailure", "win_task_name": "TacticalRMM_XROsZidGyNuUEwzvvdlgveDwxsrIKRAlHpr", "timeout": 120, "retcode": null, "stdout": null, "stderr": null, "execution_time": "0.0000", "last_run": null, "enabled": true, "agent": null, "policy": 1, "script": 1, "assigned_check": 2 }, "history_info": null, "name": "asdfasd", "check_type": "ping", "status": "pending", "more_info": null, "last_run": null, "email_alert": false, "text_alert": false, "fails_b4_alert": 1, "fail_count": 0, "email_sent": null, "text_sent": null, "outage_history": null, "extra_details": null, "threshold": null, "disk": null, "ip": "10.10.10.10", "timeout": null, "stdout": null, "stderr": null, "retcode": null, "execution_time": null, "history": [], "svc_name": null, "svc_display_name": null, "pass_if_start_pending": null, "restart_if_stopped": null, "svc_policy_mode": null, "log_name": null, "event_id": null, "event_type": null, "fail_when": null, "search_last_days": null, "agent": null, "policy": 1 }, "schedule": "Every time check fails", "name": "test", "run_time_days": [], "run_time_minute": null, "task_type": "checkfailure", "win_task_name": "TacticalRMM_XROsZidGyNuUEwzvvdlgveDwxsrIKRAlHpr", "timeout": 120, "retcode": null, "stdout": null, "stderr": null, "execution_time": "0.0000", "last_run": null, "enabled": true, "agent": null, "policy": 1, "script": 1 }]
|
||||
|
||||
export {
|
||||
diskcheck,
|
||||
cpuloadcheck,
|
||||
memcheck,
|
||||
scriptcheck,
|
||||
winservicecheck,
|
||||
pingcheck,
|
||||
eventlogcheck,
|
||||
tasks
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
import { mount, createLocalVue } from "@vue/test-utils";
|
||||
import flushPromises from "flush-promises";
|
||||
import Vuex from "vuex";
|
||||
import PolicyForm from "@/components/automation/modals/PolicyForm";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
/*** TEST DATA ***/
|
||||
const policy = {
|
||||
id: 1,
|
||||
name: "Test Policy",
|
||||
desc: "Test Desc",
|
||||
enforced: false,
|
||||
active: true
|
||||
};
|
||||
|
||||
let actions, rootActions, store;
|
||||
beforeEach(() => {
|
||||
|
||||
actions = {
|
||||
loadPolicy: jest.fn(() => new Promise(res => res({ data: policy }))),
|
||||
addPolicy: jest.fn(() => new Promise(res => res())),
|
||||
editPolicy: jest.fn(() => new Promise(res => res())),
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
actions: rootActions,
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
actions,
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
/*** TEST SUITES ***/
|
||||
describe("PolicyForm.vue when editting", () => {
|
||||
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
|
||||
wrapper = mount(PolicyForm, {
|
||||
localVue,
|
||||
store,
|
||||
propsData: {
|
||||
pk: 1
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("calls vuex actions on mount with pk prop set", () => {
|
||||
|
||||
expect(actions.loadPolicy).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
|
||||
});
|
||||
|
||||
it("sends the correct edit action on submit", async () => {
|
||||
|
||||
await flushPromises();
|
||||
const form = wrapper.findComponent({ ref: "form" });
|
||||
form.vm.$emit("submit");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(actions.addPolicy).not.toHaveBeenCalled();
|
||||
expect(actions.editPolicy).toHaveBeenCalledWith(expect.anything(), policy);
|
||||
|
||||
});
|
||||
|
||||
it("Renders correct title on edit", () => {
|
||||
|
||||
expect(wrapper.vm.title).toBe("Edit Policy");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyForm.vue when adding", () => {
|
||||
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
|
||||
wrapper = mount(PolicyForm, {
|
||||
localVue,
|
||||
store
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("calls vuex actions on mount", () => {
|
||||
|
||||
// Not called unless pk prop is set
|
||||
expect(actions.loadPolicy).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it("sends the correct add action on submit", async () => {
|
||||
|
||||
wrapper.setData({name: "Test Policy"});
|
||||
const form = wrapper.findComponent({ ref: "form" });
|
||||
form.vm.$emit("submit");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(actions.addPolicy).toHaveBeenCalled();
|
||||
expect(actions.editPolicy).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it("sends error when name isn't set on submit", async () => {
|
||||
|
||||
const form = wrapper.findComponent({ ref: "form" });
|
||||
form.vm.$emit("submit");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(actions.addPolicy).not.toHaveBeenCalled();
|
||||
expect(actions.editPolicy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Renders correct title on add", () => {
|
||||
|
||||
expect(wrapper.vm.title).toBe("Add Policy");
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,139 +0,0 @@
|
||||
import { mount, createLocalVue } from "test-utils";
|
||||
import flushpromises from "flush-promises";
|
||||
import Vuex from "vuex";
|
||||
import PolicyAdd from "@/components/automation/modals/PolicyAdd";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const related = {
|
||||
server_policy: {
|
||||
id: 1,
|
||||
name: "Test Policy"
|
||||
},
|
||||
workstation_policy: {
|
||||
id: 1,
|
||||
name: "Test Policy"
|
||||
}
|
||||
};
|
||||
|
||||
const agentRelated = {
|
||||
policy: {
|
||||
id: 1,
|
||||
name: "Test Policy"
|
||||
}
|
||||
};
|
||||
|
||||
let state, actions, getters, store;
|
||||
beforeEach(() => {
|
||||
|
||||
state = {
|
||||
policies: [
|
||||
{
|
||||
id: 1,
|
||||
name: "Test Policy"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Test Policy 2"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "TestPolicy 3"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
actions = {
|
||||
updateRelatedPolicies: jest.fn(),
|
||||
loadPolicies: jest.fn(),
|
||||
getRelatedPolicies: jest.fn(() => Promise.resolve({ data: related })),
|
||||
};
|
||||
|
||||
getters = {
|
||||
policies: (state) => {
|
||||
return state.policies
|
||||
}
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
describe.each([
|
||||
[1, "client"],
|
||||
[2, "site"],
|
||||
[3, "agent"]
|
||||
])("PolicyAdd.vue with pk:%i and %s type", (pk, type) => {
|
||||
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = mount(PolicyAdd, {
|
||||
localVue,
|
||||
store,
|
||||
propsData: {
|
||||
pk: pk,
|
||||
type: type
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("calls vuex actions on mount", async () => {
|
||||
|
||||
await flushpromises();
|
||||
expect(actions.loadPolicies).toHaveBeenCalled();
|
||||
expect(actions.getRelatedPolicies).toHaveBeenCalledWith(expect.anything(),
|
||||
{ pk: pk, type: type }
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("renders title correctly", () => {
|
||||
|
||||
expect(wrapper.find(".text-h6").text()).toBe(`Edit policies assigned to ${type}`);
|
||||
});
|
||||
|
||||
it("renders correct amount of policies in dropdown", async () => {
|
||||
|
||||
await flushpromises();
|
||||
expect(wrapper.vm.options).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("renders correct policy in selected", async () => {
|
||||
|
||||
await flushpromises();
|
||||
if (type === "client" || type === "site") {
|
||||
expect(wrapper.vm.selectedServerPolicy).toStrictEqual({ label: related.server_policy.name, value: related.server_policy.id });
|
||||
expect(wrapper.vm.selectedWorkstationPolicy).toStrictEqual({ label: related.workstation_policy.name, value: related.workstation_policy.id });
|
||||
}
|
||||
|
||||
// not testing agent
|
||||
});
|
||||
|
||||
it("sends correct data on form submit", async () => {
|
||||
|
||||
await flushpromises();
|
||||
const form = wrapper.findComponent({ ref: "form" });
|
||||
|
||||
await form.vm.$emit("submit");
|
||||
|
||||
if (type === "client" || type === "site") {
|
||||
expect(actions.updateRelatedPolicies).toHaveBeenCalledWith(expect.anything(),
|
||||
{ pk: pk, type: type, server_policy: 1, workstation_policy: 1 }
|
||||
);
|
||||
}
|
||||
|
||||
// not testing agent actions
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,405 +0,0 @@
|
||||
import { mount, createWrapper, createLocalVue } from "@vue/test-utils";
|
||||
import PolicyChecksTab from "@/components/automation/PolicyChecksTab";
|
||||
import Vuex from "vuex";
|
||||
import "../../utils/quasar.js"
|
||||
|
||||
// Import Test Data
|
||||
import {
|
||||
diskcheck,
|
||||
cpuloadcheck,
|
||||
memcheck,
|
||||
scriptcheck,
|
||||
winservicecheck,
|
||||
pingcheck,
|
||||
eventlogcheck
|
||||
} from "./data.js";
|
||||
|
||||
const localVue = createLocalVue()
|
||||
localVue.use(Vuex);
|
||||
|
||||
const bodyWrapper = createWrapper(document.body);
|
||||
|
||||
// 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());
|
||||
});
|
||||
|
||||
/*** TEST SUITES ***/
|
||||
describe("PolicyChecksTab.vue with no policy selected", () => {
|
||||
|
||||
let wrapper, state, getters, store;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
checks: [],
|
||||
selectedPolicy: null
|
||||
};
|
||||
|
||||
getters = {
|
||||
checks(state) {
|
||||
return state.checks
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy
|
||||
}
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper = mount(PolicyChecksTab, {
|
||||
store,
|
||||
localVue
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("renders text when policy is selected with no checks", () => {
|
||||
|
||||
expect(wrapper.html()).toContain("Click on a policy to see the checks");
|
||||
});
|
||||
|
||||
it("doesn't show refresh or add button when no policy selected", () => {
|
||||
|
||||
expect(wrapper.findComponent({ ref: "refresh" }).exists()).toBe(false)
|
||||
expect(wrapper.findComponent({ ref: "add" }).exists()).toBe(false)
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyChecksTab.vue with policy selected and no checks", () => {
|
||||
|
||||
// Used for the add check test loop
|
||||
const addChecksMenu = [
|
||||
{ name: "DiskSpaceCheck", index: 0 },
|
||||
{ name: "PingCheck", index: 1},
|
||||
{ name: "CpuLoadCheck", index: 2},
|
||||
{ name: "MemCheck", index: 3},
|
||||
{ name: "WinSvcCheck", index: 4},
|
||||
{ name: "ScriptCheck", index: 5},
|
||||
{ name: "EventLogCheck", index: 6}
|
||||
];
|
||||
|
||||
let wrapper, store, state, actions, getters;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
checks: [],
|
||||
selectedPolicy: 1
|
||||
};
|
||||
|
||||
getters = {
|
||||
checks(state) {
|
||||
return state.checks
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy
|
||||
}
|
||||
};
|
||||
|
||||
actions = {
|
||||
loadPolicyChecks: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mount all sub components except the ones specified
|
||||
wrapper = mount(PolicyChecksTab, {
|
||||
store,
|
||||
localVue,
|
||||
stubs: [
|
||||
"DiskSpaceCheck",
|
||||
"PingCheck",
|
||||
"CpuLoadCheck",
|
||||
"MemCheck",
|
||||
"WinSvcCheck",
|
||||
"ScriptCheck",
|
||||
"EventLogCheck"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("renders text when policy is selected with no checks", () => {
|
||||
|
||||
expect(wrapper.html()).toContain("There are no checks added to this policy");
|
||||
});
|
||||
|
||||
it("sends vuex actions on refresh button click", () => {
|
||||
|
||||
wrapper.findComponent({ ref: "refresh" }).trigger("click");
|
||||
expect(actions.loadPolicyChecks).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
});
|
||||
|
||||
// Create a test for each Add modal
|
||||
addChecksMenu.forEach(item => {
|
||||
it(`opens ${item.name} Dialog`, async () => {
|
||||
|
||||
const addButton = wrapper.findComponent({ ref: "add" });
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
await addButton.trigger("click");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
// Selects correct menu item
|
||||
await bodyWrapper.findAll(".q-item").wrappers[item.index].trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.showDialog).toBe(true);
|
||||
expect(wrapper.vm.dialogComponent).toBe(item.name);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyChecksTab.vue with policy selected and checks", () => {
|
||||
|
||||
// Used for the edit check test loop
|
||||
const editChecksModals = [
|
||||
{name: "DiskSpaceCheck", index: 0, id: 1},
|
||||
{name: "CpuLoadCheck", index: 1, id: 2},
|
||||
{name: "MemCheck", index: 2, id: 3},
|
||||
{name: "ScriptCheck", index: 3, id: 4},
|
||||
{name: "WinSvcCheck", index: 4, id: 5},
|
||||
{name: "PingCheck", index: 5, id: 6},
|
||||
{name: "EventLogCheck", index: 6, id: 7}
|
||||
];
|
||||
|
||||
let state, rootActions, actions, getters, store, wrapper;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
checks: [
|
||||
diskcheck,
|
||||
cpuloadcheck,
|
||||
memcheck,
|
||||
scriptcheck,
|
||||
winservicecheck,
|
||||
pingcheck,
|
||||
eventlogcheck
|
||||
],
|
||||
selectedPolicy: 1
|
||||
};
|
||||
|
||||
getters = {
|
||||
checks(state) {
|
||||
return state.checks
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy
|
||||
}
|
||||
};
|
||||
|
||||
actions = {
|
||||
loadPolicyChecks: jest.fn()
|
||||
};
|
||||
|
||||
rootActions = {
|
||||
editCheckAlert: jest.fn(),
|
||||
deleteCheck: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
actions: rootActions,
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mount all sub components except the ones specified
|
||||
wrapper = mount(PolicyChecksTab, {
|
||||
store,
|
||||
localVue,
|
||||
stubs: [
|
||||
"DiskSpaceCheck",
|
||||
"PingCheck",
|
||||
"CpuLoadCheck",
|
||||
"MemCheck",
|
||||
"WinSvcCheck",
|
||||
"ScriptCheck",
|
||||
"EventLogCheck",
|
||||
"PolicyStatus"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("renders the correct number of rows based on checks", () => {
|
||||
|
||||
const rows = wrapper.findAll(".q-table > tbody > .q-tr").wrappers;
|
||||
expect(rows).toHaveLength(7);
|
||||
});
|
||||
|
||||
// Create a test for each Edit modal
|
||||
editChecksModals.forEach(item => {
|
||||
it(`show ${item.name} Dialog`, async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[item.index];
|
||||
await row.trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-edit").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.showDialog).toBe(true);
|
||||
expect(wrapper.vm.dialogComponent).toBe(item.name);
|
||||
expect(wrapper.vm.editCheckPK).toBe(item.id);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("shows policy status modal on cell click", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".status-cell").wrappers[0];
|
||||
await row.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.statusCheck).toEqual(diskcheck);
|
||||
});
|
||||
|
||||
it("shows policy status modal on context menu item click", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[0];
|
||||
await row.trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-status").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.statusCheck).toEqual(diskcheck);
|
||||
});
|
||||
|
||||
it("deletes check", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[0];
|
||||
await row.trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-delete").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
//Get OK button on confirmation dialog and click it
|
||||
await bodyWrapper.findAll(".q-btn").wrappers[1].trigger("click");
|
||||
|
||||
expect(rootActions.deleteCheck).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
expect(actions.loadPolicyChecks).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it("enables and disables text alerts for check", async () => {
|
||||
|
||||
//Get first checkbox in first row
|
||||
const row = wrapper.findAll(".q-checkbox").wrappers[0];
|
||||
|
||||
//Enable Text Alert
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editCheckAlert).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{
|
||||
pk: 1,
|
||||
data: {
|
||||
text_alert: true,
|
||||
check_alert: true
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//Disable Text Alert
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editCheckAlert).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{
|
||||
pk: 1,
|
||||
data: {
|
||||
text_alert: false,
|
||||
check_alert: true
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("enables and disables email alerts for check", async () => {
|
||||
|
||||
//Get second checkbox in first row
|
||||
const row = wrapper.findAll(".q-checkbox").wrappers[1];
|
||||
|
||||
//Enable Text Alert
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editCheckAlert).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{
|
||||
pk: 1,
|
||||
data: {
|
||||
email_alert: true,
|
||||
check_alert: true
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//Disable Text Alert
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editCheckAlert).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{
|
||||
pk: 1,
|
||||
data: {
|
||||
email_alert: false,
|
||||
check_alert: true
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
/* TODO: test @close and @hide events */
|
||||
});
|
||||
@@ -1,146 +0,0 @@
|
||||
import { mount, createLocalVue } from "@vue/test-utils";
|
||||
import Vuex from "vuex";
|
||||
import PolicyOverview from "@/components/automation/PolicyOverview";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
describe("PolicyOverview.vue", () => {
|
||||
|
||||
const policyTreeData = [
|
||||
{
|
||||
// node 0
|
||||
client: "Client Name 1",
|
||||
workstation_policy: {
|
||||
id: 1,
|
||||
name: "Policy Name 1",
|
||||
active: true
|
||||
},
|
||||
server_policy: null,
|
||||
// node -1
|
||||
sites: [
|
||||
{
|
||||
site: "Site Name 1",
|
||||
server_policy: null,
|
||||
workstation_policy: null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// node -2
|
||||
client: "Client Name 2",
|
||||
server_policy: {
|
||||
id: 2,
|
||||
name: "Policy Name 2",
|
||||
active: true
|
||||
},
|
||||
workstation_policy: null,
|
||||
sites: [
|
||||
{
|
||||
// node -3
|
||||
site: "Site Name 2",
|
||||
workstation_policy: {
|
||||
id: 3,
|
||||
name: "Policy Name 3",
|
||||
active: false
|
||||
},
|
||||
server_policy: {
|
||||
id: 3,
|
||||
name: "Policy Name 3",
|
||||
active: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
let wrapper, actions, mutations, store;
|
||||
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
actions = {
|
||||
loadPolicyTreeData: jest.fn(() => new Promise(res => res({ data: policyTreeData }))),
|
||||
loadPolicyChecks: jest.fn(),
|
||||
loadPolicyAutomatedTasks: jest.fn()
|
||||
};
|
||||
|
||||
mutations = {
|
||||
setSelectedPolicy: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper = mount(PolicyOverview, {
|
||||
localVue,
|
||||
store,
|
||||
stubs: [
|
||||
"PolicyChecksTab",
|
||||
"PolicyAutomatedTasksTab"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// The Tests
|
||||
it("calls vuex actions on mount", () => {
|
||||
|
||||
expect(actions.loadPolicyTreeData).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it("renders tree data", async () => {
|
||||
|
||||
await localVue.nextTick();
|
||||
|
||||
const tree = wrapper.findComponent({ ref: "tree" });
|
||||
|
||||
const policy1 = tree.vm.getNodeByKey(1);
|
||||
const policy2 = tree.vm.getNodeByKey(2);
|
||||
const policy3 = tree.vm.getNodeByKey(3);
|
||||
const client1 = tree.vm.getNodeByKey(0);
|
||||
const client2 = tree.vm.getNodeByKey(-2);
|
||||
const site1 = tree.vm.getNodeByKey(-1);
|
||||
const site2 = tree.vm.getNodeByKey(-3);
|
||||
|
||||
expect(policy1.label).toBe("Policy Name 1 (Workstations)");
|
||||
expect(policy2.label).toBe("Policy Name 2 (Servers)");
|
||||
expect(policy3.label).toBe("Policy Name 3 (Workstations) (disabled)");
|
||||
expect(client1.label).toBe("Client Name 1");
|
||||
expect(client2.label).toBe("Client Name 2");
|
||||
expect(site1.label).toBe("Site Name 1");
|
||||
expect(site2.label).toBe("Site Name 2");
|
||||
});
|
||||
|
||||
it("selects tree node and updates data property with policy", async () => {
|
||||
|
||||
// Expected rendered policy node data
|
||||
const returnData = {
|
||||
icon: "policy",
|
||||
id: 1,
|
||||
label: "Policy Name 1 (Workstations)"
|
||||
};
|
||||
|
||||
await localVue.nextTick();
|
||||
|
||||
// Get second tree node which should be the first policy
|
||||
wrapper.findAll(".q-tree__node-header").wrappers[1].trigger("click");
|
||||
|
||||
expect(wrapper.vm.selectedPolicy).toStrictEqual(returnData);
|
||||
expect(actions.loadPolicyChecks).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
expect(mutations.setSelectedPolicy).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
expect(actions.loadPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
import { mount, createWrapper, createLocalVue } from "@vue/test-utils";
|
||||
import Vuex from "vuex";
|
||||
import flushpromises from "flush-promises";
|
||||
import PolicyStatus from "@/components/automation/modals/PolicyStatus";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const bodyWrapper = createWrapper(document.body);
|
||||
|
||||
// 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());
|
||||
});
|
||||
|
||||
// test data
|
||||
const item = {
|
||||
id: 1,
|
||||
readable_desc: "Check Description"
|
||||
};
|
||||
|
||||
describe("PolicyStatus.vue viewing check status", () => {
|
||||
|
||||
const data = [
|
||||
{
|
||||
hostname: "Agent 1",
|
||||
status: "pending",
|
||||
check_type: "ping",
|
||||
last_run: "Last Run"
|
||||
},
|
||||
{
|
||||
hostname: "Agent 2",
|
||||
status: "passing",
|
||||
check_type: "script",
|
||||
last_run: "Last Run"
|
||||
},
|
||||
{
|
||||
hostname: "Agent 3",
|
||||
status: "failing",
|
||||
check_type: "eventlog",
|
||||
last_run: "Last Run"
|
||||
},
|
||||
];
|
||||
|
||||
let wrapper, actions, store;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
actions = {
|
||||
loadCheckStatus: jest.fn(() => Promise.resolve({ data: data }))
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
actions,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper = mount(PolicyStatus, {
|
||||
localVue,
|
||||
store,
|
||||
propsData: {
|
||||
item: item,
|
||||
type: "check"
|
||||
},
|
||||
stubs: [
|
||||
"ScriptOutput",
|
||||
"EventLogCheckOutput"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("calls correct check vuex action on mount", () => {
|
||||
|
||||
expect(actions.loadCheckStatus).toHaveBeenCalledWith(expect.anything(), { checkpk: item.id });
|
||||
|
||||
});
|
||||
|
||||
it("renders correct number of rows in table", async () => {
|
||||
|
||||
await flushpromises();
|
||||
await localVue.nextTick();
|
||||
const rows = wrapper.findAll(".q-table > tbody > .q-tr").wrappers;
|
||||
expect(rows).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("shows event log status on cell click", async () => {
|
||||
|
||||
await flushpromises();
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".eventlog-cell").wrappers[0];
|
||||
await row.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
// Needs to be equal to eventlog check in test data array
|
||||
expect(wrapper.vm.evtLogData).toEqual(data[2]);
|
||||
});
|
||||
|
||||
it("shows script status on cell click", async () => {
|
||||
|
||||
await flushpromises();
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".script-cell").wrappers[0];
|
||||
await row.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
// Needs to be equal to script check in test data array
|
||||
expect(wrapper.vm.scriptInfo).toEqual(data[1]);
|
||||
});
|
||||
|
||||
it("shows pingstatus on cell click", async () => {
|
||||
|
||||
await flushpromises();
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".ping-cell").wrappers[0];
|
||||
await row.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyStatus.vue viewing task status", () => {
|
||||
|
||||
const data = [];
|
||||
|
||||
let wrapper, actions, store;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
actions = {
|
||||
loadAutomatedTaskStatus: jest.fn(() => Promise.resolve({ data: data })),
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
actions,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper = mount(PolicyStatus, {
|
||||
localVue,
|
||||
store,
|
||||
propsData: {
|
||||
item: item,
|
||||
type: "task"
|
||||
},
|
||||
stubs: [
|
||||
"ScriptOutput",
|
||||
"EventLogCheckOutput"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("calls correct check vuex action on mount", () => {
|
||||
|
||||
expect(actions.loadAutomatedTaskStatus).toHaveBeenCalledWith(expect.anything(), { taskpk: item.id });
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,300 +0,0 @@
|
||||
import { mount, createWrapper, createLocalVue } from "@vue/test-utils";
|
||||
import PolicyAutomatedTasksTab from "@/components/automation/PolicyAutomatedTasksTab";
|
||||
import Vuex from "vuex";
|
||||
import "../../utils/quasar.js";
|
||||
|
||||
// Import Test Data
|
||||
import {
|
||||
tasks
|
||||
} from "./data.js";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const bodyWrapper = createWrapper(document.body);
|
||||
|
||||
// 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());
|
||||
});
|
||||
|
||||
/*** TEST SUITES ***/
|
||||
describe("PolicyAutomatedTasksTab.vue with no policy selected", () => {
|
||||
|
||||
let wrapper, state, getters, store;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
automatedTasks: {},
|
||||
selectedPolicy: null
|
||||
};
|
||||
|
||||
getters = {
|
||||
tasks(state) {
|
||||
return state.automatedTasks.autotasks;
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy;
|
||||
}
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper = mount(PolicyAutomatedTasksTab, {
|
||||
store,
|
||||
localVue
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("renders text when policy is selected with no tasks", () => {
|
||||
|
||||
expect(wrapper.html()).toContain("Click on a policy to see the tasks");
|
||||
});
|
||||
|
||||
it("doesn't show refresh or add button when no policy selected", () => {
|
||||
|
||||
expect(wrapper.findComponent({ ref: "refresh" }).exists()).toBe(false)
|
||||
expect(wrapper.findComponent({ ref: "add" }).exists()).toBe(false)
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyAutomatedTasksTab.vue with policy selected and no tasks", () => {
|
||||
|
||||
let wrapper, store, state, actions, getters;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
automatedTasks: {
|
||||
autotasks: []
|
||||
},
|
||||
selectedPolicy: 1
|
||||
};
|
||||
|
||||
getters = {
|
||||
tasks(state) {
|
||||
return state.automatedTasks.autotasks;
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy;
|
||||
}
|
||||
};
|
||||
|
||||
actions = {
|
||||
loadPolicyAutomatedTasks: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mount all sub components except the ones specified
|
||||
wrapper = mount(PolicyAutomatedTasksTab, {
|
||||
store,
|
||||
localVue,
|
||||
stubs: [
|
||||
"AddAutomatedTask",
|
||||
"PolicyStatus"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("renders text when policy is selected with no tasks", () => {
|
||||
|
||||
expect(wrapper.html()).toContain("There are no tasks added to this policy");
|
||||
});
|
||||
|
||||
it("sends vuex actions on refresh button click", () => {
|
||||
|
||||
wrapper.findComponent({ ref: "refresh" }).trigger("click");
|
||||
expect(actions.loadPolicyAutomatedTasks).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
});
|
||||
|
||||
it(`opens AddAutomatedTask Dialog`, async () => {
|
||||
|
||||
const addButton = wrapper.findComponent({ ref: "add" });
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
await addButton.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("PolicyChecksTab.vue with policy selected and checks", () => {
|
||||
|
||||
let state, rootActions, actions, getters, store, wrapper;
|
||||
// Runs before every test
|
||||
beforeEach(() => {
|
||||
|
||||
// Create the Test store
|
||||
state = {
|
||||
automatedTasks: {
|
||||
autotasks: tasks
|
||||
},
|
||||
selectedPolicy: 1
|
||||
};
|
||||
|
||||
getters = {
|
||||
tasks(state) {
|
||||
return state.automatedTasks.autotasks;
|
||||
},
|
||||
selectedPolicyPk(state) {
|
||||
return state.selectedPolicy;
|
||||
}
|
||||
};
|
||||
|
||||
actions = {
|
||||
loadPolicyAutomatedTasks: jest.fn(),
|
||||
runPolicyTask: jest.fn()
|
||||
};
|
||||
|
||||
rootActions = {
|
||||
editAutoTask: jest.fn(),
|
||||
deleteAutoTask: jest.fn()
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
actions: rootActions,
|
||||
modules: {
|
||||
automation: {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mount all sub components except the ones specified
|
||||
wrapper = mount(PolicyAutomatedTasksTab, {
|
||||
store,
|
||||
localVue,
|
||||
stubs: [
|
||||
"AddAutomatedTask",
|
||||
"PolicyStatus"
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*** TESTS ***/
|
||||
it("renders the correct number of rows based on tasks", () => {
|
||||
|
||||
const rows = wrapper.findAll(".q-table > tbody > .q-tr").wrappers;
|
||||
expect(rows).toHaveLength(3);
|
||||
});
|
||||
|
||||
// Edit Modal
|
||||
/*it(`show EditAutomatedTask Dialog`, async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[1];
|
||||
await row.trigger("contextmenu");
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-edit").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
});*/
|
||||
|
||||
it("shows policy status modal on cell click", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".status-cell").wrappers[1];
|
||||
await row.trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.statusTask).toEqual(tasks[1]);
|
||||
});
|
||||
|
||||
it("shows policy status modal on context menu item click", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[0];
|
||||
await row.trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-status").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
expect(wrapper.vm.statusTask).toEqual(tasks[0]);
|
||||
});
|
||||
|
||||
it("deletes task", async () => {
|
||||
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(false);
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(false);
|
||||
|
||||
const row = wrapper.findAll(".q-table > tbody > .q-tr").wrappers[0];
|
||||
await row.trigger("contextmenu");
|
||||
await localVue.nextTick();
|
||||
expect(bodyWrapper.find(".q-menu").exists()).toBe(true);
|
||||
|
||||
await bodyWrapper.find("#context-delete").trigger("click");
|
||||
expect(bodyWrapper.find(".q-dialog").exists()).toBe(true);
|
||||
|
||||
//Get OK button on confirmation dialog and click it
|
||||
await bodyWrapper.findAll(".q-btn").wrappers[1].trigger("click");
|
||||
|
||||
expect(rootActions.deleteAutoTask).toHaveBeenCalledWith(expect.anything(), 1);
|
||||
expect(actions.loadPolicyAutomatedTasks).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it("enables and disables task", async () => {
|
||||
|
||||
//Get first checkbox in first row
|
||||
const row = wrapper.findAll(".q-checkbox").wrappers[0];
|
||||
|
||||
//Disable Task
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editAutoTask).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{ id: 1, enableordisable: false }
|
||||
);
|
||||
|
||||
//Enable Task
|
||||
await row.trigger("click");
|
||||
|
||||
expect(rootActions.editAutoTask).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
{ id: 1, enableordisable: true }
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
/* TODO: test @close and @hide events */
|
||||
});
|
||||
@@ -1,143 +0,0 @@
|
||||
import { mount, createLocalVue } from "@vue/test-utils";
|
||||
import Vuex from "vuex";
|
||||
import RelationsView from "@/components/automation/modals/RelationsView";
|
||||
import "../../utils/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"
|
||||
}
|
||||
],
|
||||
server_sites: [
|
||||
{
|
||||
id: 1,
|
||||
client_name: "Test Name",
|
||||
site: "Test Name"
|
||||
}
|
||||
],
|
||||
workstation_sites: [
|
||||
{
|
||||
id: 2,
|
||||
client_name: "Test Name",
|
||||
site: "Test Name"
|
||||
}
|
||||
],
|
||||
server_clients: [
|
||||
{
|
||||
id: 1,
|
||||
client: "Test Name"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
client: "Test Name2"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
client: "Test Name3"
|
||||
}
|
||||
],
|
||||
workstation_clients: [
|
||||
{
|
||||
id: 4,
|
||||
client: "Test Name"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
client: "Test Name2"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
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.server_clients.length + related.workstation_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.server_sites.length + related.workstation_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);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user