11import * as prompts from '@inquirer/prompts' ;
22import { issuer } from '@trustvc/trustvc' ;
33import { beforeEach , describe , expect , it , MockedFunction , vi } from 'vitest' ;
4- import { promptForInputs , sign } from '../../src/commands/sign' ;
5- import { SignInput } from '../../src/types' ;
4+ import { promptForInputs , sign } from '../../../ src/commands/w3c /sign' ;
5+ import { SignInput } from '../../../ src/types' ;
66
77
88vi . mock ( '@inquirer/prompts' ) ;
99
10- vi . mock ( '../../src/utils' , async ( ) => {
11- const actual = await vi . importActual < typeof import ( '../../src/utils' ) > ( '../../src/utils' ) ;
10+ vi . mock ( 'signale' , ( ) => ( {
11+ default : {
12+ success : vi . fn ( ) ,
13+ error : vi . fn ( ) ,
14+ warn : vi . fn ( ) ,
15+ info : vi . fn ( ) ,
16+ } ,
17+ Signale : vi . fn ( ) . mockImplementation ( ( ) => ( {
18+ await : vi . fn ( ) ,
19+ success : vi . fn ( ) ,
20+ } ) ) ,
21+ } ) ) ;
22+
23+ vi . mock ( '../../../src/utils' , async ( ) => {
24+ const actual = await vi . importActual < typeof import ( '../../../src/utils' ) > (
25+ '../../../src/utils' ,
26+ ) ;
1227 return {
1328 ...actual ,
1429 readJsonFile : vi . fn ( ) ,
@@ -25,39 +40,6 @@ vi.mock('@trustvc/trustvc', async () => {
2540 } ;
2641} ) ;
2742
28-
29- const mockPromptFlow = (
30- algorithm : 'ecdsa-sd-2023' | 'bbs-2023' = 'ecdsa-sd-2023' ,
31- ) => {
32- ( prompts . input as any )
33- . mockResolvedValueOnce ( './did-keypair.json' )
34- . mockResolvedValueOnce ( './credential.json' )
35- . mockResolvedValueOnce ( '.' ) ;
36-
37- ( prompts . select as any ) . mockResolvedValueOnce ( algorithm ) ;
38- } ;
39-
40- const mockUtilsHappyPath = async (
41- keyPairData = { domain : 'https://example.com' } ,
42- credential = { id : 'urn:uuid:123' } ,
43- ) => {
44- const utils = await import ( '../../src/utils' ) ;
45-
46- ( utils . readJsonFile as MockedFunction < any > )
47- . mockReturnValueOnce ( keyPairData )
48- . mockReturnValueOnce ( credential ) ;
49-
50- ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( true ) ;
51-
52- return utils ;
53- } ;
54-
55- const mockSignSuccess = async ( signed : any ) => {
56- const trustvc = await import ( '@trustvc/trustvc' ) ;
57- ( trustvc . signW3C as MockedFunction < any > ) . mockResolvedValue ( { signed } ) ;
58- } ;
59-
60-
6143describe ( 'w3c-sign' , ( ) => {
6244 beforeEach ( ( ) => {
6345 vi . clearAllMocks ( ) ;
@@ -66,8 +48,17 @@ describe('w3c-sign', () => {
6648
6749 describe ( 'promptForInputs' , ( ) => {
6850 it ( 'returns parsed inputs when algorithm is ecdsa-sd-2023' , async ( ) => {
69- mockPromptFlow ( 'ecdsa-sd-2023' ) ;
70- await mockUtilsHappyPath ( ) ;
51+ ( prompts . input as any )
52+ . mockResolvedValueOnce ( './did-keypair.json' )
53+ . mockResolvedValueOnce ( './credential.json' )
54+ . mockResolvedValueOnce ( '.' ) ;
55+ ( prompts . select as any ) . mockResolvedValueOnce ( 'ecdsa-sd-2023' ) ;
56+
57+ const utils = await import ( '../../../src/utils' ) ;
58+ ( utils . readJsonFile as MockedFunction < any > )
59+ . mockReturnValueOnce ( { domain : 'https://example.com' } )
60+ . mockReturnValueOnce ( { id : 'urn:uuid:123' } ) ;
61+ ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( true ) ;
7162
7263 const result = await promptForInputs ( ) ;
7364
@@ -80,8 +71,17 @@ describe('w3c-sign', () => {
8071 } ) ;
8172
8273 it ( 'returns parsed inputs when algorithm is bbs-2023' , async ( ) => {
83- mockPromptFlow ( 'bbs-2023' ) ;
84- await mockUtilsHappyPath ( ) ;
74+ ( prompts . input as any )
75+ . mockResolvedValueOnce ( './did-keypair.json' )
76+ . mockResolvedValueOnce ( './credential.json' )
77+ . mockResolvedValueOnce ( '.' ) ;
78+ ( prompts . select as any ) . mockResolvedValueOnce ( 'bbs-2023' ) ;
79+
80+ const utils = await import ( '../../../src/utils' ) ;
81+ ( utils . readJsonFile as MockedFunction < any > )
82+ . mockReturnValueOnce ( { domain : 'https://example.com' } )
83+ . mockReturnValueOnce ( { id : 'urn:uuid:123' } ) ;
84+ ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( true ) ;
8585
8686 const result = await promptForInputs ( ) ;
8787
@@ -94,8 +94,17 @@ describe('w3c-sign', () => {
9494 } ) ;
9595
9696 it ( 'provides required validation rules for inputs' , async ( ) => {
97- mockPromptFlow ( 'bbs-2023' ) ;
98- await mockUtilsHappyPath ( ) ;
97+ ( prompts . input as any )
98+ . mockResolvedValueOnce ( './did-keypair.json' )
99+ . mockResolvedValueOnce ( './credential.json' )
100+ . mockResolvedValueOnce ( '.' ) ;
101+ ( prompts . select as any ) . mockResolvedValueOnce ( 'bbs-2023' ) ;
102+
103+ const utils = await import ( '../../../src/utils' ) ;
104+ ( utils . readJsonFile as MockedFunction < any > )
105+ . mockReturnValueOnce ( { domain : 'https://example.com' } )
106+ . mockReturnValueOnce ( { id : 'urn:uuid:123' } ) ;
107+ ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( true ) ;
99108
100109 await promptForInputs ( ) ;
101110
@@ -117,8 +126,17 @@ describe('w3c-sign', () => {
117126 } ) ;
118127
119128 it ( 'prompts for encryption algorithm with supported choices' , async ( ) => {
120- mockPromptFlow ( ) ;
121- await mockUtilsHappyPath ( ) ;
129+ ( prompts . input as any )
130+ . mockResolvedValueOnce ( './did-keypair.json' )
131+ . mockResolvedValueOnce ( './credential.json' )
132+ . mockResolvedValueOnce ( '.' ) ;
133+ ( prompts . select as any ) . mockResolvedValueOnce ( 'ecdsa-sd-2023' ) ;
134+
135+ const utils = await import ( '../../../src/utils' ) ;
136+ ( utils . readJsonFile as MockedFunction < any > )
137+ . mockReturnValueOnce ( { domain : 'https://example.com' } )
138+ . mockReturnValueOnce ( { id : 'urn:uuid:123' } ) ;
139+ ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( true ) ;
122140
123141 await promptForInputs ( ) ;
124142
@@ -134,8 +152,8 @@ describe('w3c-sign', () => {
134152 } ) ;
135153
136154 it ( 'throws when given an invalid did key-pair file path (readJsonFile fails)' , async ( ) => {
137- mockPromptFlow ( 'ecdsa-sd-2023 ') ;
138- const utils = await import ( '../../src/utils' ) ;
155+ ( prompts . input as any ) . mockResolvedValueOnce ( './did-keypair.json ') ;
156+ const utils = await import ( '../../../ src/utils' ) ;
139157
140158 ( utils . readJsonFile as MockedFunction < any > ) . mockImplementation ( ( ) => {
141159 throw new Error ( 'Invalid key pair file path: ./did-keypair.json' ) ;
@@ -147,8 +165,10 @@ describe('w3c-sign', () => {
147165 } ) ;
148166
149167 it ( 'throws when given an invalid credential file path (readJsonFile fails)' , async ( ) => {
150- mockPromptFlow ( 'ecdsa-sd-2023' ) ;
151- const utils = await import ( '../../src/utils' ) ;
168+ ( prompts . input as any )
169+ . mockResolvedValueOnce ( './did-keypair.json' )
170+ . mockResolvedValueOnce ( './credential.json' ) ;
171+ const utils = await import ( '../../../src/utils' ) ;
152172
153173 ( utils . readJsonFile as MockedFunction < any > )
154174 . mockReturnValueOnce ( { domain : 'https://example.com' } )
@@ -163,8 +183,16 @@ describe('w3c-sign', () => {
163183 } ) ;
164184
165185 it ( 'throws when output path is not a valid directory' , async ( ) => {
166- mockPromptFlow ( 'ecdsa-sd-2023' ) ;
167- const utils = await mockUtilsHappyPath ( ) ;
186+ ( prompts . input as any )
187+ . mockResolvedValueOnce ( './did-keypair.json' )
188+ . mockResolvedValueOnce ( './credential.json' )
189+ . mockResolvedValueOnce ( './invalid-dir' ) ;
190+ ( prompts . select as any ) . mockResolvedValueOnce ( 'ecdsa-sd-2023' ) ;
191+
192+ const utils = await import ( '../../../src/utils' ) ;
193+ ( utils . readJsonFile as MockedFunction < any > )
194+ . mockReturnValueOnce ( { domain : 'https://example.com' } )
195+ . mockReturnValueOnce ( { id : 'urn:uuid:123' } ) ;
168196 ( utils . isDirectoryValid as MockedFunction < any > ) . mockReturnValue ( false ) ;
169197
170198 await expect ( promptForInputs ( ) ) . rejects . toThrow ( 'Output path is not valid' ) ;
@@ -175,6 +203,8 @@ describe('w3c-sign', () => {
175203 describe ( 'sign' , ( ) => {
176204 let writeFileMock : MockedFunction < any > ;
177205 let signW3CMock : MockedFunction < any > ;
206+ let signaleSuccessMock : MockedFunction < any > ;
207+ let signaleErrorMock : MockedFunction < any > ;
178208
179209 const input : SignInput = {
180210 keyPairData : { domain : 'https://example.com' } as typeof issuer . IssuedDIDOption ,
@@ -184,11 +214,15 @@ describe('w3c-sign', () => {
184214 } ;
185215
186216 beforeEach ( async ( ) => {
187- const utils = await import ( '../../src/utils' ) ;
217+ const utils = await import ( '../../../ src/utils' ) ;
188218 writeFileMock = utils . writeFile as MockedFunction < any > ;
189219
190220 const trustvc = await import ( '@trustvc/trustvc' ) ;
191221 signW3CMock = trustvc . signW3C as MockedFunction < any > ;
222+
223+ const signale = await import ( 'signale' ) ;
224+ signaleSuccessMock = ( signale . default as any ) . success ;
225+ signaleErrorMock = ( signale . default as any ) . error ;
192226 } ) ;
193227
194228 it ( 'signs with ecdsa-sd-2023 and writes to default output path' , async ( ) => {
@@ -202,6 +236,10 @@ describe('w3c-sign', () => {
202236 'ecdsa-sd-2023' ,
203237 ) ;
204238 expect ( writeFileMock ) . toHaveBeenCalledWith ( './signed_vc.json' , { proof : 'ok' } ) ;
239+ expect ( signaleSuccessMock ) . toHaveBeenCalledWith (
240+ expect . stringContaining ( 'Signed verifiable credential saved to: .' ) ,
241+ ) ;
242+ expect ( signaleErrorMock ) . not . toHaveBeenCalled ( ) ;
205243 } ) ;
206244
207245 it ( 'signs with bbs-2023 and writes to a custom output directory' , async ( ) => {
@@ -219,6 +257,10 @@ describe('w3c-sign', () => {
219257 'bbs-2023' ,
220258 ) ;
221259 expect ( writeFileMock ) . toHaveBeenCalledWith ( './out/signed_vc.json' , { proof : 'ok' } ) ;
260+ expect ( signaleSuccessMock ) . toHaveBeenCalledWith (
261+ expect . stringContaining ( 'Signed verifiable credential saved to: ./out' ) ,
262+ ) ;
263+ expect ( signaleErrorMock ) . not . toHaveBeenCalled ( ) ;
222264 } ) ;
223265
224266 it ( 'does not write file when signing fails' , async ( ) => {
@@ -227,6 +269,8 @@ describe('w3c-sign', () => {
227269 await sign ( input ) ;
228270
229271 expect ( writeFileMock ) . not . toHaveBeenCalled ( ) ;
272+ expect ( signaleSuccessMock ) . not . toHaveBeenCalled ( ) ;
273+ expect ( signaleErrorMock ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Failed to sign' ) ) ;
230274 } ) ;
231275
232276 it ( 'throws when writing signed VC fails' , async ( ) => {
0 commit comments