Skip to content

Commit 6145279

Browse files
authored
Merge pull request #248 from nextcloud/feat/add-tests
feat: add tests
2 parents 0bef176 + 423d4bb commit 6145279

19 files changed

Lines changed: 1769 additions & 632 deletions

‎.eslintrc.cjs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
extends: [
3+
'@nextcloud/eslint-config',
4+
],
5+
globals: {
6+
OCA: 'readonly',
7+
OC: 'readonly',
8+
},
9+
overrides: [
10+
{
11+
files: ['src/__tests__/**/*'],
12+
rules: {
13+
'n/no-unpublished-import': 'off',
14+
'jsdoc/require-jsdoc': 'off',
15+
},
16+
},
17+
],
18+
}

‎.github/workflows/lint-eslint.yml‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# This workflow is provided via the organization template repository
2+
#
3+
# https://github.com/nextcloud/.github
4+
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
5+
#
6+
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
7+
# SPDX-License-Identifier: MIT
8+
9+
name: Lint eslint
10+
11+
on: pull_request
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: lint-eslint-${{ github.head_ref || github.run_id }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
changes:
22+
runs-on: ubuntu-latest-low
23+
permissions:
24+
contents: read
25+
pull-requests: read
26+
27+
outputs:
28+
src: ${{ steps.changes.outputs.src}}
29+
30+
steps:
31+
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
32+
id: changes
33+
continue-on-error: true
34+
with:
35+
filters: |
36+
src:
37+
- '.github/workflows/**'
38+
- 'src/**'
39+
- 'appinfo/info.xml'
40+
- 'package.json'
41+
- 'package-lock.json'
42+
- 'tsconfig.json'
43+
- '.eslintrc.*'
44+
- '.eslintignore'
45+
- '**.js'
46+
- '**.ts'
47+
- '**.vue'
48+
49+
lint:
50+
runs-on: ubuntu-latest
51+
52+
needs: changes
53+
if: needs.changes.outputs.src != 'false'
54+
55+
name: NPM lint
56+
57+
steps:
58+
- name: Checkout
59+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
60+
with:
61+
persist-credentials: false
62+
63+
- name: Read package.json node and npm engines version
64+
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
65+
id: versions
66+
with:
67+
fallbackNode: '^24'
68+
fallbackNpm: '^11.3'
69+
70+
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
71+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
72+
with:
73+
node-version: ${{ steps.versions.outputs.nodeVersion }}
74+
75+
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
76+
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
77+
78+
- name: Install dependencies
79+
env:
80+
CYPRESS_INSTALL_BINARY: 0
81+
PUPPETEER_SKIP_DOWNLOAD: true
82+
run: npm ci
83+
84+
- name: Lint
85+
run: npm run lint
86+
87+
summary:
88+
permissions:
89+
contents: none
90+
runs-on: ubuntu-latest-low
91+
needs: [changes, lint]
92+
93+
if: always()
94+
95+
# This is the summary, we just avoid to rename it so that branch protection rules still match
96+
name: eslint
97+
98+
steps:
99+
- name: Summary status
100+
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi

‎.github/workflows/node-test.yml‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# This workflow is provided via the organization template repository
2+
#
3+
# https://github.com/nextcloud/.github
4+
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
5+
#
6+
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
7+
# SPDX-License-Identifier: MIT
8+
9+
name: Node tests
10+
11+
on:
12+
pull_request:
13+
push:
14+
branches:
15+
- main
16+
- master
17+
- stable*
18+
19+
permissions:
20+
contents: read
21+
22+
concurrency:
23+
group: node-tests-${{ github.head_ref || github.run_id }}
24+
cancel-in-progress: true
25+
26+
jobs:
27+
changes:
28+
runs-on: ubuntu-latest-low
29+
permissions:
30+
contents: read
31+
pull-requests: read
32+
33+
outputs:
34+
src: ${{ steps.changes.outputs.src}}
35+
36+
steps:
37+
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
38+
id: changes
39+
continue-on-error: true
40+
with:
41+
filters: |
42+
src:
43+
- '.github/workflows/**'
44+
- 'src/**'
45+
- 'appinfo/info.xml'
46+
- 'package.json'
47+
- 'package-lock.json'
48+
- 'tsconfig.json'
49+
- 'vitest.config.*'
50+
- '**.js'
51+
- '**.ts'
52+
- '**.vue'
53+
54+
test:
55+
runs-on: ubuntu-latest
56+
57+
needs: changes
58+
if: needs.changes.outputs.src != 'false'
59+
60+
steps:
61+
- name: Checkout
62+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
63+
with:
64+
persist-credentials: false
65+
66+
- name: Read package.json node and npm engines version
67+
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
68+
id: versions
69+
with:
70+
fallbackNode: '^24'
71+
fallbackNpm: '^11.3'
72+
73+
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
74+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
75+
with:
76+
node-version: ${{ steps.versions.outputs.nodeVersion }}
77+
78+
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
79+
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
80+
81+
- name: Install dependencies & build
82+
env:
83+
CYPRESS_INSTALL_BINARY: 0
84+
PUPPETEER_SKIP_DOWNLOAD: true
85+
run: |
86+
npm ci
87+
npm run build --if-present
88+
89+
- name: Test
90+
run: npm run test
91+
92+
summary:
93+
permissions:
94+
contents: none
95+
runs-on: ubuntu-latest-low
96+
needs: [changes, test]
97+
98+
if: always()
99+
100+
name: npm-test-summary
101+
102+
steps:
103+
- name: Summary status
104+
run: if ${{ needs.changes.outputs.src != 'false' && needs.test.result != 'success' }}; then exit 1; fi

‎package.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
"build": "vite --mode production build",
2525
"dev": "vite --mode development build",
2626
"watch": "vite --mode development build --watch",
27+
"lint": "ESLINT_USE_FLAT_CONFIG=false eslint --ext .js,.vue,.ts src",
2728
"test": "vitest run",
2829
"test:watch": "vitest"
2930
},
3031
"dependencies": {
3132
"@mdi/svg": "^7.3.67",
33+
"@nextcloud/auth": "^2.5.0",
3234
"@nextcloud/axios": "^2.4.0",
3335
"@nextcloud/dialogs": "^5.0.0",
3436
"@nextcloud/event-bus": "^3.1.0",
@@ -37,6 +39,8 @@
3739
"@nextcloud/l10n": "^3.0.0",
3840
"@nextcloud/logger": "^3.0.0",
3941
"@nextcloud/paths": "^3.0.0",
42+
"@nextcloud/router": "^3.1.0",
43+
"@nextcloud/sharing": "^0.3.0",
4044
"jszip": "^3.10.1"
4145
},
4246
"devDependencies": {

‎src/__tests__/MindMap.spec.js‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2+
import { shallowMount } from '@vue/test-utils'
3+
import MindMap from '../views/MindMap.vue'
4+
5+
vi.mock('@nextcloud/l10n', () => ({ getLanguage: () => 'en' }))
6+
vi.mock('@nextcloud/router', () => ({
7+
generateUrl: (path, params = {}) =>
8+
Object.entries(params).reduce(
9+
(acc, [k, v]) => acc.replace(`{${k}}`, v ?? ''),
10+
path,
11+
),
12+
}))
13+
vi.mock('@nextcloud/sharing/public', () => ({
14+
isPublicShare: vi.fn(() => false),
15+
getSharingToken: () => '',
16+
}))
17+
18+
// Viewer mixin that supplies the props/methods the component expects
19+
const viewerMixin = {
20+
data() {
21+
return {
22+
fileList: [],
23+
fileid: null,
24+
source: null,
25+
davPath: null,
26+
}
27+
},
28+
methods: {
29+
doneLoading() {},
30+
handleWebviewerloaded() {},
31+
},
32+
}
33+
34+
function mountMindMap(dataOverrides = {}) {
35+
return shallowMount(MindMap, {
36+
mixins: [
37+
{
38+
...viewerMixin,
39+
data() {
40+
return { ...viewerMixin.data(), ...dataOverrides }
41+
},
42+
},
43+
],
44+
})
45+
}
46+
47+
describe('MindMap.vue', () => {
48+
beforeEach(() => {
49+
window.OCA = { FilesMindMap: { setFile: vi.fn() } }
50+
})
51+
52+
afterEach(() => {
53+
delete window.OCA
54+
})
55+
56+
it('renders an iframe element', () => {
57+
const wrapper = mountMindMap()
58+
expect(wrapper.find('iframe').exists()).toBe(true)
59+
})
60+
61+
describe('iframeSrc computed property', () => {
62+
it('uses source when available', () => {
63+
const wrapper = mountMindMap({
64+
source: '/remote.php/dav/files/user/test.km',
65+
})
66+
expect(wrapper.vm.iframeSrc).toContain('/remote.php/dav/files/user/test.km')
67+
})
68+
69+
it('falls back to davPath when source is null', () => {
70+
const wrapper = mountMindMap({
71+
source: null,
72+
davPath: '/dav/path/test.km',
73+
})
74+
expect(wrapper.vm.iframeSrc).toContain('/dav/path/test.km')
75+
})
76+
})
77+
78+
describe('file computed property', () => {
79+
it('returns the file whose fileid matches the current fileid', () => {
80+
const file = { fileid: 7, name: 'test.km' }
81+
const wrapper = mountMindMap({ fileList: [file], fileid: 7 })
82+
expect(wrapper.vm.file).toBe(file)
83+
})
84+
85+
it('returns undefined when no file matches', () => {
86+
const wrapper = mountMindMap({
87+
fileList: [{ fileid: 1, name: 'other.km' }],
88+
fileid: 99,
89+
})
90+
expect(wrapper.vm.file).toBeUndefined()
91+
})
92+
})
93+
94+
describe('lifecycle hooks', () => {
95+
it('calls OCA.FilesMindMap.setFile on mount', () => {
96+
mountMindMap({
97+
fileList: [{ fileid: 3, name: 'test.km' }],
98+
fileid: 3,
99+
})
100+
expect(window.OCA.FilesMindMap.setFile).toHaveBeenCalled()
101+
})
102+
103+
it('removes the webviewerloaded event listener on destroy', () => {
104+
const spy = vi.spyOn(document, 'removeEventListener')
105+
const wrapper = mountMindMap()
106+
wrapper.destroy()
107+
expect(spy).toHaveBeenCalledWith('webviewerloaded', expect.anything())
108+
spy.mockRestore()
109+
})
110+
})
111+
})

0 commit comments

Comments
 (0)