Skip to content

Commit ad31f0a

Browse files
test(vue3): add CertificateContent coverage
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent cb15e71 commit ad31f0a

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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 { mount } from '@vue/test-utils'
8+
9+
import CertificateContent from '../../../views/ReadCertificate/CertificateContent.vue'
10+
11+
const selectCustonOptionMock = vi.fn()
12+
13+
vi.mock('@nextcloud/l10n', () => ({
14+
t: vi.fn((_app: string, text: string, params?: Record<string, string | number>) => {
15+
if (!params) {
16+
return text
17+
}
18+
return text.replace('{number}', String(params.number ?? ''))
19+
}),
20+
}))
21+
22+
vi.mock('../../../helpers/certification', () => ({
23+
selectCustonOption: vi.fn((...args: unknown[]) => selectCustonOptionMock(...args)),
24+
}))
25+
26+
vi.mock('@nextcloud/vue/components/NcSettingsSection', () => ({
27+
default: {
28+
name: 'NcSettingsSection',
29+
props: ['name'],
30+
template: '<section class="nc-settings-section-stub"><h3>{{ name }}</h3><slot /></section>',
31+
},
32+
}))
33+
34+
vi.mock('@nextcloud/vue/components/NcNoteCard', () => ({
35+
default: {
36+
name: 'NcNoteCard',
37+
props: ['type', 'heading'],
38+
template: '<article class="nc-note-card-stub"><h4>{{ heading }}</h4><slot /></article>',
39+
},
40+
}))
41+
42+
vi.mock('@nextcloud/vue/components/NcChip', () => ({
43+
default: {
44+
name: 'NcChip',
45+
props: ['text'],
46+
template: '<span class="nc-chip-stub">{{ text }}<slot /></span>',
47+
},
48+
}))
49+
50+
vi.mock('@nextcloud/vue/components/NcIconSvgWrapper', () => ({
51+
default: {
52+
name: 'NcIconSvgWrapper',
53+
template: '<i class="nc-icon-svg-wrapper-stub" />',
54+
},
55+
}))
56+
57+
describe('CertificateContent.vue', () => {
58+
const baseCertificate = {
59+
subject: { CN: 'Ada Lovelace', emailAddress: 'ada@example.com' },
60+
issuer: { CN: 'LibreSign CA' },
61+
valid_from: '2025-01-01',
62+
valid_to: '2027-01-01',
63+
validTo_time_t: Math.floor(new Date('2027-01-01T00:00:00Z').getTime() / 1000),
64+
crl_validation: 'valid',
65+
extensions: { keyUsage: 'Digital Signature' },
66+
purposes: {
67+
0: [true, true, 'codesign'],
68+
},
69+
}
70+
71+
const createWrapper = (certificate = baseCertificate, index = '0') => mount(CertificateContent, {
72+
props: {
73+
certificate,
74+
index,
75+
},
76+
global: {
77+
stubs: {
78+
CertificateContent: {
79+
name: 'CertificateContent',
80+
template: '<div class="certificate-content-recursive-stub" />',
81+
},
82+
},
83+
},
84+
})
85+
86+
beforeEach(() => {
87+
selectCustonOptionMock.mockReset()
88+
selectCustonOptionMock.mockReturnValue({
89+
isSome: () => false,
90+
})
91+
})
92+
93+
it('shows purposes only for the root certificate entry', async () => {
94+
const wrapper = createWrapper()
95+
96+
expect(wrapper.vm.shouldShowPurposes).toBe(true)
97+
expect(wrapper.text()).toContain('Certificate purposes')
98+
99+
await wrapper.setProps({ index: '1' })
100+
101+
expect(wrapper.vm.shouldShowPurposes).toBe(false)
102+
})
103+
104+
it('maps certificate validity and crl status to display metadata', () => {
105+
const wrapper = createWrapper()
106+
107+
expect(wrapper.vm.certificateValidityStatus.text).toBe('Valid')
108+
expect(wrapper.vm.crlValidationStatus.text).toBe('Valid (Not Revoked)')
109+
110+
const expiredWrapper = createWrapper({
111+
...baseCertificate,
112+
validTo_time_t: Math.floor(new Date('2020-01-01T00:00:00Z').getTime() / 1000),
113+
crl_validation: 'unexpected',
114+
})
115+
116+
expect(expiredWrapper.vm.certificateValidityStatus.text).toBe('Expired')
117+
expect(expiredWrapper.vm.crlValidationStatus.text).toBe('Unknown Status')
118+
})
119+
120+
it('formats labels using custom certification metadata when available', () => {
121+
selectCustonOptionMock.mockReturnValue({
122+
isSome: () => true,
123+
unwrap: () => ({ label: 'signerName' }),
124+
})
125+
126+
const wrapper = createWrapper()
127+
128+
expect(wrapper.vm.getLabelFromId('CN')).toBe('Signer Name')
129+
expect(wrapper.vm.camelCaseToTitleCase('serialNumberHex')).toBe('Serial Number Hex')
130+
})
131+
132+
it('labels chain certificates according to their position and self-signed state', () => {
133+
const wrapper = createWrapper()
134+
135+
expect(wrapper.vm.getChainCertificateLabel(0, baseCertificate)).toBe('Intermediate Certificate')
136+
expect(wrapper.vm.getChainCertificateLabel(1, {
137+
subject: { CN: 'Root' },
138+
issuer: { CN: 'Root' },
139+
})).toBe('Root Certificate (CA)')
140+
expect(wrapper.vm.getChainCertificateLabel(2, {
141+
subject: { CN: 'Leaf' },
142+
issuer: { CN: 'Issuer' },
143+
})).toBe('Certificate 3')
144+
})
145+
})

0 commit comments

Comments
 (0)