diff --git a/package.json b/package.json
index 531bb2ea..9f393534 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "yattie",
- "version": "0.1.0",
+ "version": "0.1.1",
"private": true,
"main": "background.js",
"engines": {
@@ -27,7 +27,7 @@
"@fortawesome/fontawesome-free": "^6.2.1",
"@johmun/vue-tags-input": "^2.1.0",
"@tinymce/tinymce-vue": "^3.2.0",
- "@toast-ui/vue-image-editor": "^3.15.2",
+ "tui-image-editor": "^3.15.3",
"adm-zip": "^0.5.9",
"core-js": "^3.8.3",
"d3": "^5.14.2",
@@ -39,6 +39,7 @@
"fluent-ffmpeg": "^2.1.2",
"lodash": "^4.17.21",
"simple-json-db": "^2.0.0",
+ "sinon": "^15.0.0",
"tinymce": "^6.2.0",
"uuid": "3.3.3",
"v-mask": "^2.3.0",
diff --git a/src/App.vue b/src/App.vue
index b8c585c5..7f61d7ca 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,41 +1,28 @@
-
-
-
+
+
-
-
+
+
+
diff --git a/src/assets/avatar.png b/src/assets/avatar.png
new file mode 100644
index 00000000..737cf25b
Binary files /dev/null and b/src/assets/avatar.png differ
diff --git a/src/assets/icon/camera-white.svg b/src/assets/icon/camera-white.svg
new file mode 100644
index 00000000..0f73ffb5
--- /dev/null
+++ b/src/assets/icon/camera-white.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icon/expand.svg b/src/assets/icon/expand.svg
new file mode 100644
index 00000000..72262a40
--- /dev/null
+++ b/src/assets/icon/expand.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icon/jira.png b/src/assets/icon/jira.png
new file mode 100644
index 00000000..6c5aa9f2
Binary files /dev/null and b/src/assets/icon/jira.png differ
diff --git a/src/assets/icon/jira.svg b/src/assets/icon/jira.svg
new file mode 100644
index 00000000..612e4c42
--- /dev/null
+++ b/src/assets/icon/jira.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/icon/microphone-slash-solid.svg b/src/assets/icon/microphone-slash-solid.svg
new file mode 100644
index 00000000..b69e019e
--- /dev/null
+++ b/src/assets/icon/microphone-slash-solid.svg
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/icon/microphone-solid.svg b/src/assets/icon/microphone-solid.svg
new file mode 100644
index 00000000..8028507e
--- /dev/null
+++ b/src/assets/icon/microphone-solid.svg
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/icon/microphone-white.svg b/src/assets/icon/microphone-white.svg
new file mode 100644
index 00000000..eaccc705
--- /dev/null
+++ b/src/assets/icon/microphone-white.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/icon/microphone.svg b/src/assets/icon/microphone.svg
deleted file mode 100644
index 16c93e0a..00000000
--- a/src/assets/icon/microphone.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/src/assets/icon/pause-white.svg b/src/assets/icon/pause-white.svg
new file mode 100644
index 00000000..850db3d6
--- /dev/null
+++ b/src/assets/icon/pause-white.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icon/pencil-white1.svg b/src/assets/icon/pencil-white1.svg
new file mode 100644
index 00000000..7cb6e4a0
--- /dev/null
+++ b/src/assets/icon/pencil-white1.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/icon/practitest.png b/src/assets/icon/practitest.png
new file mode 100644
index 00000000..4b9f3e27
Binary files /dev/null and b/src/assets/icon/practitest.png differ
diff --git a/src/assets/icon/practitest.svg b/src/assets/icon/practitest.svg
new file mode 100644
index 00000000..76ef7b1d
--- /dev/null
+++ b/src/assets/icon/practitest.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/icon/qtest.png b/src/assets/icon/qtest.png
new file mode 100644
index 00000000..6c5e5f4b
Binary files /dev/null and b/src/assets/icon/qtest.png differ
diff --git a/src/assets/icon/qtest.svg b/src/assets/icon/qtest.svg
new file mode 100644
index 00000000..f900d4b4
--- /dev/null
+++ b/src/assets/icon/qtest.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/icon/stop-white.svg b/src/assets/icon/stop-white.svg
new file mode 100644
index 00000000..c1887907
--- /dev/null
+++ b/src/assets/icon/stop-white.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icon/testrail.png b/src/assets/icon/testrail.png
new file mode 100644
index 00000000..dae6f408
Binary files /dev/null and b/src/assets/icon/testrail.png differ
diff --git a/src/assets/icon/testrail.svg b/src/assets/icon/testrail.svg
new file mode 100644
index 00000000..53772188
--- /dev/null
+++ b/src/assets/icon/testrail.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/icon/union.svg b/src/assets/icon/union.svg
new file mode 100644
index 00000000..874e20e6
--- /dev/null
+++ b/src/assets/icon/union.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icon/video-slash-solid.svg b/src/assets/icon/video-slash-solid.svg
new file mode 100644
index 00000000..c9c72329
--- /dev/null
+++ b/src/assets/icon/video-slash-solid.svg
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/icon/video-solid.svg b/src/assets/icon/video-solid.svg
new file mode 100644
index 00000000..2050d262
--- /dev/null
+++ b/src/assets/icon/video-solid.svg
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/icon/video-white.svg b/src/assets/icon/video-white.svg
new file mode 100644
index 00000000..3649798e
--- /dev/null
+++ b/src/assets/icon/video-white.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/icon/video.svg b/src/assets/icon/video.svg
deleted file mode 100644
index b66284eb..00000000
--- a/src/assets/icon/video.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/src/assets/icon/yattie.png b/src/assets/icon/yattie.png
new file mode 100644
index 00000000..19bce1b9
Binary files /dev/null and b/src/assets/icon/yattie.png differ
diff --git a/src/assets/icon/yattie.svg b/src/assets/icon/yattie.svg
new file mode 100644
index 00000000..84e76873
--- /dev/null
+++ b/src/assets/icon/yattie.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/AudioWrapper.vue b/src/components/AudioWrapper.vue
index a45ba8c0..459e3936 100644
--- a/src/components/AudioWrapper.vue
+++ b/src/components/AudioWrapper.vue
@@ -98,7 +98,7 @@
diff --git a/src/components/CheckTaskWrapper.vue b/src/components/CheckTaskWrapper.vue
index 51e2d0b6..87f077de 100644
--- a/src/components/CheckTaskWrapper.vue
+++ b/src/components/CheckTaskWrapper.vue
@@ -9,7 +9,7 @@
-
+
@@ -201,7 +201,11 @@
:disabled="status === 'pause'"
@click="stopRecordVideo()"
>
-
mdi-video-off
+
Stop Video Record
@@ -242,9 +246,9 @@
@click="startRecordAudio()"
>
@@ -263,7 +267,11 @@
:disabled="status === 'pause'"
@click="stopRecordAudio()"
>
-
mdi-microphone-off
+
Stop Audio Record
@@ -311,6 +319,26 @@
Mind Map
+
-
+
+
[],
+ },
selectedItems: {
type: Array,
default: () => [],
},
+ configItem: {
+ type: Object,
+ default: () => {},
+ },
checkedStatusOfPreSessionTask: {
type: Boolean,
default: () => false,
@@ -422,15 +475,30 @@ export default {
default: () => {},
},
},
+ created() {
+ try {
+ audioContext = new AudioContext();
+ dest = audioContext.createMediaStreamDestination();
+ } catch (e) {
+ console.log(e);
+ }
+ },
watch: {
+ items: function (newValue) {
+ this.itemLists = newValue;
+ },
selectedItems: function (newValue) {
this.selected = newValue;
},
+ configItem: function (newValue) {
+ this.config = newValue;
+ },
},
data() {
return {
sourcePickerDialog: false,
noteDialog: false,
+ summaryDialog: false,
deleteConfirmDialog: false,
resetConfirmDialog: false,
@@ -441,6 +509,8 @@ export default {
sources: [],
sourceId: "",
+ itemLists: this.items,
+ config: this.configItem,
audioDevices: [],
loaded: false,
status: this.$store.state.status,
@@ -460,6 +530,10 @@ export default {
mounted() {
this.$root.$on("close-sourcepickerdialog", this.hideSourcePickerDialog);
this.$root.$on("close-notedialog", this.hideNoteDialog);
+ this.$root.$on("close-summarydialog", () => {
+ this.summaryDialog = false;
+ this.endSession();
+ });
},
beforeDestroy() {
this.$root.$off("close-sourcepickerdialog", this.hideSourcePickerDialog);
@@ -509,9 +583,6 @@ export default {
this.updateStoreSession();
},
updateStoreSession() {
- console.log(`
- status: ${this.status}, timer: ${this.timer}, duration: ${this.duration}
- `);
this.$store.commit("updateSession", {
status: this.status,
timer: this.timer,
@@ -531,6 +602,7 @@ export default {
this.$store.commit("setStarted", this.started);
this.startInterval();
+ this.changeSessionStatus(SESSION_STATUSES.START);
const currentPath = this.$router.history.current.path;
if (currentPath !== "/main/timeline") {
@@ -539,6 +611,7 @@ export default {
},
pauseSession() {
this.status = SESSION_STATUSES.PAUSE;
+ this.changeSessionStatus(SESSION_STATUSES.PAUSE);
this.stopInterval();
},
resumeSession() {
@@ -562,6 +635,7 @@ export default {
this.$store.commit("setEnded", this.ended);
this.status = SESSION_STATUSES.END;
+ this.changeSessionStatus(SESSION_STATUSES.END);
this.stopInterval();
if (window.ipc) {
@@ -580,14 +654,17 @@ export default {
},
resume() {
this.status = SESSION_STATUSES.PAUSE;
+ this.changeSessionStatus(SESSION_STATUSES.PAUSE);
this.timer = this.$store.state.timer;
this.updateStoreSession();
+ this.removeSummary();
this.$router.push({ path: "/main/timeline" });
},
reset() {
this.resetConfirmDialog = false;
this.status = SESSION_STATUSES.PENDING;
+ this.changeSessionStatus(SESSION_STATUSES.PENDING);
this.$store.commit("resetState");
try {
@@ -610,11 +687,13 @@ export default {
proceed() {
this.durationConfirmDialog = false;
this.status = SESSION_STATUSES.PROCEED;
+ this.changeSessionStatus(SESSION_STATUSES.PROCEED);
this.startInterval();
},
updateStatus(value) {
this.status = value;
+ this.changeSessionStatus(this.status);
this.$store.commit("setStatus", this.status);
},
async getSourceList() {
@@ -653,7 +732,7 @@ export default {
})
.then(({ fileName, filePath }) => {
const data = {
- sessionType: "screenshot",
+ sessionType: "Screenshot",
fileType: "image",
fileName: fileName,
filePath: filePath,
@@ -690,6 +769,9 @@ export default {
},
async startRecordVideo() {
this.handleStream = (stream) => {
+ if (this.config.audioCapture && this.audioDevices.length > 0) {
+ stream.addTrack(dest.stream.getAudioTracks()[0]);
+ }
mediaRecorder = new MediaRecorder(stream, {
mimeType: "video/webm;codecs=h264",
});
@@ -739,7 +821,7 @@ export default {
})
.then(({ fileName, filePath }) => {
const data = {
- sessionType: "video",
+ sessionType: "Video",
fileType: "video",
fileName: fileName,
filePath: filePath,
@@ -761,21 +843,39 @@ export default {
};
try {
- const stream = await navigator.mediaDevices.getUserMedia({
+ const videoQuality = this.config.videoQuality;
+ let resolution;
+ VIDEO_RESOLUTION.map((item) => {
+ let temp = Object.assign({}, item);
+ if (temp.type === videoQuality) {
+ resolution = temp;
+ }
+ });
+ const constraints = {
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: this.sourceId,
- minWidth: 640,
- maxWidth: 1920,
- minHeight: 480,
- maxHeight: 1080,
+ minWidth: resolution.width,
+ maxWidth: resolution.width,
+ minHeight: resolution.height,
+ maxHeight: resolution.height,
},
},
- });
+ };
+
+ if (this.config.audioCapture) {
+ this.audioDevices = await this.getAudioSources();
+ if (this.audioDevices.length > 0) {
+ await this.setAudio(this.audioDevices);
+ }
+ }
+
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
stream.getVideoTracks()[0].applyConstraints({ frameRate: 30 });
+
this.handleStream(stream);
} catch (e) {
console.log(e);
@@ -788,6 +888,29 @@ export default {
console.log(error);
}
},
+ async getAudioSources() {
+ return await navigator.mediaDevices.enumerateDevices().then((devices) => {
+ const audioDevices = devices.filter(
+ (d) =>
+ d.kind === "audioinput" &&
+ d.deviceId != "communications" &&
+ d.deviceId != "default"
+ );
+ return audioDevices;
+ });
+ },
+ async setAudio(source) {
+ const audioStream = await navigator.mediaDevices.getUserMedia({
+ audio: {
+ deviceId: source.deviceId,
+ autoGainControl: false,
+ latency: 0.0,
+ },
+ });
+ let audioIn_01 = audioContext.createMediaStreamSource(audioStream);
+ audioIn_01.connect(dest);
+ return audioIn_01;
+ },
async startRecordAudio() {
this.setAudioSource = async () => {
try {
@@ -829,21 +952,23 @@ export default {
const blob = new Blob(recordedChunks, {
type: "audio/mpeg-3",
});
+
const buffer = await blob.arrayBuffer();
- const fileName = dayjs().format("YYYY-MM-DD_HH-mm-ss-ms") + ".mp3";
+
if (window.ipc) {
await window.ipc
.invoke(IPC_HANDLERS.CAPTURE, {
- func: IPC_FUNCTIONS.CREATE_TEMP_USER_MEDIA,
- data: { buffer: buffer, fileName: fileName },
+ func: IPC_FUNCTIONS.CREATE_AUDIO,
+ data: { buffer: buffer },
})
- .then((filePath) => {
+ .then(({ fileName, filePath }) => {
const data = {
- sessionType: "audio",
+ sessionType: "Audio",
fileType: "audio",
fileName: fileName,
filePath: filePath,
time: this.timer,
+ poster: "",
};
this.openAddWindow(data);
@@ -859,6 +984,18 @@ export default {
console.log("Error:", error);
};
+ // try {
+ // this.audioDevices = await this.getAudioSources();
+ // if (!this.audioDevices.length) {
+ // this.audioErrorDialog = true;
+ // return;
+ // }
+ // const stream = this.setAudio(this.audioDevices);
+ // this.handleStream(stream);
+ // } catch (e) {
+ // console.log(e);
+ // }
+
await navigator.mediaDevices.enumerateDevices().then((devices) => {
this.audioDevices = devices.filter(
(d) =>
@@ -888,7 +1025,7 @@ export default {
data: { width: 700, height: 800, data: data },
});
},
- async addNote(comment) {
+ async addNote(value) {
const date = dayjs().format("MM/DD/YYYY HH:mm:ss");
const fileName = dayjs().format("YYYY-MM-DD_HH-mm-ss-ms") + ".txt";
@@ -897,16 +1034,16 @@ export default {
await window.ipc
.invoke(IPC_HANDLERS.CAPTURE, {
func: IPC_FUNCTIONS.SAVE_NOTE,
- data: { fileName: fileName, comment: comment },
+ data: { fileName: fileName, comment: value },
})
.then((filePath) => {
let newItem = {
id: Date.now(),
- sessionType: "note",
+ sessionType: "Note",
fileType: "text",
fileName: fileName,
filePath: filePath,
- comment: comment,
+ comment: value,
time: this.timer,
createdAt: date,
};
@@ -916,20 +1053,55 @@ export default {
this.noteDialog = false;
},
+ async addSummary(value) {
+ const date = dayjs().format("MM/DD/YYYY HH:mm:ss");
+
+ const data = {
+ id: Date.now(),
+ sessionType: "Summary",
+ comment: value,
+ time: this.timer,
+ createdAt: date,
+ };
+
+ this.$emit("add-item", data);
+ this.summaryDialog = false;
+ this.endSession();
+ },
+ async removeSummary() {
+ let summary = [];
+ this.items.map((item) => {
+ if (item.sessionType === "Summary") {
+ summary.push(item.id);
+ }
+ });
+ if (window.ipc) {
+ await window.ipc.invoke(IPC_HANDLERS.DATABASE, {
+ func: IPC_FUNCTIONS.DELETE_ITEMS,
+ data: summary,
+ });
+ }
+ },
mindMap() {
const data = {
- sessionType: "mindmap",
+ sessionType: "Mindmap",
fileType: "mindmap",
fileName: "",
filePath: "",
content: {
- nodes: MAP_NODES,
- connections: MAP_CONNECTIONS,
+ nodes: DEFAULT_MAP_NODES,
+ connections: DEFAULT_MAP_CONNECTIONS,
},
time: this.timer,
};
this.openAddWindow(data);
},
+ async minimize() {
+ await window.ipc.invoke(IPC_HANDLERS.CAPTURE, {
+ func: IPC_FUNCTIONS.OPEN_MINIMIZE_WINDOW,
+ data: { width: 700, height: 800 },
+ });
+ },
async deleteItems() {
if (window.ipc) {
await window.ipc.invoke(IPC_HANDLERS.DATABASE, {
@@ -973,6 +1145,7 @@ export default {
},
discardSession() {
this.$store.commit("resetState");
+ this.changeSessionStatus(SESSION_STATUSES.PENDING);
clearInterval(this.interval);
this.$router.push({ path: "/" });
},
@@ -991,6 +1164,12 @@ export default {
return currentDateTime;
},
+ changeSessionStatus(status) {
+ window.ipc.invoke(IPC_HANDLERS.MENU, {
+ func: IPC_FUNCTIONS.CHANGE_MENUITEM_STATUS,
+ data: { sessionStatus: status },
+ });
+ },
},
};
diff --git a/src/components/FileWrapper.vue b/src/components/FileWrapper.vue
index 14db5b82..6e3c6555 100644
--- a/src/components/FileWrapper.vue
+++ b/src/components/FileWrapper.vue
@@ -27,7 +27,8 @@ export default {
},
triggerSave: function (newValue) {
if (newValue) {
- this.$root.$emit("save-data", this.sessionItem);
+ this.$root.$emit("update-session", this.sessionItem);
+ this.$root.$emit("save-data");
}
},
},
diff --git a/src/components/ImageEditor.vue b/src/components/ImageEditor.vue
index 09e9ce30..350320fe 100644
--- a/src/components/ImageEditor.vue
+++ b/src/components/ImageEditor.vue
@@ -3,39 +3,20 @@
class="d-flex flex-column"
style="width: 100%; height: 100%; row-gap: 10px"
>
-
-
-
- Cancel
-
- handleImage(false)"
- >
- Apply
-
-
+
+
diff --git a/src/components/authentication/Signup1Wrapper.vue b/src/components/authentication/Signup1Wrapper.vue
new file mode 100644
index 00000000..6d797e33
--- /dev/null
+++ b/src/components/authentication/Signup1Wrapper.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+ Sign up to test apps
+
+
+ Sign UP
+
+
+ Sign In
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/authentication/Signup2Wrapper.vue b/src/components/authentication/Signup2Wrapper.vue
new file mode 100644
index 00000000..62dfbf79
--- /dev/null
+++ b/src/components/authentication/Signup2Wrapper.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+ Sign up with YATT
+
+
+
+ Sign up with JIRA
+
+
+
+ Sign up with TestRail
+
+
+
+ Sign up with qTest
+
+
+
+ Sign up with PractiTest
+
+
+
+
+
+
+ Skip Sign Up
+
+
+
+
+ Sign Up
+
+
+
+
+
+
+ Or
+
+
+
+
+
+ Already have an account?
+
+ Sign in
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/authentication/Signup3Wrapper.vue b/src/components/authentication/Signup3Wrapper.vue
new file mode 100644
index 00000000..ef4e872b
--- /dev/null
+++ b/src/components/authentication/Signup3Wrapper.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+ Start Test As
+
+
+
+
+
+
+
+
+ Your Email
+
+
+
+
+
+ Enter Service URL
+
+
+
+
+
+
+ Sign Up
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/dialogs/EndSessionDialog.vue b/src/components/dialogs/EndSessionDialog.vue
index d1759d72..625b4149 100644
--- a/src/components/dialogs/EndSessionDialog.vue
+++ b/src/components/dialogs/EndSessionDialog.vue
@@ -3,7 +3,7 @@
@@ -11,7 +11,7 @@
End Session
@@ -35,6 +35,11 @@ export default {
default: () => {},
},
},
+ computed: {
+ tasks() {
+ return this.postSessionData ? this.postSessionData.tasks : [];
+ },
+ },
data() {
return {
showTaskError: false,
diff --git a/src/components/dialogs/NodeEditDialog.vue b/src/components/dialogs/NodeEditDialog.vue
index c98d34f6..e068eaa2 100644
--- a/src/components/dialogs/NodeEditDialog.vue
+++ b/src/components/dialogs/NodeEditDialog.vue
@@ -8,7 +8,7 @@
@@ -48,7 +48,7 @@ export default {
return {
text: "",
valid: false,
- textRules: [(v) => !!v || "Title is required"],
+ textRules: [(v) => !!v || "Node title is required"],
};
},
methods: {
diff --git a/src/components/dialogs/NoteDialog.vue b/src/components/dialogs/NoteDialog.vue
index bfca1f8d..8cb367a9 100644
--- a/src/components/dialogs/NoteDialog.vue
+++ b/src/components/dialogs/NoteDialog.vue
@@ -4,7 +4,7 @@
Take a Note
-
+
{},
+ },
+ },
+ watch: {
+ configItem: function (newValue) {
+ this.config = newValue;
+
+ // set comment type by config
+ if (this.config.commentType && this.config.commentType !== "") {
+ this.comment.type = this.config.commentType;
+ }
+
+ // set templates by config
+ this.config.templates.map((item) => {
+ let temp = Object.assign({}, item);
+ if (temp.type === "Note") {
+ this.comment.content = temp.precondition.content;
+ this.comment.text = temp.precondition.text;
+ }
+ });
+ },
+ },
data() {
return {
+ config: this.configItem,
comment: {
- type: "Comment",
+ type:
+ this.conifgItem &&
+ this.configItem.commentType &&
+ this.configItem.commentType !== ""
+ ? this.configItem.commentType
+ : "Comment",
content: "",
text: "",
tags: [],
},
- commentTypes: TEXT_TYPES,
+ commentTypes: TEXT_TYPES.filter((item) => item !== "Summary"),
tag: "",
tags: [],
};
@@ -116,7 +146,7 @@ export default {
this.$root.$emit("close-notedialog");
},
handleSave() {
- this.$emit("submit-note", this.comment);
+ this.$emit("submit-comment", this.comment);
},
handleClear() {
this.comment.type = "Comment";
diff --git a/src/components/dialogs/SummaryDialog.vue b/src/components/dialogs/SummaryDialog.vue
new file mode 100644
index 00000000..b5753feb
--- /dev/null
+++ b/src/components/dialogs/SummaryDialog.vue
@@ -0,0 +1,145 @@
+
+
+
+
+ Take a Summary
+
+
+
+
+
+
+
+
+
+ Comment Type
+
+
+
+
+ Clear
+
+
+
+
+
+
+
+
+
+ Discard
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/dialogs/__tests__/EndSessionDialog.spec.js b/src/components/dialogs/__tests__/EndSessionDialog.spec.js
new file mode 100644
index 00000000..66c4fda1
--- /dev/null
+++ b/src/components/dialogs/__tests__/EndSessionDialog.spec.js
@@ -0,0 +1,73 @@
+import Vuetify from "vuetify";
+
+import CheckTaskWrapper from "../../CheckTaskWrapper.vue";
+import EndSessionDialog from "../EndSessionDialog.vue";
+
+import { mount, createLocalVue } from "@vue/test-utils";
+
+let vuetify;
+let wrapper;
+let localVue;
+
+describe("EndSessionDialog.vue", () => {
+ beforeEach(() => {
+ const rootDiv = document.createElement("div");
+ rootDiv.id = "root";
+ document.body.appendChild(rootDiv);
+
+ localVue = createLocalVue();
+ vuetify = new Vuetify();
+
+ const App = localVue.component("App", {
+ components: { EndSessionDialog },
+ data() {
+ return {
+ dialog: false,
+ showTaskError: false,
+ };
+ },
+ template: `
+
+
+
+ `,
+ });
+
+ wrapper = mount(App, {
+ localVue,
+ vuetify,
+ attachTo: "#root",
+ });
+ });
+
+ test("render a dialog", async () => {
+ wrapper.setData({
+ dialog: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findComponent(CheckTaskWrapper).exists()).toBe(true);
+ expect(wrapper.find(".btn-end").exists()).toBe(true);
+ });
+
+ test('trigger the click event of "End Session" button', async () => {
+ wrapper.setData({
+ dialog: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const button = wrapper.find(".btn-end");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+ });
+});
diff --git a/src/components/dialogs/__tests__/NodeEditDialog.spec.js b/src/components/dialogs/__tests__/NodeEditDialog.spec.js
new file mode 100644
index 00000000..926165ce
--- /dev/null
+++ b/src/components/dialogs/__tests__/NodeEditDialog.spec.js
@@ -0,0 +1,86 @@
+import Vuetify from "vuetify";
+import LogoWrapper from "../../LogoWrapper.vue";
+import NodeEditDialog from "../NodeEditDialog.vue";
+
+import { mount, createLocalVue } from "@vue/test-utils";
+
+let vuetify;
+let wrapper;
+let localVue;
+
+describe("NodeEditDialog.vue", () => {
+ beforeEach(() => {
+ const rootDiv = document.createElement("div");
+ rootDiv.id = "root";
+ document.body.appendChild(rootDiv);
+
+ localVue = createLocalVue();
+ vuetify = new Vuetify();
+
+ const App = localVue.component("App", {
+ components: { NodeEditDialog },
+ data() {
+ return {
+ dialog: false,
+ };
+ },
+ template: `
+
+
+
+ `,
+ });
+
+ wrapper = mount(App, {
+ localVue,
+ vuetify,
+ attachTo: "#root",
+ });
+ });
+
+ test("render a dialog", async () => {
+ wrapper.setData({ dialog: true });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findComponent(LogoWrapper).exists()).toBe(true);
+ expect(wrapper.find("form").exists()).toBe(true);
+ expect(wrapper.find("form input").exists()).toBe(true);
+
+ expect(wrapper.findAll("button").length).toBe(2);
+ expect(wrapper.find("button:first-child").text()).toContain("Save");
+ expect(wrapper.find("button:last-child").text()).toContain("Cancel");
+ });
+
+ test('trigger the click event of "Save" button', async () => {
+ wrapper.setData({ dialog: true });
+
+ await wrapper.vm.$nextTick();
+
+ const button = wrapper.find("button:first-child");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+ });
+
+ test('trigger the click event of "Cancel" button', async () => {
+ wrapper.setData({ dialog: true });
+
+ await wrapper.vm.$nextTick();
+
+ const button = wrapper.find("button:last-child");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+ });
+});
diff --git a/src/components/dialogs/__tests__/NoteDialog.spec.js b/src/components/dialogs/__tests__/NoteDialog.spec.js
index 4aabecf2..dd5426ed 100644
--- a/src/components/dialogs/__tests__/NoteDialog.spec.js
+++ b/src/components/dialogs/__tests__/NoteDialog.spec.js
@@ -20,6 +20,17 @@ describe("NoteDialog.vue", () => {
const App = localVue.component("App", {
components: { NoteDialog },
+ propsData: {
+ configItem: {
+ commentType: "",
+ templates: [
+ {
+ precondition: { comment: "", text: "" },
+ type: "Note",
+ },
+ ],
+ },
+ },
data() {
return {
dialog: false,
diff --git a/src/components/settings/ConfigCheckListTab.vue b/src/components/settings/ConfigCheckListTab.vue
index a50f1001..536303dc 100644
--- a/src/components/settings/ConfigCheckListTab.vue
+++ b/src/components/settings/ConfigCheckListTab.vue
@@ -1,6 +1,9 @@
Session Checklists
+
+ Use pre and post testing checklists to streamline your testing process
+
@@ -12,7 +15,7 @@
-
+
-
+
-
+
EXTERNAL CONNECTIONS
Connect to a TestRail instance
Connect to a JIRA instance
-
+
Use the app locally only
@@ -21,12 +21,12 @@
inset
hide-details
dense
- class="mt-0 pt-0"
+ class="mt-0 pt-0 switch-control"
>
-
+
diff --git a/src/components/settings/GeneralTab.vue b/src/components/settings/GeneralTab.vue
index 0c7a064b..f1896466 100644
--- a/src/components/settings/GeneralTab.vue
+++ b/src/components/settings/GeneralTab.vue
@@ -1,12 +1,12 @@
-
+
Apperance
-
- Screenshots
-
-
-
Select the default annotation color
-
- This will change the default color of the image annotation tools.
-
-
-
-
-
-
-
-
+
Screen Recording
-
-
-
- Notes
-
-
-
Select Default note/comment type
-
-
-
-
-
- Select Default note/comment type
-
-
-
- Screen Recording
- Audio on video recording
Audio on screen capture
@@ -83,28 +28,23 @@
inset
hide-details
dense
- class="mt-0 pt-0"
+ class="mt-0 pt-0 switch-control"
@change="handleConfig"
>
-
-
- Video capture quality
+
+ Video capture quality
-
High quality Video
-
- This will change the default color of the image annotation
- tools.
-
+
High quality Video
@@ -112,11 +52,7 @@
-
Standard quality video
-
- This will change the default color of the image annotation
- tools.
-
+
Standard quality video
@@ -124,11 +60,7 @@
-
Low quality video
-
- This will change the default color of the image annotation
- tools.
-
+
Low quality video
@@ -136,6 +68,40 @@
+
+ Screenshots
+
+
+
Select the default annotation color
+
+ This will change the default color of the image annotation tools.
+
+
+
+
+
+
+
+
+ Notes
+ Select Default note/comment type
+
+
@@ -168,7 +134,7 @@ export default {
content: "",
text: "",
},
- commentTypes: TEXT_TYPES,
+ commentTypes: TEXT_TYPES.filter((item) => item !== "Summary"),
};
},
methods: {
diff --git a/src/components/settings/ReportsTab.vue b/src/components/settings/ReportsTab.vue
new file mode 100644
index 00000000..e754123c
--- /dev/null
+++ b/src/components/settings/ReportsTab.vue
@@ -0,0 +1,85 @@
+
+
+
+
+ Session Summary
+
+
+
Mandatory session summary
+
+ Make a written summary mandatory upon completing a session.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/settings/TemplateTab.vue b/src/components/settings/TemplateTab.vue
index bb143fd1..4b2bac2f 100644
--- a/src/components/settings/TemplateTab.vue
+++ b/src/components/settings/TemplateTab.vue
@@ -1,9 +1,14 @@
+ Note Templates
+
+ Improve your note taking and evidence labeling with pre-populated
+ templates
+
+
- Prefill Text for Screenshots
-
+
-
+
-
+
+
-
+
+
+
+
mdi-play
+
mdi-play-circle
+
mdi-file
+
+
+
+
+
+
+
+ mdi-clock-outline
+ {{ calculateTime(item.time) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ mdi-clock-outline
+ {{ calculateTime(item.time) }}
+
+
+
+
+
+
@@ -202,8 +307,7 @@ import {
VIcon,
VDivider,
} from "vuetify/lib/components";
-// import LogoWrapper from "../components/LogoWrapper.vue";
-import { IPC_HANDLERS, IPC_FUNCTIONS } from "../modules/constants";
+import { IPC_HANDLERS, IPC_FUNCTIONS, TEXT_TYPES } from "../modules/constants";
export default {
name: "PrintView",
@@ -215,7 +319,6 @@ export default {
VTimelineItem,
VIcon,
VDivider,
- // LogoWrapper,
},
data() {
return {
@@ -253,6 +356,39 @@ export default {
return hours + ":" + minutes + ":" + seconds;
},
+ commentTypes() {
+ let data = [];
+ const commentTypes = TEXT_TYPES.filter((item) => item !== "Summary");
+ commentTypes.map((type) => {
+ let temp,
+ i = 0;
+ this.items.map((item) => {
+ if (type === item.comment.type && item.comment.text) {
+ i++;
+ }
+ });
+ if (i > 0) {
+ temp = {
+ title: type,
+ count: i,
+ };
+ data.push(temp);
+ }
+ });
+ console.log(commentTypes);
+ console.log("result:", data);
+ return data;
+ },
+ summary() {
+ let summary = "";
+ this.items.map((item) => {
+ if (item.comment.type === "Summary" && item.comment.text) {
+ summary = item.comment.text;
+ }
+ });
+ console.log("summary:", summary);
+ return summary;
+ },
},
methods: {
async initialize() {
@@ -306,6 +442,31 @@ export default {
.content {
padding: 20px 0;
}
+.summary {
+ display: flex;
+ flex-direction: column;
+ row-gap: 5px;
+ justify-content: flex-start;
+}
+.summary .summary-content {
+ display: flex;
+ flex-direction: row;
+ column-gap: 5px;
+}
+.summary .summary-content span {
+ font-style: normal;
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 16px;
+ color: #6b7280;
+}
+.summary .summary-text {
+ font-style: normal;
+ font-weight: 500;
+ font-size: 14px;
+ line-height: 20px;
+ color: #111827;
+}
.timeline-item {
height: auto;
display: flex;
@@ -314,7 +475,7 @@ export default {
.timeline-item .v-timeline-item__body {
max-width: calc(100% - 40px);
}
-.screen-wrapper {
+.image-wrapper {
position: relative;
display: flex;
background: #fff;
@@ -350,6 +511,13 @@ export default {
border-radius: 6px;
border: 1px solid #d1d5db;
}
+.comment-wrapper {
+ display: flex;
+ background: #fff;
+}
+.comment-wrapper p {
+ margin-bottom: 0 !important;
+}
.note-wrapper {
display: flex;
justify-content: flex-start;
@@ -389,7 +557,12 @@ export default {
line-height: 16px;
color: #6b7280;
}
-
+.tags-wrapper .tag {
+ margin-right: 5px;
+}
+.tags-wrapper .tag:last-child {
+ margin-right: 0;
+}
.detail-title {
font-style: normal;
font-weight: 600;
diff --git a/src/views/ResultView.vue b/src/views/ResultView.vue
index a0a88f81..2de3b635 100644
--- a/src/views/ResultView.vue
+++ b/src/views/ResultView.vue
@@ -70,7 +70,11 @@
/>
@@ -104,16 +108,36 @@ export default {
data() {
return {
items: [],
+ config: {},
activeSession: {},
- commentTypes: TEXT_TYPES,
+ commentTypes: TEXT_TYPES.filter((item) => item !== "Summary"),
type: "Comment",
search: "",
selected: [],
autoSaveEvent: true,
+ postsession: {
+ tasks: [],
+ },
};
},
created() {
this.fetchItems();
+ this.getConfig();
+ },
+ mounted() {
+ this.$root.$on("submit-search", this.handleSearch);
+ this.$root.$on("update-selected", this.updateSelected);
+ this.$root.$on("save-data", this.updateActiveSession);
+ this.$root.$on("update-session", this.updateActiveSession);
+
+ if (!window.ipc) return;
+
+ window.ipc.on("DATA_CHANGE", () => {
+ this.fetchItems();
+ });
+ window.ipc.on("CONFIG_CHANGE", () => {
+ this.getConfig();
+ });
},
computed: {
searchItems() {
@@ -129,14 +153,6 @@ export default {
return tempItems;
},
},
- mounted() {
- this.$root.$on("submit-search", this.handleSearch);
- this.$root.$on("update-selected", this.updateSelected);
- this.$root.$on("save-data", this.updateActiveSession);
- window.ipc.on("DATA_CHANGE", () => {
- this.fetchItems();
- });
- },
methods: {
fetchItems() {
if (!window.ipc) return;
@@ -147,19 +163,30 @@ export default {
this.items = result;
});
},
+ async getConfig() {
+ if (!window.ipc) return;
+
+ window.ipc
+ .invoke(IPC_HANDLERS.DATABASE, {
+ func: IPC_FUNCTIONS.GET_CONFIG,
+ })
+ .then((result) => {
+ this.config = result;
+ });
+ },
handleSearch(val) {
this.search = val;
},
handleComment({ content, text }) {
this.activeSession.comment.content = content;
this.activeSession.comment.text = text;
- this.updateItems();
+ this.saveData();
},
handleCommentType(val) {
this.activeSession.commentType = val;
- this.updateItems();
+ this.saveData();
},
- updateItems() {
+ saveData() {
this.items = this.items.map((item) => {
let temp = Object.assign({}, item);
if (temp.id === this.activeSession.id) {
@@ -167,6 +194,9 @@ export default {
}
return temp;
});
+
+ if (!window.ipc) return;
+
window.ipc.invoke(IPC_HANDLERS.DATABASE, {
func: IPC_FUNCTIONS.UPDATE_ITEMS,
data: this.items,
@@ -175,14 +205,14 @@ export default {
handleClear() {
this.activeSession.comment = "";
this.activeSession.commentType = "Comment";
- this.updateItems();
+ this.saveData();
},
updateSelected(value) {
this.selected = value;
},
updateActiveSession(value) {
this.activeSession = value;
- this.updateItems();
+ this.saveData();
},
},
};
diff --git a/src/views/SettingView.vue b/src/views/SettingView.vue
index 36e55310..36190953 100644
--- a/src/views/SettingView.vue
+++ b/src/views/SettingView.vue
@@ -47,7 +47,8 @@ export default {
{ id: 2, name: "Connections", route: `/settings/connections` },
{ id: 3, name: "Templates", route: `/settings/template` },
{ id: 4, name: "Checklists", route: `/settings/checklist` },
- // { id: 5, name: "Support", route: `/settings/support` },
+ { id: 5, name: "Reports", route: `/settings/reports` },
+ // { id: 6, name: "Support", route: `/settings/support` },
],
config: {},
};
@@ -58,13 +59,20 @@ export default {
mounted() {},
methods: {
async getConfig() {
- const { config } = await window.ipc.invoke(IPC_HANDLERS.DATABASE, {
- func: IPC_FUNCTIONS.GET_CONFIG,
- });
- this.config = config;
+ if (!window.ipc) return;
+
+ window.ipc
+ .invoke(IPC_HANDLERS.DATABASE, {
+ func: IPC_FUNCTIONS.GET_CONFIG,
+ })
+ .then((result) => {
+ this.config = result;
+ });
},
updateConfig(value) {
this.config = value;
+ if (!window.ipc) return;
+
window.ipc.invoke(IPC_HANDLERS.DATABASE, {
func: IPC_FUNCTIONS.UPDATE_CONFIG,
data: this.config,
diff --git a/src/views/__tests__/AddSession.spec.js b/src/views/__tests__/AddSession.spec.js
new file mode 100644
index 00000000..4b040e70
--- /dev/null
+++ b/src/views/__tests__/AddSession.spec.js
@@ -0,0 +1,149 @@
+import Vuetify from "vuetify";
+import AddSession from "../AddSession";
+import ReviewWrapper from "../../components/ReviewWrapper";
+import TextEditor from "../../components/TextEditor";
+
+import { mount } from "@vue/test-utils";
+
+const vuetify = new Vuetify();
+
+describe("AddSession.vue", () => {
+ test("loads editor view", () => {
+ const wrapper = mount(AddSession, {
+ data() {
+ return {
+ item: {
+ fileType: "",
+ comment: {
+ type: "",
+ },
+ },
+ config: {},
+ comment: {
+ type: "",
+ content: "",
+ text: "",
+ },
+ };
+ },
+ stubs: ["router-link"],
+ vuetify,
+ });
+
+ expect(
+ wrapper
+ .find(".content-bottom .comment-type .subtitle-2.label-text")
+ .text()
+ ).toContain("Comment Type");
+ expect(wrapper.findComponent(ReviewWrapper).exists()).toBe(true);
+ expect(wrapper.findComponent(TextEditor).exists()).toBe(true);
+ expect(wrapper.find(".footer button:nth-child(1)").text()).toContain(
+ "Clear"
+ );
+ expect(wrapper.find(".footer > div button:nth-child(1)").text()).toContain(
+ "Discard"
+ );
+ expect(wrapper.find(".footer > div button:nth-child(2)").text()).toContain(
+ "Save"
+ );
+ });
+
+ test('triggers a click on "Discard" button', async () => {
+ const wrapper = mount(AddSession, {
+ data() {
+ return {
+ item: {
+ fileType: "",
+ comment: {
+ type: "",
+ },
+ },
+ config: {},
+ comment: {
+ type: "",
+ content: "",
+ text: "",
+ },
+ processing: false,
+ };
+ },
+ stubs: ["router-link"],
+ vuetify,
+ });
+
+ const button = wrapper.find(".footer > div button:nth-child(1)");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+ });
+
+ test('triggers a click on "Save" button', async () => {
+ const wrapper = mount(AddSession, {
+ data() {
+ return {
+ item: {
+ fileType: "",
+ comment: {
+ type: "",
+ },
+ },
+ config: {},
+ comment: {
+ type: "",
+ content: "",
+ text: "",
+ },
+ processing: false,
+ };
+ },
+ stubs: ["router-link"],
+ vuetify,
+ });
+
+ const button = wrapper.find(".footer > div button:nth-child(2)");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+ });
+
+ it('trigger the click event of "Clear" button', async () => {
+ const wrapper = mount(AddSession, {
+ data() {
+ return {
+ item: {
+ fileType: "",
+ comment: {
+ type: "",
+ },
+ },
+ config: {},
+ comment: {
+ type: "",
+ content: "",
+ text: "",
+ },
+ processing: false,
+ };
+ },
+ stubs: ["router-link"],
+ vuetify,
+ });
+
+ const button = wrapper.find(".footer button:nth-child(1)");
+ const event = jest.fn();
+
+ button.vm.$on("click", event);
+ button.trigger("click");
+
+ expect(event).toHaveBeenCalled();
+
+ expect(wrapper.vm.comment.text).toBe("");
+ expect(wrapper.vm.comment.type).toBe("Comment");
+ });
+});
diff --git a/src/views/__tests__/EditView.spec.js b/src/views/__tests__/EditSession.spec.js
similarity index 91%
rename from src/views/__tests__/EditView.spec.js
rename to src/views/__tests__/EditSession.spec.js
index 058ece5d..d9e58fcd 100644
--- a/src/views/__tests__/EditView.spec.js
+++ b/src/views/__tests__/EditSession.spec.js
@@ -1,5 +1,5 @@
import Vuetify from "vuetify";
-import EditView from "../EditView";
+import EditSession from "../EditSession";
import ReviewWrapper from "../../components/ReviewWrapper";
import TextEditor from "../../components/TextEditor";
@@ -7,9 +7,9 @@ import { mount } from "@vue/test-utils";
const vuetify = new Vuetify();
-describe("EditView.vue", () => {
+describe("EditSession.vue", () => {
test("loads editor view", () => {
- const wrapper = mount(EditView, {
+ const wrapper = mount(EditSession, {
data() {
return {
item: {
@@ -43,7 +43,7 @@ describe("EditView.vue", () => {
});
test('triggers a click on "Discard" button', async () => {
- const wrapper = mount(EditView, {
+ const wrapper = mount(EditSession, {
data() {
return {
item: {
@@ -68,7 +68,7 @@ describe("EditView.vue", () => {
});
test('triggers a click on "Save" button', async () => {
- const wrapper = mount(EditView, {
+ const wrapper = mount(EditSession, {
data() {
return {
item: {
@@ -93,7 +93,7 @@ describe("EditView.vue", () => {
});
it('Click on "Clear" button calls "handleClear" method', async () => {
- const wrapper = mount(EditView, {
+ const wrapper = mount(EditSession, {
data() {
return {
item: {
diff --git a/src/views/__tests__/EditorView.spec.js b/src/views/__tests__/EditorView.spec.js
deleted file mode 100644
index 98595382..00000000
--- a/src/views/__tests__/EditorView.spec.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Vuetify from "vuetify";
-import EditorView from "../EditorView";
-import ReviewWrapper from "../../components/ReviewWrapper";
-import TextEditor from "../../components/TextEditor";
-
-import { mount } from "@vue/test-utils";
-
-const vuetify = new Vuetify();
-
-describe("EditorView.vue", () => {
- test("loads editor view", () => {
- const wrapper = mount(EditorView, {
- stubs: ["router-link"],
- vuetify,
- });
-
- expect(
- wrapper
- .find(".content-bottom .comment-type .subtitle-2.label-text")
- .text()
- ).toContain("Comment Type");
- expect(wrapper.findComponent(ReviewWrapper).exists()).toBe(true);
- expect(wrapper.findComponent(TextEditor).exists()).toBe(true);
- expect(wrapper.find(".footer button:nth-child(1)").text()).toContain(
- "Clear"
- );
- expect(wrapper.find(".footer > div button:nth-child(1)").text()).toContain(
- "Discard"
- );
- expect(wrapper.find(".footer > div button:nth-child(2)").text()).toContain(
- "Save"
- );
- });
-
- test('triggers a click on "Discard" button', async () => {
- const wrapper = mount(EditorView, {
- stubs: ["router-link"],
- vuetify,
- });
-
- const button = wrapper.find(".footer > div button:nth-child(1)");
- const event = jest.fn();
-
- button.vm.$on("click", event);
- button.trigger("click");
-
- expect(event).toHaveBeenCalled();
- });
-
- test('triggers a click on "Save" button', async () => {
- const wrapper = mount(EditorView, {
- stubs: ["router-link"],
- vuetify,
- });
-
- const button = wrapper.find(".footer > div button:nth-child(1)");
- const event = jest.fn();
-
- button.vm.$on("click", event);
- button.trigger("click");
-
- expect(event).toHaveBeenCalled();
- });
-
- it('Click on "Clear" button calls "handleClear" method', async () => {
- const wrapper = mount(EditorView, {
- stubs: ["router-link"],
- vuetify,
- });
-
- await wrapper.find(".footer button:nth-child(1)").trigger("click");
-
- expect(wrapper.vm.comment.text).toBe("");
- expect(wrapper.vm.comment.type).toBe("Comment");
- });
-});
diff --git a/src/views/__tests__/ResultView.spec.js b/src/views/__tests__/ResultView.spec.js
index 5323ebe6..ee6b8118 100644
--- a/src/views/__tests__/ResultView.spec.js
+++ b/src/views/__tests__/ResultView.spec.js
@@ -35,7 +35,7 @@ describe("ResultView.vue", () => {
data() {
return {
items: [],
- activeItem: { comment: "" },
+ activeSession: { comment: "" },
commentTypes: TEXT_TYPES,
type: "Comment",
search: "",
@@ -64,7 +64,7 @@ describe("ResultView.vue", () => {
data() {
return {
items: [],
- activeItem: { comment: "" },
+ activeSession: { comment: "" },
commentTypes: TEXT_TYPES,
type: "Comment",
};
diff --git a/src/views/__tests__/SettingView.spec.js b/src/views/__tests__/SettingView.spec.js
new file mode 100644
index 00000000..0828f344
--- /dev/null
+++ b/src/views/__tests__/SettingView.spec.js
@@ -0,0 +1,34 @@
+import Vuetify from "vuetify";
+import VueRouter from "vue-router";
+
+import SettingView from "../SettingView.vue";
+
+import { mount, createLocalVue } from "@vue/test-utils";
+
+const vuetify = new Vuetify();
+
+const localVue = createLocalVue();
+localVue.use(VueRouter);
+
+const router = new VueRouter();
+
+describe("SettingView.vue", () => {
+ test("loadin a view", () => {
+ const wrapper = mount(SettingView, {
+ data() {
+ return {
+ activeTab: "/settings",
+ tabs: [{ id: 1, name: "General", route: `/settings` }],
+ config: {},
+ };
+ },
+ localVue,
+ router,
+ vuetify,
+ });
+
+ expect(wrapper.find(".settings-menu").exists()).toBe(true);
+ expect(wrapper.findAll(".v-tab").length).toBe(1);
+ expect(wrapper.findAll(".v-tab-item").length).toBe(0);
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index a7126979..21658bd4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1540,6 +1540,20 @@
dependencies:
type-detect "4.0.8"
+"@sinonjs/commons@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3"
+ integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^7.0.4":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5"
+ integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
"@sinonjs/fake-timers@^8.0.1":
version "8.1.0"
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
@@ -1547,6 +1561,27 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
+"@sinonjs/fake-timers@^9.1.2":
+ version "9.1.2"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c"
+ integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
+"@sinonjs/samsam@^7.0.1":
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-7.0.1.tgz#5b5fa31c554636f78308439d220986b9523fc51f"
+ integrity sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==
+ dependencies:
+ "@sinonjs/commons" "^2.0.0"
+ lodash.get "^4.4.2"
+ type-detect "^4.0.8"
+
+"@sinonjs/text-encoding@^0.7.1":
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918"
+ integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==
+
"@soda/friendly-errors-webpack-plugin@^1.8.0":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz#4d4fbb1108993aaa362116247c3d18188a2c6c85"
@@ -1574,14 +1609,6 @@
resolved "https://registry.yarnpkg.com/@tinymce/tinymce-vue/-/tinymce-vue-3.2.8.tgz#014571b52ec8fa83665a7fa887bf65140207de71"
integrity sha512-jEz+NZ0g+FZFz273OEUWz9QkwPMyjc5AJYyxOgu51O1Y5UaJ/6IUddXTX6A20mwCleEv5ebwNYdalviafx4fnA==
-"@toast-ui/vue-image-editor@^3.15.2":
- version "3.15.2"
- resolved "https://registry.yarnpkg.com/@toast-ui/vue-image-editor/-/vue-image-editor-3.15.2.tgz#744391197be5aec1a044713949a250a86d54482b"
- integrity sha512-vOAvBjWMCtXCe4wDamyGLNcZiXcNGgfJR/4qy8J2hDwyk3b83a0CUKel4Q/VEGbdzF4sAeexPgX4pmiyvewdQA==
- dependencies:
- fabric "^4.2.0"
- tui-image-editor "^3.15.2"
-
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -4875,6 +4902,11 @@ diff-sequences@^27.5.1:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+diff@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
+ integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
+
diffie-hellman@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -7052,6 +7084,11 @@ is-wsl@^2.1.1, is-wsl@^2.2.0:
dependencies:
is-docker "^2.0.0"
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+ integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
+
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -7861,6 +7898,11 @@ jszip@^3.1.0:
readable-stream "~2.3.6"
setimmediate "^1.0.5"
+just-extend@^4.0.2:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744"
+ integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==
+
keyv@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
@@ -8013,6 +8055,11 @@ lodash.defaultsdeep@^4.6.1:
resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6"
integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
+
lodash.kebabcase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
@@ -8524,6 +8571,17 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+nise@^5.1.2:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.3.tgz#f46197e5f60ae9a96401b602bd9d8239b1ee8656"
+ integrity sha512-U597iWTTBBYIV72986jyU382/MMZ70ApWcRmkoF1AZ75bpqOtI3Gugv/6+0jLgoDOabmcSwYBkSSAWIp1eA5cg==
+ dependencies:
+ "@sinonjs/commons" "^2.0.0"
+ "@sinonjs/fake-timers" "^7.0.4"
+ "@sinonjs/text-encoding" "^0.7.1"
+ just-extend "^4.0.2"
+ path-to-regexp "^1.7.0"
+
no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
@@ -9077,6 +9135,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+path-to-regexp@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
+ integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+ dependencies:
+ isarray "0.0.1"
+
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -10393,6 +10458,18 @@ simple-update-notifier@^1.0.7:
dependencies:
semver "~7.0.0"
+sinon@^15.0.0:
+ version "15.0.0"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-15.0.0.tgz#651a641b45c0a57aabc8275343c7108cffc9c062"
+ integrity sha512-pV97G1GbslaSJoSdy2F2z8uh5F+uPGp3ddOzA4JsBOUBLEQRz2OAqlKGRFTSh2KiqUCmHkzyAeu7R4x1Hx0wwg==
+ dependencies:
+ "@sinonjs/commons" "^2.0.0"
+ "@sinonjs/fake-timers" "^9.1.2"
+ "@sinonjs/samsam" "^7.0.1"
+ diff "^5.0.0"
+ nise "^5.1.2"
+ supports-color "^7.2.0"
+
sirv@^1.0.7:
version "1.0.19"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49"
@@ -10851,7 +10928,7 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"
-supports-color@^7.0.0, supports-color@^7.1.0:
+supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
@@ -11244,7 +11321,7 @@ tui-color-picker@^2.2.6:
resolved "https://registry.yarnpkg.com/tui-color-picker/-/tui-color-picker-2.2.8.tgz#8e140ab04066dbdb2353c4a1f434ad7d8d7b0d73"
integrity sha512-q5sE9NQ5NR9lYpilYjcI7Sdv0KCogo+W8fZY+AYTj/HYg+9fscYy3UuJ6UQiV1bF+ARCLwFRWC8UcOt9kuUctQ==
-tui-image-editor@^3.15.2:
+tui-image-editor@^3.15.3:
version "3.15.3"
resolved "https://registry.yarnpkg.com/tui-image-editor/-/tui-image-editor-3.15.3.tgz#b016c53de5ed11c0ed4a91604a868e7964d1b431"
integrity sha512-7B5YUxe2eSSh+8YrlREmjqkgeFFKrVkdy0D/G0dWCJIQ2WLPQ/Bkm02WXQeWJiFPzgvargZjn7eAe80p3qBHPQ==
@@ -11284,7 +11361,7 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"
-type-detect@4.0.8:
+type-detect@4.0.8, type-detect@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==