Skip to content

Commit 9edfa37

Browse files
test(vue3): add FooterTemplateEditor coverage
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 752279f commit 9edfa37

1 file changed

Lines changed: 203 additions & 0 deletions

File tree

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { beforeEach, describe, expect, it, vi } from 'vitest'
7+
import { flushPromises, mount } from '@vue/test-utils'
8+
9+
import FooterTemplateEditor from '../../components/FooterTemplateEditor.vue'
10+
11+
const axiosGetMock = vi.fn()
12+
const axiosPostMock = vi.fn()
13+
const ensurePdfWorkerMock = vi.fn()
14+
15+
const appConfigMock = {
16+
deleteKey: vi.fn(),
17+
setValue: vi.fn(),
18+
}
19+
20+
const clipboardWriteTextMock = vi.fn()
21+
22+
vi.mock('debounce', () => ({
23+
default: vi.fn((fn: (...args: unknown[]) => unknown) => fn),
24+
}))
25+
26+
vi.mock('@nextcloud/l10n', () => ({
27+
t: vi.fn((_app: string, text: string) => text),
28+
}))
29+
30+
vi.mock('@nextcloud/axios', () => ({
31+
default: {
32+
get: vi.fn((...args: unknown[]) => axiosGetMock(...args)),
33+
post: vi.fn((...args: unknown[]) => axiosPostMock(...args)),
34+
},
35+
}))
36+
37+
vi.mock('@nextcloud/initial-state', () => ({
38+
loadState: vi.fn((_app: string, key: string, defaultValue: unknown) => {
39+
if (key === 'footer_preview_zoom_level') {
40+
return 100
41+
}
42+
if (key === 'footer_template_variables') {
43+
return {
44+
signerName: { description: 'Signer', type: 'string', example: 'Alice' },
45+
}
46+
}
47+
return defaultValue
48+
}),
49+
}))
50+
51+
vi.mock('@nextcloud/router', () => ({
52+
generateOcsUrl: vi.fn((path: string) => `/ocs/v2.php${path}`),
53+
}))
54+
55+
vi.mock('../../helpers/pdfWorker', () => ({
56+
ensurePdfWorker: vi.fn(() => ensurePdfWorkerMock()),
57+
}))
58+
59+
vi.mock('@libresign/pdf-elements/src/components/PDFElements.vue', () => ({
60+
default: {
61+
name: 'PDFElements',
62+
props: ['initialScale'],
63+
template: '<div class="pdf-elements-stub" />',
64+
},
65+
}))
66+
67+
vi.mock('../../components/CodeEditor.vue', () => ({
68+
default: {
69+
name: 'CodeEditor',
70+
props: ['modelValue', 'label', 'placeholder'],
71+
emits: ['update:modelValue'],
72+
template: '<textarea class="code-editor-stub" />',
73+
},
74+
}))
75+
76+
vi.mock('@nextcloud/vue/components/NcButton', () => ({
77+
default: {
78+
name: 'NcButton',
79+
emits: ['click'],
80+
template: '<button class="nc-button-stub" @click="$emit(\'click\')"><slot /><slot name="icon" /></button>',
81+
},
82+
}))
83+
84+
vi.mock('@nextcloud/vue/components/NcDialog', () => ({
85+
default: {
86+
name: 'NcDialog',
87+
template: '<div class="nc-dialog-stub"><slot /><slot name="actions" /></div>',
88+
},
89+
}))
90+
91+
vi.mock('@nextcloud/vue/components/NcFormBoxButton', () => ({
92+
default: {
93+
name: 'NcFormBoxButton',
94+
emits: ['click'],
95+
template: '<button class="nc-form-box-button-stub" @click="$emit(\'click\')"><slot /><slot name="icon" /><slot name="description" /></button>',
96+
},
97+
}))
98+
99+
vi.mock('@nextcloud/vue/components/NcLoadingIcon', () => ({
100+
default: {
101+
name: 'NcLoadingIcon',
102+
template: '<span class="nc-loading-icon-stub" />',
103+
},
104+
}))
105+
106+
vi.mock('@nextcloud/vue/components/NcTextField', () => ({
107+
default: {
108+
name: 'NcTextField',
109+
props: ['modelValue', 'label'],
110+
emits: ['update:modelValue', 'input'],
111+
template: '<input class="nc-text-field-stub" />',
112+
},
113+
}))
114+
115+
vi.mock('@nextcloud/vue/components/NcIconSvgWrapper', () => ({
116+
default: {
117+
name: 'NcIconSvgWrapper',
118+
template: '<i class="nc-icon-svg-wrapper-stub" />',
119+
},
120+
}))
121+
122+
describe('FooterTemplateEditor.vue', () => {
123+
const createWrapper = () => mount(FooterTemplateEditor, {
124+
global: {
125+
directives: {
126+
linkify: vi.fn(),
127+
},
128+
},
129+
})
130+
131+
beforeEach(() => {
132+
axiosGetMock.mockReset()
133+
axiosPostMock.mockReset()
134+
ensurePdfWorkerMock.mockReset()
135+
appConfigMock.deleteKey.mockReset()
136+
appConfigMock.setValue.mockReset()
137+
clipboardWriteTextMock.mockReset()
138+
139+
axiosGetMock.mockResolvedValue({
140+
data: {
141+
ocs: {
142+
data: {
143+
template: 'Footer {{ signerName }}',
144+
preview_height: 120,
145+
preview_width: 640,
146+
},
147+
},
148+
},
149+
})
150+
axiosPostMock.mockResolvedValue({ data: new Blob(['pdf'], { type: 'application/pdf' }) })
151+
152+
vi.stubGlobal('OCP', { AppConfig: appConfigMock })
153+
vi.stubGlobal('navigator', {
154+
clipboard: {
155+
writeText: clipboardWriteTextMock,
156+
},
157+
})
158+
})
159+
160+
it('loads the saved footer template on mount and initializes the PDF worker', async () => {
161+
const wrapper = createWrapper()
162+
await flushPromises()
163+
164+
expect(ensurePdfWorkerMock).toHaveBeenCalledTimes(1)
165+
expect(axiosGetMock).toHaveBeenCalledWith('/ocs/v2.php/apps/libresign/api/v1/admin/footer-template')
166+
expect(wrapper.vm.footerTemplate).toBe('Footer {{ signerName }}')
167+
expect(wrapper.vm.previewWidth).toBe(640)
168+
expect(wrapper.vm.previewHeight).toBe(120)
169+
})
170+
171+
it('copies template variables to the clipboard and marks them as copied', async () => {
172+
const wrapper = createWrapper()
173+
await flushPromises()
174+
175+
wrapper.vm.copyToClipboard('{{ signerName }}')
176+
177+
expect(clipboardWriteTextMock).toHaveBeenCalledWith('{{ signerName }}')
178+
expect(wrapper.vm.isCopied('signerName')).toBe(true)
179+
})
180+
181+
it('resets dimensions and clears the stored app config values', async () => {
182+
const wrapper = createWrapper()
183+
await flushPromises()
184+
185+
wrapper.vm.previewWidth = 700
186+
wrapper.vm.previewHeight = 150
187+
wrapper.vm.resetDimensions()
188+
189+
expect(wrapper.vm.previewWidth).toBe(wrapper.vm.DEFAULT_PREVIEW_WIDTH)
190+
expect(wrapper.vm.previewHeight).toBe(wrapper.vm.DEFAULT_PREVIEW_HEIGHT)
191+
expect(appConfigMock.deleteKey).toHaveBeenCalledWith('libresign', 'footer_preview_width')
192+
expect(appConfigMock.deleteKey).toHaveBeenCalledWith('libresign', 'footer_preview_height')
193+
})
194+
195+
it('updates zoom level through the zoom controls logic', async () => {
196+
const wrapper = createWrapper()
197+
await flushPromises()
198+
199+
wrapper.vm.changeZoomLevel(20)
200+
201+
expect(wrapper.vm.zoomLevel).toBe(120)
202+
})
203+
})

0 commit comments

Comments
 (0)