/tests/mocks.js"],
16 | };
17 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/public/drag-drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/public/drag-drop.png
--------------------------------------------------------------------------------
/public/icon/checkbox-off.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icon/checkbox-on.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/icon/gear.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/icon/indeterminate.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | <%= htmlWebpackPlugin.options.title %>
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/public/logo.png
--------------------------------------------------------------------------------
/public/tiptap/bold.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/tiptap/italic.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/tiptap/link.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/tiptap/list-number.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/tiptap/list.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/tiptap/quotes.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/public/tiptap/underline.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | /dist
--------------------------------------------------------------------------------
/server/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/server/images/favicon.ico
--------------------------------------------------------------------------------
/server/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/server/images/logo.png
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pinata-oauth-backend",
3 | "version": "0.1.0",
4 | "description": "Express backend for Pinata OAuth",
5 | "main": "server.js",
6 | "scripts": {
7 | "server": "node server.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [
11 | "node.js",
12 | "express",
13 | "oauth2"
14 | ],
15 | "author": "",
16 | "license": "ISC",
17 | "dependencies": {
18 | "axios": "^1.3.4",
19 | "body-parser": "^1.20.1",
20 | "cors": "^2.8.5",
21 | "express": "^4.18.2",
22 | "open": "^8.4.0",
23 | "path": "^0.12.7"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const express = require("express");
3 | const bodyParser = require("body-parser");
4 | const cors = require("cors");
5 | const path = require("path");
6 |
7 | const app = express();
8 | const port = process.env.VUE_APP_SERVER_PORT || 64064;
9 |
10 | const corsOptions = {
11 | origin: `http://localhost:${port}`,
12 | };
13 |
14 | app.use(cors(corsOptions));
15 |
16 | // parse requests of content-type - application/json
17 | app.use(bodyParser.json());
18 |
19 | // parse requests of content-type - application/x-www-form-urlencoded
20 | app.use(bodyParser.urlencoded({ extended: true }));
21 |
22 | // path
23 | app.use(express.static(path.join(__dirname, "images")));
24 |
25 | app.disable("x-powered-by");
26 |
27 | // modules
28 | require("./modules/JiraUtility")(app);
29 |
30 | try {
31 | app.listen(port, () => {
32 | console.log(`OAuth redirect server running at http://localhost:${port}`);
33 | });
34 | } catch (err) {
35 | console.log(err);
36 | }
37 |
--------------------------------------------------------------------------------
/src/assets/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/avatar.png
--------------------------------------------------------------------------------
/src/assets/icon/align.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/bell.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/bold.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/bug-gray.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/bug.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/bullet.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/camera-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/camera-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/camera.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/compass.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/connect-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/connect-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/connect.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/bug.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/camera.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/evidence.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/file-search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/microphone.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/mindmap.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/notification.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/control-panel-icon/video.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/cross.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/diamond.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/double-arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/download-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/download.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/downward-triangle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/drag-drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/drag-drop.png
--------------------------------------------------------------------------------
/src/assets/icon/edit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/ellipse.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/error.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/expand.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/fill.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/highlight.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/jira.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/jira.png
--------------------------------------------------------------------------------
/src/assets/icon/link.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/list.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-slash-solid-gray.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-slash-solid-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-slash-solid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-solid-gray.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-solid-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/microphone-solid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/nofill.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/pause-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/pause-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/pause.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/pencil-gray.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/pencil-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/pencil-white1.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/pencil.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/pinata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/pinata.png
--------------------------------------------------------------------------------
/src/assets/icon/play-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/play-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/play.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/plus-integration.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/icon/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/plus.png
--------------------------------------------------------------------------------
/src/assets/icon/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
26 |
--------------------------------------------------------------------------------
/src/assets/icon/practitest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/practitest.png
--------------------------------------------------------------------------------
/src/assets/icon/qtest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/qtest.png
--------------------------------------------------------------------------------
/src/assets/icon/rectangle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/refresh.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/setting.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/shape.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/stop-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/stop-white.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/stop.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/testfiesta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/testfiesta.png
--------------------------------------------------------------------------------
/src/assets/icon/testrail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/testrail.png
--------------------------------------------------------------------------------
/src/assets/icon/text.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/text_link.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/thick.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/thin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/face-smile.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/message-blue.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/message-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/message.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/microphone-blue.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/microphone-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/microphone.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/mindmap-blue.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/mindmap-gray.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/notes.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/pause20px.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/play.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/play20px.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/stop.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/video-blue.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/timeline-icon/video-gray.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/transparent.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/assets/icon/trash-red.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/trash.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/triangle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/underline.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/upload.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/video-slash-solid-gray.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-slash-solid-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-slash-solid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-solid-gray.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-solid-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-solid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/assets/icon/video-white.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/icon/xray-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/xray-logo.png
--------------------------------------------------------------------------------
/src/assets/icon/zephyr-scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/zephyr-scale.png
--------------------------------------------------------------------------------
/src/assets/icon/zephyr-squad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/icon/zephyr-squad.png
--------------------------------------------------------------------------------
/src/assets/icon/zoom-in.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/icon/zoom-out.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/mindmap-workspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testfiesta/pinata/d788c89e7428f59aca637441b66eb60158bf0c11/src/assets/mindmap-workspace.png
--------------------------------------------------------------------------------
/src/components/FileWrapper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | mdi-file
5 |
6 |
{{ editSessionItem.fileName }}
7 |
8 |
9 |
10 |
44 |
71 |
--------------------------------------------------------------------------------
/src/components/LogoWrapper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
34 |
--------------------------------------------------------------------------------
/src/components/SearchWrapper.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
39 |
44 |
--------------------------------------------------------------------------------
/src/components/__tests__/CheckTaskWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import CheckTaskWrapper from "../CheckTaskWrapper.vue";
3 |
4 | import { mount, createLocalVue } from "@vue/test-utils";
5 |
6 | const localVue = createLocalVue();
7 |
8 | const vuetify = new Vuetify();
9 |
10 | describe("CheckTaskWrapper.vue", () => {
11 | test("render a view", () => {
12 | const wrapper = mount(CheckTaskWrapper, {
13 | mocks: {
14 | $t: () => {},
15 | $tc: () => {},
16 | },
17 | propsData: {
18 | showError: false,
19 | tasks: [
20 | {
21 | id: 1,
22 | checked: false,
23 | content: "",
24 | },
25 | ],
26 | type: "presession",
27 | },
28 | localVue,
29 | vuetify,
30 | });
31 |
32 | expect(wrapper.find(".task-wrapper .subtitle-2").exists()).toBe(true);
33 | expect(wrapper.find(".task-wrapper .list").exists()).toBe(true);
34 | expect(wrapper.findAll(".task-wrapper .list .one").length).toBe(1);
35 | expect(wrapper.find(".task-wrapper .error1").exists()).toBe(false);
36 | });
37 |
38 | test("show a error panel", () => {
39 | const wrapper = mount(CheckTaskWrapper, {
40 | mocks: {
41 | $t: () => {},
42 | $tc: () => {},
43 | },
44 | propsData: {
45 | showError: true,
46 | tasks: [
47 | {
48 | id: 1,
49 | checked: false,
50 | content: "",
51 | },
52 | ],
53 | type: "presession",
54 | },
55 | localVue,
56 | vuetify,
57 | });
58 |
59 | expect(wrapper.find(".task-wrapper .error1").exists()).toBe(true);
60 | expect(wrapper.find(".task-wrapper .error1 .content .title").exists()).toBe(
61 | true
62 | );
63 | expect(wrapper.find(".task-wrapper .error1 .content .desc").exists()).toBe(
64 | true
65 | );
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/src/components/__tests__/ExportPanel.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from "@vue/test-utils";
2 | import Vuetify from "vuetify";
3 |
4 | import ExportPanel from "../ExportPanel.vue";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("ExportPanel.vue", () => {
9 | const items = [];
10 |
11 | test("Display buttons", () => {
12 | const wrapper = mount(ExportPanel, {
13 | mocks: {
14 | $t: () => {},
15 | $tc: () => {},
16 | },
17 | propsData: {
18 | items: items,
19 | },
20 | vuetify,
21 | });
22 |
23 | expect(wrapper.find("button.v-btn").exists()).toBe(true);
24 | });
25 |
26 | test('trigger the click event of "export session report" button', async () => {
27 | const wrapper = mount(ExportPanel, {
28 | mocks: {
29 | $t: () => {},
30 | $tc: () => {},
31 | },
32 | items: items,
33 | vuetify,
34 | });
35 |
36 | const button = wrapper.find("button.v-btn");
37 | const event = jest.fn();
38 |
39 | button.vm.$on("click", event);
40 | button.trigger("click");
41 |
42 | expect(event).toHaveBeenCalled();
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/src/components/__tests__/FileWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import FileWrapper from "../FileWrapper";
2 | import Vuetify from "vuetify";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | describe("FileWrapper.vue", () => {
7 | const vuetify = new Vuetify();
8 |
9 | test("load a view", () => {
10 | const wrapper = mount(FileWrapper, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | propsData: {
16 | item: {
17 | fileName: "test.pdf",
18 | },
19 | },
20 | vuetify,
21 | });
22 |
23 | expect(wrapper.find(".wrapper .file-icon").exists()).toBe(true);
24 | expect(wrapper.find(".wrapper p").exists()).toBe(true);
25 | expect(wrapper.find(".wrapper p").text()).toContain("test.pdf");
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/components/__tests__/ImageEditor.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import ImageEditor from "../ImageEditor";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("ImageEditor.vue", () => {
9 | test("render a view", () => {
10 | const wrapper = mount(ImageEditor, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | propsData: {
16 | item: {
17 | filePath: "",
18 | },
19 | },
20 | vuetify,
21 | });
22 |
23 | expect(wrapper.find(".image-editor").exists()).toBe(true);
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/components/__tests__/LogoWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from "@vue/test-utils";
2 |
3 | import LogoWrapper from "../LogoWrapper";
4 |
5 | describe("LogoWrapper.vue", () => {
6 | test("displays logo", () => {
7 | const wrapper = mount(LogoWrapper);
8 |
9 | expect(wrapper.find(".v-image")).toBeTruthy();
10 |
11 | const images = wrapper.findAll(".v-image");
12 | expect(images.length).toBe(1);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/__tests__/MindmapEditor.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import MindmapEditor from "../MindmapEditor.vue";
3 | import NodeEditDialog from "../dialogs/NodeEditDialog.vue";
4 |
5 | import { mount, createLocalVue } from "@vue/test-utils";
6 |
7 | const vuetify = new Vuetify();
8 | const localVue = createLocalVue();
9 |
10 | describe("MindmapEditor.vue", () => {
11 | test("render a view", () => {
12 | const wrapper = mount(MindmapEditor, {
13 | mocks: {
14 | $t: () => {},
15 | $tc: () => {},
16 | },
17 | localVue,
18 | vuetify,
19 | });
20 |
21 | expect(wrapper.find(".wrapper").exists()).toBe(true);
22 | expect(wrapper.findComponent(NodeEditDialog).exists()).toBe(true);
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/components/__tests__/NotesWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import NotesWrapper from "../NotesWrapper.vue";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("NotesWrapper.vue", () => {
9 | test("render a view", () => {
10 | const wrapper = mount(NotesWrapper, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | data() {
16 | return {
17 | notes: { text: "", content: "" },
18 | };
19 | },
20 | vuetify,
21 | });
22 | expect(wrapper.find(".content").exists()).toBe(true);
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/components/__tests__/ReviewWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 |
3 | import ReviewWrappper from "../ReviewWrapper";
4 | import ImageEditor from "../ImageEditor";
5 | import VideoWrapper from "../VideoWrapper";
6 | import AudioWrapper from "../AudioWrapper";
7 | import FileWrapper from "../FileWrapper";
8 | import MindmapEditor from "../MindmapEditor.vue";
9 |
10 | import { mount } from "@vue/test-utils";
11 |
12 | const vuetify = new Vuetify();
13 |
14 | describe("ReivewWrapper.vue", () => {
15 | test("render a view", async () => {
16 | const wrapper = mount(ReviewWrappper, {
17 | mocks: {
18 | $t: () => {},
19 | $tc: () => {},
20 | },
21 | propsData: {
22 | item: {
23 | fileType: "application/mindmap",
24 | content: { nodes: [] },
25 | },
26 | processing: false,
27 | triggerSave: false,
28 | autoSave: false,
29 | currentView: false,
30 | config: {
31 | defaultColor: "#000000",
32 | },
33 | },
34 | data() {
35 | return {
36 | sessionItem: {
37 | fileType: "application/mindmap",
38 | },
39 | };
40 | },
41 | vuetify,
42 | });
43 |
44 | expect(wrapper.findComponent(MindmapEditor).exists()).toBe(true);
45 |
46 | await wrapper.setData({
47 | sessionItem: {
48 | fileType: "image/png",
49 | },
50 | });
51 |
52 | expect(wrapper.findComponent(ImageEditor).exists()).toBe(true);
53 |
54 | await wrapper.setData({
55 | sessionItem: {
56 | fileType: "video/mp4",
57 | },
58 | });
59 | expect(wrapper.findComponent(VideoWrapper).exists()).toBe(true);
60 |
61 | await wrapper.setData({
62 | sessionItem: {
63 | fileType: "audio/mp3",
64 | },
65 | });
66 | expect(wrapper.findComponent(AudioWrapper).exists()).toBe(true);
67 |
68 | await wrapper.setData({
69 | sessionItem: {
70 | fileType: "other",
71 | },
72 | });
73 | expect(wrapper.findComponent(FileWrapper).exists()).toBe(true);
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/src/components/__tests__/SearchWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from "@vue/test-utils";
2 | import Vuetify from "vuetify";
3 |
4 | import SearchWrapper from "../SearchWrapper.vue";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("SearchWrapper.vue", () => {
9 | test("load serach box", () => {
10 | const wrapper = mount(SearchWrapper, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | vuetify,
16 | });
17 |
18 | const searchInput = wrapper.find("input");
19 | expect(searchInput.exists()).toBe(true);
20 | });
21 |
22 | test("change the value of searchbox", async () => {
23 | const wrapper = mount(SearchWrapper, {
24 | mocks: {
25 | $t: () => {},
26 | $tc: () => {},
27 | },
28 | vuetify,
29 | });
30 |
31 | const searchInput = wrapper.find("input");
32 | await searchInput.setValue("Search");
33 |
34 | expect(wrapper.vm.search).toBe("Search");
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/components/__tests__/TimeCounter.spec.js:
--------------------------------------------------------------------------------
1 | import { mount, createLocalVue } from "@vue/test-utils";
2 | import Vuex from "vuex";
3 | import Vuetify from "vuetify";
4 | import { cloneDeep } from "lodash";
5 |
6 | import TimeCounter from "../TimeCounter";
7 | import storeConfig from "../../store/store-config";
8 |
9 | const vuetify = new Vuetify();
10 | const localVue = createLocalVue();
11 |
12 | localVue.use(Vuex);
13 |
14 | describe("TimeCounter.vue", () => {
15 | let store;
16 |
17 | beforeEach(() => {
18 | store = new Vuex.Store(cloneDeep(storeConfig));
19 | });
20 |
21 | test("displays elapsed time title", () => {
22 | const wrapper = mount(TimeCounter, {
23 | mocks: {
24 | $t: () => {},
25 | $tc: () => {},
26 | },
27 | localVue,
28 | store,
29 | vuetify,
30 | });
31 |
32 | expect(
33 | wrapper.find(".time-wrapper .time:nth-child(1) .time-title")
34 | ).toBeTruthy();
35 | });
36 |
37 | test("displays remaining time title", () => {
38 | const wrapper = mount(TimeCounter, {
39 | mocks: {
40 | $t: () => {},
41 | $tc: () => {},
42 | },
43 | localVue,
44 | store,
45 | vuetify,
46 | });
47 |
48 | expect(
49 | wrapper.find(".time-wrapper .time:nth-child(2) .time-title")
50 | ).toBeTruthy();
51 | });
52 |
53 | test("displays elapsed time value", () => {
54 | const wrapper = mount(TimeCounter, {
55 | mocks: {
56 | $t: () => {},
57 | $tc: () => {},
58 | },
59 | localVue,
60 | store,
61 | vuetify,
62 | });
63 |
64 | expect(
65 | wrapper.find(".time-wrapper .time:nth-child(1) .time-value")
66 | ).toBeTruthy();
67 | expect(
68 | wrapper.find(".time-wrapper .time:nth-child(1) .time-value").text()
69 | ).toBe("00:00:00");
70 | });
71 |
72 | test("displays remaining time value", () => {
73 | const wrapper = mount(TimeCounter, {
74 | mocks: {
75 | $t: () => {},
76 | $tc: () => {},
77 | },
78 | localVue,
79 | store,
80 | vuetify,
81 | });
82 |
83 | expect(
84 | wrapper.find(".time-wrapper .time:nth-child(2) .time-value")
85 | ).toBeTruthy();
86 | expect(
87 | wrapper.find(".time-wrapper .time:nth-child(2) .time-value").text()
88 | ).toBe("00:00:00");
89 | });
90 | });
91 |
--------------------------------------------------------------------------------
/src/components/__tests__/WorkspaceWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import WorkspaceWrapper from "../WorkspaceWrapper.vue";
3 | import NotesWrapper from "../NotesWrapper.vue";
4 | import TimelineWrapper from "../TimelineWrapper.vue";
5 |
6 | import { shallowMount } from "@vue/test-utils";
7 |
8 | const vuetify = new Vuetify();
9 |
10 | describe("WorkspaceWrapper.vue", () => {
11 | test("render a view", () => {
12 | const wrapper = shallowMount(WorkspaceWrapper, {
13 | mocks: {
14 | $t: () => {},
15 | $tc: () => {},
16 | },
17 | propsData: {
18 | items: [],
19 | selectedItems: [],
20 | eventType: "",
21 | },
22 | vuetify,
23 | });
24 |
25 | expect(wrapper.find(".tab-bar .timeline-tab").exists()).toBe(true);
26 | expect(wrapper.find(".tab-bar .notes-tab").exists()).toBe(true);
27 | expect(wrapper.findComponent(NotesWrapper).exists()).toBe(true);
28 | expect(wrapper.findComponent(TimelineWrapper).exists()).toBe(true);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/components/authentication/__tests__/SigninWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import SigninWrapper from "../SigninWrapper.vue";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("SigninWrapper.vue", () => {
9 | test("render a view", () => {
10 | const wrapper = mount(SigninWrapper, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | vuetify,
16 | });
17 |
18 | expect(wrapper.find(".wrapper .header").exists()).toBe(true);
19 | expect(wrapper.find(".wrapper .subtitle-1").exists()).toBe(true);
20 | expect(wrapper.find(".wrapper .content").exists()).toBe(true);
21 | expect(
22 | wrapper.findAll(".wrapper .content .row:first-child button").length
23 | ).toBe(2);
24 | });
25 |
26 | test('trigger the click event of "signin with pinata" button', () => {
27 | const wrapper = mount(SigninWrapper, {
28 | mocks: {
29 | $t: () => {},
30 | $tc: () => {},
31 | },
32 | data() {
33 | return {};
34 | },
35 | vuetify,
36 | });
37 |
38 | const event = jest.fn();
39 | const button = wrapper.find("button.pinata");
40 |
41 | button.vm.$on("click", event);
42 | button.trigger("click");
43 |
44 | expect(event).toHaveBeenCalled();
45 | });
46 |
47 | test('trigger the click event of "signin with jira" button', () => {
48 | const wrapper = mount(SigninWrapper, {
49 | mocks: {
50 | $t: () => {},
51 | $tc: () => {},
52 | },
53 | data() {
54 | return {};
55 | },
56 | vuetify,
57 | });
58 |
59 | const event = jest.fn();
60 | const button = wrapper.find("button.jira");
61 |
62 | button.vm.$on("click", event);
63 | button.trigger("click");
64 |
65 | expect(event).toHaveBeenCalled();
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/src/components/authentication/__tests__/SignupPinataWrapper.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import SignupPinataWrapper from "../SignupPinataWrapper.vue";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | const vuetify = new Vuetify();
7 | let wrapper;
8 |
9 | describe("SignupPinataWrapper.vue", () => {
10 | beforeEach(() => {
11 | wrapper = mount(SignupPinataWrapper, {
12 | mocks: {
13 | $t: () => {},
14 | $tc: () => {},
15 | },
16 | data() {
17 | return {
18 | start: "individual",
19 | email: "",
20 | url: "",
21 | };
22 | },
23 | vuetify,
24 | });
25 | });
26 |
27 | test("render a view", () => {
28 | expect(wrapper.find(".wrapper .header").exists()).toBe(true);
29 | expect(wrapper.find(".wrapper .header .v-btn").exists()).toBe(true);
30 | expect(wrapper.find(".wrapper .header .subtitle-1").exists()).toBe(true);
31 | expect(wrapper.find(".wrapper .content").exists()).toBe(true);
32 | expect(wrapper.find(".wrapper .content .radio-box").exists()).toBe(true);
33 | expect(wrapper.find(".wrapper"));
34 | expect(wrapper.find(".wrapper .footer").exists()).toBe(true);
35 | });
36 |
37 | test('trigger the click event of "back" button', async () => {
38 | const event = jest.fn();
39 | const button = wrapper.find(".back-btn");
40 |
41 | button.vm.$on("click", event);
42 | button.trigger("click");
43 |
44 | await wrapper.vm.$nextTick();
45 |
46 | // expect(event).toHaveBeenCalled();
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/components/dialogs/SettingsDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
24 |
25 |
26 |
27 |
28 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/components/dialogs/__tests__/EndSessionDialog.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import CheckTaskWrapper from "../../CheckTaskWrapper.vue";
3 | import EndSessionDialog from "../EndSessionDialog.vue";
4 |
5 | import { mount, createLocalVue } from "@vue/test-utils";
6 |
7 | let vuetify;
8 | let wrapper;
9 | let localVue;
10 |
11 | describe("EndSessionDialog.vue", () => {
12 | beforeEach(() => {
13 | const rootDiv = document.createElement("div");
14 | rootDiv.id = "root";
15 | document.body.appendChild(rootDiv);
16 |
17 | localVue = createLocalVue();
18 |
19 | vuetify = new Vuetify();
20 |
21 | const App = localVue.component("App", {
22 | components: { EndSessionDialog },
23 | data() {
24 | return {
25 | dialog: false,
26 | showTaskError: false,
27 | };
28 | },
29 | template: `
30 |
31 |
36 |
37 | `,
38 | });
39 |
40 | wrapper = mount(App, {
41 | mocks: {
42 | $t: () => {},
43 | $tc: () => {},
44 | },
45 | localVue,
46 | vuetify,
47 | attachTo: "#root",
48 | });
49 | });
50 |
51 | test("render a dialog", async () => {
52 | wrapper.setData({
53 | dialog: true,
54 | });
55 |
56 | await wrapper.vm.$nextTick();
57 |
58 | expect(wrapper.findComponent(CheckTaskWrapper).exists()).toBe(true);
59 | expect(wrapper.find(".btn-end").exists()).toBe(true);
60 | });
61 |
62 | test('trigger the click event of "End Session" button', async () => {
63 | wrapper.setData({
64 | dialog: true,
65 | });
66 |
67 | await wrapper.vm.$nextTick();
68 |
69 | const button = wrapper.find(".btn-end");
70 | const event = jest.fn();
71 |
72 | button.vm.$on("click", event);
73 | button.trigger("click");
74 |
75 | expect(event).toHaveBeenCalled();
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/src/components/dialogs/__tests__/SourcePIckerDialog.spec.js:
--------------------------------------------------------------------------------
1 | import SourcePickerDialog from "../SourcePickerDialog";
2 | import Vuetify from "vuetify";
3 |
4 | import { mount, createLocalVue } from "@vue/test-utils";
5 |
6 | let wrapper;
7 | let vuetify;
8 | let localVue;
9 |
10 | describe("SourcePickerDialog", () => {
11 | beforeEach(() => {
12 | const rootDiv = document.createElement("div");
13 | rootDiv.id = "root";
14 | document.body.appendChild(rootDiv);
15 |
16 | localVue = createLocalVue();
17 | vuetify = new Vuetify();
18 |
19 | const App = localVue.component("App", {
20 | components: { SourcePickerDialog },
21 | data() {
22 | return {
23 | dialog: false,
24 | };
25 | },
26 | template: `
27 |
28 |
32 |
33 | `,
34 | });
35 |
36 | wrapper = mount(App, {
37 | mocks: {
38 | $t: () => {},
39 | $tc: () => {},
40 | },
41 | localVue,
42 | vuetify,
43 | attachTo: "#root",
44 | });
45 | });
46 |
47 | test("render a dialog", async () => {
48 | await wrapper.setData({ dialog: true });
49 |
50 | expect(wrapper.find(".header span").exists()).toBe(true);
51 |
52 | expect(wrapper.find(".content").exists()).toBe(true);
53 | expect(wrapper.findAll(".footer button").length).toBe(2);
54 | });
55 |
56 | test('trigger the click event of "Cancel" button', async () => {
57 | await wrapper.setData({ dialog: true });
58 |
59 | const button = wrapper.find(".footer button:first-child");
60 | const event = jest.fn();
61 |
62 | button.vm.$on("click", event);
63 | button.trigger("click");
64 |
65 | expect(event).toHaveBeenCalled();
66 | });
67 |
68 | test('trigger the click event of "Start Recording" button', async () => {
69 | await wrapper.setData({ dialog: true });
70 |
71 | const button = wrapper.find(".footer button:first-child");
72 | const event = jest.fn();
73 |
74 | button.vm.$on("click", event);
75 | button.trigger("click");
76 |
77 | expect(event).toHaveBeenCalled();
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/src/components/mindmap/ColorPicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
80 |
98 |
--------------------------------------------------------------------------------
/src/components/mindmap/MarkerPad.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
11 |
12 |
13 | {{ $tc("caption.marker", 1) }}
14 |
15 |
16 |
17 |
18 |
![]()
23 |
24 |
25 | {{ $tc("caption.ellipse", 1) }}
26 |
27 |
28 |
29 |
30 |
![]()
35 |
36 |
37 | {{ $tc("caption.triangle", 1) }}
38 |
39 |
40 |
41 |
42 |
![]()
47 |
48 |
49 | {{ $tc("caption.downward-triangle", 1) }}
50 |
51 |
52 |
53 |
54 |
70 |
--------------------------------------------------------------------------------
/src/components/mindmap/contextMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ action.label }}
6 |
7 |
8 |
9 |
10 |
11 |
35 |
36 |
54 |
--------------------------------------------------------------------------------
/src/components/settings/SupportTab.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $tc("caption.todo", 1) }}
6 |
7 |
8 |
9 |
10 |
11 |
29 |
70 |
--------------------------------------------------------------------------------
/src/components/settings/__tests__/GeneralTab.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import GeneralTab from "../GeneralTab";
3 |
4 | import { mount, createLocalVue } from "@vue/test-utils";
5 |
6 | const localVue = createLocalVue();
7 | const vuetify = new Vuetify();
8 |
9 | describe("GeneralTab.vue", () => {
10 | test("render a view", () => {
11 | const wrapper = mount(GeneralTab, {
12 | mocks: {
13 | $t: () => {},
14 | $tc: () => {},
15 | },
16 | propsData: {
17 | config: {},
18 | },
19 | localVue,
20 | vuetify,
21 | });
22 |
23 | expect(wrapper.find(".content-wrapper .theme-mode-section").exists()).toBe(
24 | true
25 | );
26 | expect(
27 | wrapper
28 | .find(".content-wrapper .theme-mode-section .radio-control")
29 | .exists()
30 | ).toBe(true);
31 |
32 | expect(wrapper.find(".content-wrapper .screenshot-section").exists()).toBe(
33 | true
34 | );
35 | expect(
36 | wrapper
37 | .find(".content-wrapper .screenshot-section .color-picker-wrapper")
38 | .exists()
39 | ).toBe(true);
40 |
41 | expect(wrapper.find(".content-wrapper .note-section").exists()).toBe(true);
42 | expect(wrapper.find(".content-wrapper .note-section input").exists()).toBe(
43 | true
44 | );
45 |
46 | expect(
47 | wrapper.find(".content-wrapper .screen-recording-section").exists()
48 | ).toBe(true);
49 | expect(
50 | wrapper
51 | .find(".content-wrapper .screen-recording-section .switch-control")
52 | .exists()
53 | ).toBe(true);
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/components/settings/__tests__/SupportTab.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import SupportTab from "../SupportTab.vue";
3 |
4 | import { mount, createLocalVue } from "@vue/test-utils";
5 |
6 | const localVue = createLocalVue();
7 | localVue.use(Vuetify);
8 |
9 | const vuetify = new Vuetify();
10 |
11 | describe("SupportTab.vue", () => {
12 | test("render a view", () => {
13 | const wrapper = mount(SupportTab, {
14 | mocks: {
15 | $t: () => {},
16 | $tc: () => {},
17 | },
18 | localVue,
19 | vuetify,
20 | });
21 |
22 | expect(wrapper.find(".content-wrapper").exists()).toBe(true);
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/helpers/HotkeyHelpers.js:
--------------------------------------------------------------------------------
1 | export default {
2 | findBinding(key, bindingConfig) {
3 | let keys = key.split(".");
4 | let bindingCursor = bindingConfig;
5 | for (const k of keys) {
6 | if (bindingCursor) {
7 | bindingCursor = bindingCursor?.[k];
8 | }
9 | }
10 | if (bindingCursor && bindingCursor.constructor === String) {
11 | return this.findBinding(bindingCursor, bindingConfig);
12 | }
13 | return bindingCursor || [];
14 | },
15 | printBindings(directBinding, bindingConfig) {
16 | if (directBinding.constructor === Array) {
17 | return directBinding.join(" + ").toUpperCase();
18 | } else {
19 | return this.findBinding(directBinding, bindingConfig)
20 | .join(" + ")
21 | .toUpperCase();
22 | }
23 | },
24 | focusField(refs, label) {
25 | const el = refs[label]?.$el || refs[label];
26 | let input = el.querySelector(".ProseMirror");
27 | if (!input) {
28 | input = el.querySelector(
29 | "input:not([type=hidden]),textarea:not([type=hidden])"
30 | );
31 | }
32 | if (input) {
33 | setTimeout(() => {
34 | input.focus();
35 | });
36 | }
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/src/i18n.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueI18n from "vue-i18n";
3 |
4 | Vue.use(VueI18n);
5 |
6 | function loadLocaleMessages() {
7 | const locales = require.context(
8 | "./locales",
9 | true,
10 | /[A-Za-z0-9-_,\s]+\.json$/i
11 | );
12 | const messages = {};
13 | locales.keys().forEach((key) => {
14 | const matched = key.match(/([A-Za-z0-9-_]+)\./i);
15 | if (matched && matched.length > 1) {
16 | const locale = matched[1];
17 | messages[locale] = locales(key);
18 | }
19 | });
20 |
21 | return messages;
22 | }
23 |
24 | export default new VueI18n({
25 | locale: process.env.VUE_APP_I18N_LOCALE || "en",
26 | fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
27 | messages: loadLocaleMessages(),
28 | silentTranslationWarn: true, //process.env.NODE_ENV === "production",
29 | });
30 |
--------------------------------------------------------------------------------
/src/integrations/TestRailIntegrationHelpers.js:
--------------------------------------------------------------------------------
1 | import { IPC_HANDLERS, IPC_FUNCTIONS } from "../modules/constants";
2 |
3 | export default {
4 | saveCredentials(credentials, data) {
5 | // TODO - can this be generalized and the key passed
6 | let formattedData = this.formatData(data);
7 |
8 | if (!credentials) {
9 | credentials = {};
10 | }
11 |
12 | if (credentials.testrail && credentials.testrail.length > 0) {
13 | let matched = false;
14 | for (const [testrailIndex, credential] of Object.entries(
15 | credentials.testrail
16 | )) {
17 | if (credential.user.id === formattedData.user.id) {
18 | credentials.testrail[testrailIndex] = formattedData;
19 | matched = true;
20 | }
21 | }
22 | if (!matched) {
23 | credentials.testrail.push(formattedData);
24 | }
25 | } else {
26 | credentials.testrail = [formattedData];
27 | }
28 |
29 | window.ipc.invoke(IPC_HANDLERS.PERSISTENCE, {
30 | func: IPC_FUNCTIONS.UPDATE_CREDENTIALS,
31 | data: credentials,
32 | });
33 |
34 | return credentials;
35 | },
36 | formatData(data) {
37 | return {
38 | accessToken: data.accessToken,
39 | type: data.type,
40 | loggedInAt: data.loggedInAt,
41 | user: {
42 | id: data.profile.account_id,
43 | email: data.profile.email,
44 | name: data.profile.name,
45 | },
46 | url: data.url,
47 | };
48 | },
49 | };
50 |
--------------------------------------------------------------------------------
/src/layouts/Minimize.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
15 |
20 |
--------------------------------------------------------------------------------
/src/mixins/theme.js:
--------------------------------------------------------------------------------
1 | export default {
2 | computed: {
3 | currentTheme() {
4 | if (this.$vuetify.theme.dark) {
5 | return this.$vuetify.theme.themes.dark;
6 | } else {
7 | return this.$vuetify.theme.themes.light;
8 | }
9 | },
10 | mainBg() {
11 | return this.$vuetify.theme.dark ? "#374151" : this.currentTheme.white;
12 | },
13 | btnBg() {
14 | return this.$vuetify.theme.dark ? "#4B5563" : "#F2F4F7";
15 | },
16 | inputBg() {
17 | return this.$vuetify.theme.dark ? "#4B5563" : "#F9F9FB";
18 | },
19 | btnColor() {
20 | return this.$vuetify.theme.dark ? "#FFFFFF" : "#000000";
21 | },
22 | mainBgReverse() {
23 | return this.$vuetify.theme.dark ? "#F2F4F7" : "#161B26";
24 | },
25 | },
26 | };
27 |
--------------------------------------------------------------------------------
/src/modules/BrowserWindowUtility.js:
--------------------------------------------------------------------------------
1 | const { VIEW_MODE } = require("./constants");
2 |
3 | module.exports.setBrowserWindow = (browserWindow) => {
4 | this._browserWindow = browserWindow;
5 | };
6 |
7 | module.exports.getBrowserWindow = () => {
8 | return this._browserWindow;
9 | };
10 |
11 | module.exports.setLowProfiledWindow = (lowProfiledWindow) => {
12 | this._lowProfiledWindow = lowProfiledWindow;
13 | };
14 |
15 | module.exports.getLowProfiledWindow = () => {
16 | return this._lowProfiledWindow;
17 | };
18 |
19 | module.exports.setViewMode = (viewMode) => {
20 | this._viewMode = viewMode;
21 | };
22 |
23 | module.exports.getViewMode = () => {
24 | return this._viewMode;
25 | };
26 |
27 | module.exports.getParentWindow = () => {
28 | if (this._viewMode === VIEW_MODE.NORMAL) return this._browserWindow;
29 | else return this._lowProfiledWindow;
30 | };
31 |
--------------------------------------------------------------------------------
/src/modules/MenuUtility.js:
--------------------------------------------------------------------------------
1 | const { Menu } = require("electron");
2 |
3 | const { SESSION_STATUSES } = require("./constants");
4 |
5 | module.exports.changeMenuItemStatus = ({ sessionStatus }) => {
6 | const mainMenu = Menu.getApplicationMenu();
7 | const fileMenu = mainMenu.items.find((item) => item.id === "menu_file");
8 | const fileSubMenus = fileMenu.submenu.items;
9 |
10 | if (sessionStatus === SESSION_STATUSES.PENDING) {
11 | fileSubMenus.find(
12 | (item) => item.id === "menu_save_session"
13 | ).enabled = false;
14 | // fileSubMenus.find(
15 | // (item) => item.id === "menu_save_as_charter"
16 | // ).enabled = false;
17 | fileSubMenus.find(
18 | (item) => item.id === "menu_reset_session"
19 | ).enabled = false;
20 | } else {
21 | fileSubMenus.find((item) => item.id === "menu_save_session").enabled = true;
22 | // fileSubMenus.find(
23 | // (item) => item.id === "menu_save_as_charter"
24 | // ).enabled = true;
25 | fileSubMenus.find(
26 | (item) => item.id === "menu_reset_session"
27 | ).enabled = true;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/modules/ServerUtility.js:
--------------------------------------------------------------------------------
1 | const { fork } = require("child_process");
2 | const path = require("path");
3 | const browserUtility = require("./BrowserWindowUtility");
4 |
5 | let serverProcess = null;
6 |
7 | module.exports.startServer = async (vars) => {
8 | if (Object.keys(vars) < 1) {
9 | vars = {};
10 | }
11 |
12 | const isDevelopment = process.env.NODE_ENV !== "production";
13 | serverProcess = fork(
14 | isDevelopment
15 | ? path.resolve(__dirname, "../server/server.js")
16 | : path.resolve(process.resourcesPath, "./server/server.js"),
17 | {
18 | env: vars,
19 | }
20 | );
21 |
22 | const browserWindow = browserUtility.getBrowserWindow();
23 |
24 | serverProcess.on("message", (data) => {
25 | switch (data.type) {
26 | case "jira":
27 | browserWindow.webContents.send("JIRA_LOGIN", data.data);
28 | break;
29 | default:
30 | break;
31 | }
32 | });
33 | await new Promise((resolve) => setTimeout(resolve, 1000));
34 | // TODO: The above line is not ideal, but the express server doesn't seem to
35 | // send a 'spawn' event, so the below line doesn't work.
36 | //await once(serverProcess, 'spawn');
37 | };
38 |
39 | module.exports.stopServer = () => {
40 | if (serverProcess) {
41 | serverProcess.kill();
42 | }
43 | };
44 |
--------------------------------------------------------------------------------
/src/modules/SystemInfoUtility.js:
--------------------------------------------------------------------------------
1 | const os = require("os");
2 | const si = require("systeminformation");
3 |
4 | async function getCurrentDateTime() {
5 | return new Date().toLocaleString("en-US", { timeZone: "UTC" });
6 | }
7 |
8 | async function getComputerName() {
9 | return os.hostname();
10 | }
11 |
12 | async function getOperatingSystem() {
13 | const osInfo = await si.osInfo();
14 | return `${osInfo.distro} ${osInfo.release} ${osInfo.arch}`;
15 | }
16 |
17 | async function getSystemInfo() {
18 | const systemInfo = await si.system();
19 | return {
20 | manufacturer: systemInfo.manufacturer,
21 | model: systemInfo.model,
22 | };
23 | }
24 |
25 | async function getBIOSVersion() {
26 | const biosInfo = await si.bios();
27 | return biosInfo.version;
28 | }
29 |
30 | async function getProcessor() {
31 | const cpuInfo = await si.cpu();
32 | return `${cpuInfo.manufacturer} ${cpuInfo.brand} (${cpuInfo.physicalCores} CPUs), ~${cpuInfo.speed}GHz`;
33 | }
34 |
35 | async function getMemory() {
36 | const memInfo = await si.mem();
37 | return `${(memInfo.total / 1024 / 1024).toFixed(0)}MB RAM`;
38 | }
39 |
40 | module.exports.getSystemInfo = async () => {
41 | try {
42 | const currentDateTime = await getCurrentDateTime();
43 | const computerName = await getComputerName();
44 | const operatingSystem = await getOperatingSystem();
45 | const systemInfo = await getSystemInfo(); // Store the result of getSystemInfo() in a variable
46 | const systemManufacturer = systemInfo.manufacturer;
47 | const systemModel = systemInfo.model;
48 | const biosVersion = await getBIOSVersion();
49 | const processor = await getProcessor();
50 | const memory = await getMemory();
51 |
52 | return {
53 | currentDateTime,
54 | computerName,
55 | operatingSystem,
56 | systemManufacturer,
57 | systemModel,
58 | biosVersion,
59 | processor,
60 | memory,
61 | };
62 | } catch (error) {
63 | console.error("Error fetching system information:", error);
64 | return null; // or handle the error in a different way as per your requirement
65 | }
66 | };
67 |
--------------------------------------------------------------------------------
/src/modules/migrations/v0.6.0.js:
--------------------------------------------------------------------------------
1 | export const migrationStruct = {
2 | up: {
3 | meta: {
4 | credentialPath: "credentialsPath",
5 | },
6 | },
7 | down: {
8 | meta: {
9 | credentialsPath: "credentialPath",
10 | },
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/src/modules/migrations/v0.8.0.js:
--------------------------------------------------------------------------------
1 | export const migrationStruct = {
2 | up: {
3 | meta: {
4 | meta: "..",
5 | dataPath: "sessionDataPath",
6 | },
7 | },
8 | down: {
9 | meta: {
10 | configPath: "meta.configPath",
11 | credentialsPath: "meta.credentialsPath",
12 | sessionDataPath: "meta.dataPath",
13 | version: "meta.version",
14 | },
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/src/modules/mindmap/parser/regex.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Extract text from the inner HTML of a node.
3 | */
4 | const getText = (html) => {
5 | const res = [];
6 |
7 | // Match all text inside A tags. If there's no A tags,
8 | // match text inside P tags instead.
9 | const matchText = /]*>([^<]*)<\/a>|]*>([^>]*)<\/p>/g;
10 | let match = matchText.exec(html);
11 |
12 | while (match) {
13 | res.push(match[1] || match[2]);
14 | match = matchText.exec(html);
15 | }
16 |
17 | return res.join(" ");
18 | };
19 |
20 | /*
21 | * Extract HREF content from the first link on a node.
22 | */
23 | const getURL = (html) => {
24 | // Match HREF content inside A tags.
25 | const matchURL = /]*href="([^"]*)"[^>]*>[^<]*<\/a>/;
26 | const match = matchURL.exec(html);
27 |
28 | if (match) {
29 | return match[1];
30 | }
31 |
32 | return "";
33 | };
34 |
35 | module.exports = {
36 | getText,
37 | getURL,
38 | };
39 |
--------------------------------------------------------------------------------
/src/modules/mindmap/sass/mindmap.sass:
--------------------------------------------------------------------------------
1 | $grey100: #f5f5f5
2 | $grey500: #9e9e9e
3 | $grey800: #424242
4 | $grey900: #212121
5 | $orange700: #f57c00
6 | $cyan100: #D6E4EE
7 | $cyan200: #A0D8F3
8 | $cyan300: #80B3FF
9 |
10 | $white: #fff
11 | $shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12)
12 |
13 |
14 | .mindmap-svg
15 | height: 100vh
16 | width: 100%
17 |
18 | &:focus
19 | outline: none
20 |
21 | .mindmap-node > a
22 | background: $grey100
23 | border-radius: 10px
24 | box-shadow: $shadow
25 | color: $grey900
26 | display: inline-block
27 | font-family: 'Raleway'
28 | font-size: 22px
29 | margin: 0 auto
30 | padding: 15px
31 | text-align: center
32 | text-decoration: none
33 | transition: background-color .2s, color .2s ease-out
34 |
35 | &[href]
36 | &:hover
37 | background-color: $orange700
38 | color: $white
39 | cursor: pointer
40 |
41 | .mindmap-node--editable
42 | cursor: all-scroll
43 |
44 | & > a
45 | pointer-events: none
46 |
47 | .mindmap-subnode-group
48 | align-items: center
49 | border-left: 4px solid $grey500
50 | display: flex
51 | margin-left: 15px
52 | padding: 5px
53 |
54 | a
55 | color: $grey900
56 | font-family: 'Raleway'
57 | font-size: 16px
58 | padding: 2px 5px
59 |
60 | .mindmap-connection
61 | fill: transparent
62 | stroke: $grey500
63 | stroke-dasharray: 10px 4px
64 | stroke-width: 3px
65 |
66 | .mindmap-connector-line
67 | fill: transparent
68 | stroke: $grey500
69 | stroke-dasharray: 10px 4px
70 | stroke-width: 3px
71 |
72 | .mindmap-label
73 | fill: $grey500
74 | font-size: 12px
75 | text-anchor: middle
76 |
77 | .mindmap-emoji
78 | height: 24px
79 | vertical-align: bottom
80 | width: 24px
81 |
82 | .mindmap-overlay
83 | fill: $cyan100
84 | stroke: $cyan300
85 | border: 1px solid $cyan200
86 | box-shadow: $shadow
87 |
88 | .reddit-emoji
89 | border-radius: 50%
--------------------------------------------------------------------------------
/src/modules/mindmap/utils/dimensions.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the dimensions (width & height) that some HTML
3 | * with a given style would take in the page.
4 | */
5 | export const getDimensions = (html, style, classname) => {
6 | const el = document.createElement("span");
7 | const dimensions = {};
8 |
9 | // Set display: inline-block so that the size of el
10 | // will depend on the size of its children.
11 | el.style.display = "inline-block";
12 |
13 | // Hide the element (it will be added to the page for a short time).
14 | el.style.visibility = "hidden";
15 |
16 | el.className = classname;
17 | el.innerHTML = html;
18 |
19 | // Apply CSS rules.
20 | Object.keys(style).forEach((rule) => {
21 | el.style[rule] = style[rule];
22 | });
23 | document.body.append(el);
24 |
25 | dimensions.width = el.offsetWidth;
26 | dimensions.height = el.offsetHeight;
27 |
28 | el.remove();
29 | return dimensions;
30 | };
31 |
32 | /*
33 | * Return the dimensions of an SVG viewport calculated from
34 | * some given nodes.
35 | */
36 | export const getViewBox = (nodes) => {
37 | const Xs = [];
38 | const Ys = [];
39 |
40 | nodes.forEach((node) => {
41 | const x = node.x || node.fx;
42 | const y = node.y || node.fy;
43 |
44 | if (x) {
45 | Xs.push(x);
46 | }
47 |
48 | if (y) {
49 | Ys.push(y);
50 | }
51 | });
52 |
53 | if (Xs.length === 0 || Ys.length === 0) {
54 | return "0 0 0 0";
55 | }
56 |
57 | // Find the smallest coordinates...
58 | const min = [Math.min(...Xs) - 150, Math.min(...Ys) - 150];
59 |
60 | // ...and the biggest ones.
61 | const max = [Math.max(...Xs) - min[0] + 150, Math.max(...Ys) - min[1] + 150];
62 |
63 | return `${min.join(" ")} ${max.join(" ")}`;
64 | };
65 |
--------------------------------------------------------------------------------
/src/modules/mindmap/utils/nodeToHTML.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the HTML representation of a node.
3 | * The node is an object that has text, url, and category attributes
4 | * all of them optional.
5 | */
6 | export default (node) => {
7 | return `
8 | `;
22 | };
23 |
--------------------------------------------------------------------------------
/src/modules/mindmap/utils/subnodesToHTML.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the HTML representation of a node.
3 | * The node is an object that has text, url, and category attributes
4 | * all of them optional.
5 | */
6 | const subnodesToHTML = (subnodes = [], fcolor) => {
7 | let color = fcolor || "";
8 |
9 | if (!fcolor && subnodes.length > 0 && subnodes[0].color) {
10 | color = `style="border-left-color: ${subnodes[0].color}"`;
11 | }
12 |
13 | return subnodes
14 | .map((subnode) => {
15 | let href = `href="${subnode.url}"`;
16 |
17 | if (!subnode.url) {
18 | href = "";
19 | }
20 |
21 | return ``;
25 | })
26 | .join("");
27 | };
28 |
29 | export default subnodesToHTML;
30 |
--------------------------------------------------------------------------------
/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuetify from "vuetify/lib/framework";
3 | import colors from "vuetify/lib/util/colors";
4 |
5 | Vue.use(Vuetify);
6 |
7 | const getSavedThemeMod = () =>
8 | localStorage.getItem("isDarkMode") === "true" ? true : false;
9 |
10 | export default new Vuetify({
11 | theme: {
12 | dark: getSavedThemeMod(),
13 | themes: {
14 | dark: {
15 | default: "#6B7280",
16 | primary: "#0C2FF3",
17 | secondary: "#FFFFFF",
18 | third: "#F2F4F7",
19 | black: "#000000",
20 | white: "#FFFFFF",
21 | danger: "#F4284E",
22 | accent: colors.amber.accent2,
23 | warning: colors.orange,
24 | background: "#1F2937",
25 | // accenttext: colors.amber.lighten4,
26 | // darkerblue: "#1d262b",
27 | // componentmain: colors.blueGrey.darken4,
28 | },
29 | light: {
30 | default: "#6B7280",
31 | primary: "#0C2FF3",
32 | secondary: "#111827",
33 | third: "#F2F4F7",
34 | black: "#000000",
35 | white: "#FFFFFF",
36 | danger: "#F4284E",
37 | accent: colors.indigo.accent2,
38 | warning: colors.red.accent3,
39 | background: "#FFFFFF",
40 | // accenttext: colors.indigo.darken2,
41 | // componentmain: colors.blueGrey.lighten5,
42 | },
43 | },
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/src/preload.js:
--------------------------------------------------------------------------------
1 | const { contextBridge, ipcRenderer, webFrame } = require("electron");
2 | window.ipcRenderer = ipcRenderer;
3 |
4 | contextBridge.exposeInMainWorld("ipc", {
5 | invoke: async (channel, data) => {
6 | return await ipcRenderer.invoke(channel, data);
7 | },
8 | on: (channel, func) => {
9 | // Remove any old listeners
10 | ipcRenderer.removeAllListeners(channel);
11 | // Strip event as it includes `sender` and is a security risk
12 | ipcRenderer.on(channel, (event, ...args) => func(...args));
13 | },
14 | clearCache: () => {
15 | webFrame.clearCache();
16 | },
17 | eventNames: () => {
18 | return ipcRenderer.eventNames();
19 | },
20 | });
21 |
--------------------------------------------------------------------------------
/src/services/storageInterface.js:
--------------------------------------------------------------------------------
1 | export default class StorageInterface {
2 | // eslint-disable-next-line
3 | async getState(executionId) {
4 | throw new Error("Method 'getState()' must be implemented.");
5 | }
6 |
7 | // eslint-disable-next-line
8 | async updateState(state) {
9 | throw new Error("Method 'updateState()' must be implemented.");
10 | }
11 |
12 | async getConfig() {
13 | throw new Error("Method 'getConfig()' must be implemented.");
14 | }
15 |
16 | async getCredentials() {
17 | throw new Error("Method 'getCredentials()' must be implemented.");
18 | }
19 |
20 | // eslint-disable-next-line
21 | async updateCredentials(credentials) {
22 | throw new Error("Method 'updateCredentials()' must be implemented.");
23 | }
24 |
25 | async getItems() {
26 | throw new Error("Method 'fetchItems()' must be implemented.");
27 | }
28 |
29 | // eslint-disable-next-line
30 | async getItemById(id) {
31 | throw new Error("Method 'getItemById(id)' must be implemented.");
32 | }
33 |
34 | // eslint-disable-next-line
35 | async updateItems(state) {
36 | throw new Error("Method 'updateItems(state)' must be implemented.");
37 | }
38 |
39 | async getNotes() {
40 | throw new Error("Method 'getNotes()' must be implemented.");
41 | }
42 |
43 | // eslint-disable-next-line
44 | async updateNotes(notes) {
45 | throw new Error("Method 'updateNotes()' must be implemented.");
46 | }
47 |
48 | // eslint-disable-next-line
49 | async createNewSession(state) {
50 | throw new Error("Method 'createNewSession(state)' must be implemented.");
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/store/modules/auth.js:
--------------------------------------------------------------------------------
1 | export const auth = {
2 | namespaced: true,
3 | state: () => ({
4 | isAuthenticated: false,
5 | credentials: {},
6 | }),
7 | mutations: {
8 | setIsAuthenticated(state, payload) {
9 | state.isAuthenticated = payload;
10 | },
11 | setCredentials(state, payload) {
12 | state.credentials = payload;
13 | },
14 | },
15 | actions: {},
16 | getters: {
17 | credentials: (state) => state.credentials,
18 | isAuthenticated: (state) => state.isAuthenticated,
19 | loggedInServices: (state) => {
20 | const services = {};
21 | for (const credentialType of Object.keys(state.credentials)) {
22 | services[credentialType] = state.credentials[credentialType].length > 0;
23 | }
24 | return services;
25 | },
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/src/store/store-config.js:
--------------------------------------------------------------------------------
1 | // Used for tests - TODO clean up
2 | import { SESSION_STATUSES } from "../modules/constants";
3 |
4 | export default {
5 | state: {
6 | title: "",
7 | charter: "",
8 | preconditions: "",
9 | duration: 0,
10 | status: SESSION_STATUSES.PENDING,
11 | timer: 0,
12 | started: "",
13 | ended: "",
14 | quickTest: false,
15 | },
16 | getters: {},
17 | mutations: {
18 | setTitle(state, payload) {
19 | state.title = payload;
20 | },
21 | setCharter(state, payload) {
22 | state.charter = payload;
23 | },
24 | setPrecondition(state, payload) {
25 | state.preconditions = payload;
26 | },
27 | setDuration(state, payload) {
28 | state.duration = payload;
29 | },
30 | setStarted(state, payload) {
31 | state.started = payload;
32 | },
33 | setEnded(state, payload) {
34 | state.ended = payload;
35 | },
36 | setQuickTest(state, payload) {
37 | state.quickTest = payload;
38 | },
39 | updateSession(state, payload) {
40 | state.status = payload.status;
41 | state.timer = payload.timer;
42 | state.duration = payload.duration;
43 | },
44 | resetState(state) {
45 | state.title = "";
46 | state.charter = "";
47 | state.preconditions = "";
48 | state.status = SESSION_STATUSES.PENDING;
49 | state.timer = 0;
50 | state.duration = 0;
51 | state.started = "";
52 | state.ended = "";
53 | state.quickTest = false;
54 | },
55 | },
56 | actions: {},
57 | modules: {},
58 | };
59 |
--------------------------------------------------------------------------------
/src/views/AuthenticationView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
68 |
74 |
--------------------------------------------------------------------------------
/src/views/__tests__/AuthenticationView.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import AuthenticationView from "../AuthenticationView.vue";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | const vuetify = new Vuetify();
7 |
8 | describe("AutheticationView.vue", () => {
9 | test("render a view", () => {
10 | const wrapper = mount(AuthenticationView, {
11 | mocks: {
12 | $t: () => {},
13 | $tc: () => {},
14 | },
15 | vuetify,
16 | });
17 |
18 | expect(wrapper.find(".authentication-wrapper").exists()).toBe(true);
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/src/views/__tests__/HomeView.spec.js:
--------------------------------------------------------------------------------
1 | import HomeView from "../HomeView";
2 | import LogoWrapper from "../../components/LogoWrapper";
3 |
4 | import { mount } from "@vue/test-utils";
5 |
6 | describe("HomeView.vue", () => {
7 | test('displays "New session" button', () => {
8 | const wrapper = mount(HomeView, {
9 | mocks: {
10 | $t: () => {},
11 | $tc: () => {},
12 | },
13 | stubs: ["router-link"],
14 | });
15 |
16 | expect(wrapper.findComponent(LogoWrapper).exists()).toBe(true);
17 |
18 | expect(
19 | wrapper.find(".new-section .text-capitalize:nth-child(1)")
20 | ).toBeTruthy();
21 | // expect(wrapper.text()).toContain("New session");
22 |
23 | expect(
24 | wrapper.find(".open-section .text-capitalize:nth-child(1)")
25 | ).toBeTruthy();
26 | // expect(wrapper.text()).toContain("Open Saved Session");
27 | });
28 |
29 | test('trigger the click envent of "New Session" button', () => {
30 | const wrapper = mount(HomeView, {
31 | mocks: {
32 | $t: () => {},
33 | $tc: () => {},
34 | },
35 | stubs: ["router-link"],
36 | });
37 |
38 | const button = wrapper.find(".new-section .text-capitalize:nth-child(1)");
39 | const event = jest.fn();
40 |
41 | button.vm.$on("click", event);
42 | button.trigger("click");
43 |
44 | expect(event).toHaveBeenCalled();
45 | });
46 |
47 | test('trigger the click event of "Open Saved Session"', () => {
48 | const wrapper = mount(HomeView, {
49 | mocks: {
50 | $t: () => {},
51 | $tc: () => {},
52 | },
53 | stubs: ["router-link"],
54 | });
55 |
56 | const button = wrapper.find(".open-section .text-capitalize:nth-child(1)");
57 | const event = jest.fn();
58 |
59 | button.vm.$on("click", event);
60 | button.trigger("click");
61 |
62 | expect(event).toHaveBeenCalled();
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/src/views/__tests__/LowProfileView.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import LowProfileView from "../LowProfileView.vue";
3 | import ControlPanel from "../../components/ControlPanel.vue";
4 |
5 | import { shallowMount } from "@vue/test-utils";
6 |
7 | const vuetify = new Vuetify();
8 |
9 | describe("LowProfileView.vue", () => {
10 | test("render a view", () => {
11 | const wrapper = shallowMount(LowProfileView, {
12 | mocks: {
13 | $t: () => {},
14 | $tc: () => {},
15 | },
16 | data() {
17 | return {
18 | overlay: true,
19 | };
20 | },
21 | vuetify,
22 | });
23 |
24 | expect(wrapper.find(".header").exists()).toBe(true);
25 | expect(wrapper.find(".header .maximize-btn").exists()).toBe(true);
26 | expect(wrapper.find(".body").exists()).toBe(true);
27 | expect(wrapper.find(".body .overlay").exists()).toBe(true);
28 | expect(wrapper.findComponent(ControlPanel).exists()).toBe(true);
29 | });
30 |
31 | test('trigger the click event of "Maximize" button', () => {
32 | const wrapper = shallowMount(LowProfileView, {
33 | mocks: {
34 | $t: () => {},
35 | $tc: () => {},
36 | },
37 | data() {
38 | return {
39 | overlay: false,
40 | };
41 | },
42 | vuetify,
43 | });
44 |
45 | const event = jest.fn();
46 | const button = wrapper.find(".header .maximize-btn");
47 |
48 | button.vm.$on("click", event);
49 | // button.trigger("click");
50 |
51 | // expect(event).toHaveBeenCalled();
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/src/views/__tests__/PrintView.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import Vuex from "vuex";
3 |
4 | import PrintView from "../PrintView";
5 | import storeConfig from "@/store/store-config";
6 |
7 | import { mount, createLocalVue } from "@vue/test-utils";
8 | import { cloneDeep } from "lodash";
9 |
10 | const vuetify = new Vuetify();
11 | const items = [];
12 | const selected = [];
13 | const localVue = createLocalVue();
14 |
15 | localVue.use(Vuex);
16 |
17 | // const formatTime = (timer) => {
18 | // const seconds = ("0" + (timer % 60)).slice(-2);
19 | // const minutes = ("0" + (parseInt(timer / 60, 10) % 60)).slice(-2);
20 | // const hours = ("0" + (parseInt(timer / 3600, 10) % 24)).slice(-2);
21 |
22 | // return hours + ":" + minutes + ":" + seconds;
23 | // };
24 |
25 | describe("PrintView.vue", () => {
26 | let store;
27 |
28 | beforeEach(() => {
29 | store = new Vuex.Store(cloneDeep(storeConfig));
30 | });
31 |
32 | test("render view", () => {
33 | const wrapper = mount(PrintView, {
34 | mocks: {
35 | $t: () => {},
36 | $tc: () => {},
37 | },
38 | data() {
39 | return {
40 | items,
41 | titie: "",
42 | charter: "",
43 | precondition: "",
44 | window: "",
45 | screenWidth: "",
46 | screenHeight: "",
47 | selected,
48 | timer: "10287209",
49 | };
50 | },
51 | store: {
52 | ...store,
53 | state: {
54 | ...store.state,
55 | },
56 | },
57 | localVue,
58 | vuetify,
59 | });
60 |
61 | expect(wrapper.find(".header").exists()).toBe(true);
62 | expect(wrapper.find(".header img").exists()).toBe(true);
63 | expect(wrapper.find(".content .timeline").exists()).toBe(true);
64 | expect(wrapper.find(".content .detail").exists()).toBe(true);
65 |
66 | expect(wrapper.find(".duration-text span").text()).toContain("");
67 | expect(wrapper.find(".detail .title").exists()).toBe(true);
68 | expect(wrapper.find(".detail .charter").exists()).toBe(true);
69 | expect(wrapper.find(".detail .pre-condition").exists()).toBe(true);
70 | expect(wrapper.find(".detail .session-time").exists()).toBe(true);
71 | expect(wrapper.find(".detail .session-elapsed-time").exists()).toBe(true);
72 | expect(wrapper.find(".detail .environment").exists()).toBe(true);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/src/views/__tests__/SettingView.spec.js:
--------------------------------------------------------------------------------
1 | import Vuetify from "vuetify";
2 | import VueRouter from "vue-router";
3 |
4 | import SettingView from "../SettingView.vue";
5 |
6 | import { mount, createLocalVue } from "@vue/test-utils";
7 |
8 | const vuetify = new Vuetify();
9 |
10 | const localVue = createLocalVue();
11 | localVue.use(VueRouter);
12 |
13 | const router = new VueRouter();
14 |
15 | describe("SettingView.vue", () => {
16 | test("loadin a view", () => {
17 | const wrapper = mount(SettingView, {
18 | mocks: {
19 | $t: () => {},
20 | $tc: () => {},
21 | },
22 | data() {
23 | return {
24 | activeTab: "/settings",
25 | tabs: [{ id: 1, name: "General", route: `/settings` }],
26 | config: {},
27 | };
28 | },
29 | localVue,
30 | router,
31 | vuetify,
32 | });
33 |
34 | expect(wrapper.find(".settings-menu").exists()).toBe(true);
35 | expect(wrapper.findAll(".v-tab").length).toBe(1);
36 | expect(wrapper.findAll(".v-tab-item").length).toBe(0);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/tests/mocks.js:
--------------------------------------------------------------------------------
1 | Object.defineProperty(window, "matchMedia", {
2 | writable: true,
3 | value: jest.fn().mockImplementation((query) => ({
4 | matches: false,
5 | media: query,
6 | onchange: null,
7 | addListener: jest.fn(), // Deprecated
8 | removeListener: jest.fn(), // Deprecated
9 | addEventListener: jest.fn(),
10 | removeEventListener: jest.fn(),
11 | dispatchEvent: jest.fn(),
12 | })),
13 | });
14 |
--------------------------------------------------------------------------------
/tests/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuetify from "vuetify";
3 | import { config } from "@vue/test-utils";
4 |
5 | Vue.config.productionTip = false;
6 | Vue.use(Vuetify);
7 |
8 | config.mocks.$store = { dispatch: jest.fn(), getters: {} };
9 |
10 | // Required for Vuetify
11 | const app = document.createElement("div");
12 | app.setAttribute("data-app", "true");
13 | document.body.appendChild(app);
14 |
15 | // JSDOM does not implement HTMLMediaElement functions
16 | window.HTMLMediaElement.prototype.load = () => {};
17 | window.HTMLMediaElement.prototype.play = () => {};
18 | window.HTMLMediaElement.prototype.pause = () => {};
19 | window.HTMLMediaElement.prototype.addTextTrack = () => {};
20 |
21 | global.console = {
22 | ...console,
23 | log: jest.fn(),
24 | debug: jest.fn(),
25 | error: jest.fn(),
26 | };
27 |
--------------------------------------------------------------------------------
/tests/styleMock.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------