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