import { jest } from '@jest/globals'; import { RevocationValidator } from '../../../../src/validators/credential/revocationValidator.js'; import { StatusListCredentialFetcher } from '../../../../src/resolvers/statusListCredentialFetcher.js'; import { mock } from 'jest-mock-extended'; describe('revocationValidator', () => { const statusListCredentialFetcher = mock(); let revocationValidator: RevocationValidator; beforeEach(() => { revocationValidator = new RevocationValidator(statusListCredentialFetcher); jest.resetAllMocks(); }); it('validate a non revoked credential', async () => { const statusListCredential = { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://w3id.org/vc-status-list-2021/v1', ], id: 'https://api.vidchain.net/api/v1/revocation/status-list/213', type: ['VerifiableCredential', 'StatusList2021Credential'], issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', issuanceDate: '2024-03-20T16:00:18.000Z', credentialSubject: { encodedList: 'eJzt0dEJACAIBcCVdP/lQirIAaqfO1B46IdgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/lqjO3WZl9x9ihb/NU1jN+H3HbAJ1aBe0=', id: 'https://api.vidchain.net/api/v1/revocation/status-list/213', type: 'RevocationList2021', }, proof: { type: 'EcdsaSecp256k1Signature2019', created: '2024-03-20T16:00:18.000Z', proofPurpose: 'assertionMethod', verificationMethod: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22#ccbrSsEgCzdEmgYq7OQZ7ganmp44gEwBaHfO7sy7bao=', jws: 'eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6ZXRocjoweDIzMzYyYkNENjBmNzRmMDk2MEU5OWUwNzU2MTk3NEMyNzhBZjdhMjIjY2NiclNzRWdDemRFbWdZcTdPUVo3Z2FubXA0NGdFd0JhSGZPN3N5N2Jhbz0iLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3MTA5NTA0MTgsImlzcyI6ImRpZDpldGhyOjB4MjMzNjJiQ0Q2MGY3NGYwOTYwRTk5ZTA3NTYxOTc0QzI3OEFmN2EyMiIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93M2lkLm9yZy92Yy1zdGF0dXMtbGlzdC0yMDIxL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImVuY29kZWRMaXN0IjoiZUp6dDBkRUpBQ0FJQmNDVmRQL2xRaXJJQWFxZk8xQjQ2SWRnQkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUkvbHFqTzNXWmw5eDlpaGIvTlUxak4rSDNIYkFKMWFCZTA9IiwiaWQiOiJodHRwczovL2Rldi52aWRjaGFpbi5uZXQvYXBpL3YxL3Jldm9jYXRpb24vc3RhdHVzLWxpc3QvMjEzIiwidHlwZSI6IlJldm9jYXRpb25MaXN0MjAyMSJ9LCJpZCI6Imh0dHBzOi8vZGV2LnZpZGNoYWluLm5ldC9hcGkvdjEvcmV2b2NhdGlvbi9zdGF0dXMtbGlzdC8yMTMiLCJpc3N1ZWQiOiIyMDI0LTAzLTIwVDE2OjAwOjE4LjgzM1oiLCJpc3N1ZXIiOiJkaWQ6ZXRocjoweDIzMzYyYkNENjBmNzRmMDk2MEU5OWUwNzU2MTk3NEMyNzhBZjdhMjIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiU3RhdHVzTGlzdDIwMjFDcmVkZW50aWFsIl19fQ.dqK7tvImbqEuVuLfO4FsOnmM1HqW5BLWDcwEhgB8sVFK8w4LNEikCiw0IplA-eqqJFdmsscB0n88Fy_LGwG0Sg', }, }; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://api.vidchain.net/api/v1/contexts/v1', ], credentialStatus: { id: 'https://api.vidchain.net/api/v1/revocation/credential-status/status-list/213/credential/278', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/213', statusListIndex: '278', type: 'RevocationList2021', }, credentialSubject: { email: 'example@validatedid.com', id: 'did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbpowbhpY5RXvM8JEKkZ4xG33iKWBAnrTYpggXjMCzXXze8qJ9DtLzn11zGnGD36kwmFyqCs9Qc7sogQeoAqMU7ReSiYymmVVD5CWHRw7m8xou6b84KuQ7KzdsSzbYWUuVyn', }, id: 'urn:uuid:106553c2-5888-42bf-8f5d-e8920de9bd98', issuer: { id: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', name: 'Validated ID SL', }, type: ['VerifiableCredential', 'EmailCredential'], }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListCredential, ); const result = await revocationValidator.validate(credential); expect(result).toStrictEqual({ valid: true }); }); it('not validate a revoked credential', async () => { const statusListCredential = { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://w3id.org/vc-status-list-2021/v1', ], id: 'https://api.vidchain.net/api/v1/revocation/status-list/88', type: ['VerifiableCredential', 'StatusList2021Credential'], issuer: 'did:ethr:0x3b0a84556e1ccd4Dc2C48c21F27544aCccd26578', issuanceDate: '2023-11-17T12:39:20.000Z', credentialSubject: { encodedList: 'eJztzEERAAAMAqBK2r/cQvjbQQASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Il2HQ5dogXT', id: 'https://api.vidchain.net/api/v1/revocation/status-list/88', type: 'RevocationList2021', }, proof: { type: 'EcdsaSecp256k1Signature2019', created: '2023-11-17T12:39:20.000Z', proofPurpose: 'assertionMethod', verificationMethod: 'did:ethr:0x3b0a84556e1ccd4Dc2C48c21F27544aCccd26578#MbRMVda/6mNdejCh6V9VgzNcC4ujCQ7eR+brCzQW/7k=', jws: 'eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6ZXRocjoweDNiMGE4NDU1NmUxY2NkNERjMkM0OGMyMUYyNzU0NGFDY2NkMjY1NzgjTWJSTVZkYS82bU5kZWpDaDZWOVZnek5jQzR1akNRN2VSK2JyQ3pRVy83az0iLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3MDAyMjQ3NjAsImlzcyI6ImRpZDpldGhyOjB4M2IwYTg0NTU2ZTFjY2Q0RGMyQzQ4YzIxRjI3NTQ0YUNjY2QyNjU3OCIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93M2lkLm9yZy92Yy1zdGF0dXMtbGlzdC0yMDIxL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImVuY29kZWRMaXN0IjoiZUp6dHpqRU5BQUFJQXpCTHc3ODVSSXlFcDFYUUJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUkvbHFqTzNXWmw5eDlpaGIvTlUxak4rSDNIYkFKMWFCZTA9IiwiaWQiOiJodHRwczovL2Rldi52aWRjaGFpbi5uZXQvYXBpL3YxL3Jldm9jYXRpb24vc3RhdHVzLWxpc3QvODgiLCJpc3N1ZWQiOiIyMDIzLTExLTE3VDEyOjM5OjE2LjUyNFoiLCJpc3N1ZXIiOiJkaWQ6ZXRocjoweDNiMGE4NDU1NmUxY2NkNERjMkM0OGMyMUYyNzU0NGFDY2NkMjY1NzgiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiU3RhdHVzTGlzdDIwMjFDcmVkZW50aWFsIl19fQ.QP-N1utgfXGAjg-bghQYkXUZcOZ4Dv0NtlMBjY745WmhEmCtC63NDJ8nSh9-ZmAqyo1KnqNs8evZoXnoMdQXSA', }, }; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://api.vidchain.net/api/v1/contexts/v1', ], credentialStatus: { id: 'https://api.vidchain.net/api/v1/revocation/credential-status/status-list/213/credential/278', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/213', statusListIndex: '64', type: 'RevocationList2021', }, credentialSubject: { email: 'example@validatedid.com', id: 'did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbpowbhpY5RXvM8JEKkZ4xG33iKWBAnrTYpggXjMCzXXze8qJ9DtLzn11zGnGD36kwmFyqCs9Qc7sogQeoAqMU7ReSiYymmVVD5CWHRw7m8xou6b84KuQ7KzdsSzbYWUuVyn', }, id: 'urn:uuid:106553c2-5888-42bf-8f5d-e8920de9bd98', issuer: { id: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', name: 'Validated ID SL', }, type: ['VerifiableCredential', 'EmailCredential'], }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListCredential, ); const result = await revocationValidator.validate(credential); expect(result).toStrictEqual({ valid: false, message: `${credential.vc.id} is revoked`, }); }); it('return valid true when credential has no credentialStatus', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:no-status', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, }, }; const result = await revocationValidator.validate(credential as any); expect(result).toStrictEqual({ valid: true }); expect( statusListCredentialFetcher.getStatusListCredential, ).not.toHaveBeenCalled(); }); it('throw when status list credential cannot be loaded', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:missing-status-list', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, credentialStatus: { id: 'status-id', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/404', statusListIndex: '1', type: 'RevocationList2021', }, }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( undefined as any, ); await expect( revocationValidator.validate(credential as any), ).rejects.toThrow('Unable to get Status List Credential'); }); it('throw when both credentialStatus and token status are present', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:duplicate-status', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, status: { status_list: { uri: 'https://api.vidchain.net/api/v1/revocation/status-list/213', idx: 9, }, }, credentialStatus: { id: 'status-id', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/213', statusListIndex: '9', type: 'RevocationList2021', }, }, }; await expect( revocationValidator.validate(credential as any), ).rejects.toThrow( 'Invalid status reference: both TokenStatusList and CredentialStatus present', ); }); it('throw when credentialStatus uri is missing', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:missing-uri', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, credentialStatus: { id: 'status-id', statusListCredential: undefined, statusListIndex: '1', type: 'RevocationList2021', }, }, }; await expect( revocationValidator.validate(credential as any), ).rejects.toThrow('Invalid CredentialStatus: missing uri'); }); it('throw when credentialStatus index is missing', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:missing-index', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, credentialStatus: { id: 'status-id', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/213', statusListIndex: undefined, type: 'RevocationList2021', }, }, }; await expect( revocationValidator.validate(credential as any), ).rejects.toThrow('Invalid CredentialStatus: missing index'); }); it('throw when credentialStatus index is not an integer', async () => { const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:invalid-index', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test', }, credentialStatus: { id: 'status-id', statusListCredential: 'https://api.vidchain.net/api/v1/revocation/status-list/213', statusListIndex: '1.5', type: 'RevocationList2021', }, }, }; await expect( revocationValidator.validate(credential as any), ).rejects.toThrow('Invalid CredentialStatus: index must be integer'); }); it('validate a non revoked credential with TokenStatusList via credentialStatus', async () => { const statusListJwt = 'eyJhbGciOiJFUzI1NiIsImtpZCI6IjhkNjY3NGYxLWNkZmMtNGU4Ny05MjEyLTRlMTI0YzkwOGI5ZSIsInR5cCI6InN0YXR1c2xpc3Qrand0In0.eyJpc3MiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92MS8xMTEiLCJzdWIiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92Mi8xMTEvc3RhdHVzX2xpc3QiLCJzdGF0dXNfbGlzdCI6eyJiaXRzIjoxLCJsc3QiOiJlTnBqWUVBQUFBQU1BQUUifSwiaWF0IjoxNzc2MDc2MTU5fQ.CjoRjUjFDHtprmS0GtyswYRpzlUME6remMZsZzl-hEvZXVdQxqu516v5vSq3QvBBJlTfYhWVxRij_ZP5WyiPnQ'; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:token-status-list-valid', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test' }, credentialStatus: { id: 'https://example.com/status/credential/1', type: 'TokenStatusList', statusListCredential: 'https://example.com/status-list/1', statusListIndex: '0', }, }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListJwt as any, ); const result = await revocationValidator.validate(credential as any); expect(result).toStrictEqual({ valid: true }); }); it('not validate a revoked credential with TokenStatusList via credentialStatus', async () => { const statusListJwt = 'eyJhbGciOiJFUzI1NiIsImtpZCI6IjhkNjY3NGYxLWNkZmMtNGU4Ny05MjEyLTRlMTI0YzkwOGI5ZSIsInR5cCI6InN0YXR1c2xpc3Qrand0In0.eyJpc3MiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92MS8xMTEiLCJzdWIiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92Mi8xMTEvc3RhdHVzX2xpc3QiLCJzdGF0dXNfbGlzdCI6eyJiaXRzIjoxLCJsc3QiOiJlTnBqWUdCZ2tHQ0FBQUFBekFBWiJ9LCJpYXQiOjE3NzYwOTAwMjh9.RAVr4krqjvqcZTYhitB50iXud44kAF89uKbQGpSG7FrKKbp3e63KC7zKpnsOdJAPKuWSS578YLNB_W12Ppnr8g'; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:token-status-list-revoked', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test' }, credentialStatus: { id: 'https://example.com/status/credential/1', type: 'TokenStatusList', statusListCredential: 'https://example.com/status-list/1', statusListIndex: '36', }, }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListJwt as any, ); const result = await revocationValidator.validate(credential as any); expect(result).toStrictEqual({ valid: false, message: 'urn:uuid:token-status-list-revoked is revoked', }); }); it('throw error if is expected a credentialStatus received and is received a TokenStatusList JWT', async () => { const statusListJwt = 'eyJhbGciOiJFUzI1NiIsImtpZCI6IjhkNjY3NGYxLWNkZmMtNGU4Ny05MjEyLTRlMTI0YzkwOGI5ZSIsInR5cCI6InN0YXR1c2xpc3Qrand0In0.eyJpc3MiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92MS8xMTEiLCJzdWIiOiJodHRwczovL2Z1bmRpYy11bnRhdXRvbG9naWNhbGx5LWRvcmV0aGVhLm5ncm9rLWZyZWUuZGV2L2lzc3VhbmNlL2FwaS92Mi8xMTEvc3RhdHVzX2xpc3QiLCJzdGF0dXNfbGlzdCI6eyJiaXRzIjoxLCJsc3QiOiJlTnBqWUdCZ2tHQ0FBQUFBekFBWiJ9LCJpYXQiOjE3NzYwOTAwMjh9.RAVr4krqjvqcZTYhitB50iXud44kAF89uKbQGpSG7FrKKbp3e63KC7zKpnsOdJAPKuWSS578YLNB_W12Ppnr8g'; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:token-status-list-revoked', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test' }, credentialStatus: { id: 'https://example.com/status/credential/1', type: 'BitstringStatusListEntry', statusListCredential: 'https://example.com/status-list/1', statusListIndex: '36', }, }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListJwt as any, ); await expect( revocationValidator.validate(credential as any), ).rejects.toThrow( 'Expected a JWT with a vc payload for CredentialStatus types', ); }); it('throw error if TokenStatusList is expected but a JSON credential is received', async () => { const statusListCredential = { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://w3id.org/vc-status-list-2021/v1', ], id: 'https://api.vidchain.net/api/v1/revocation/status-list/213', type: ['VerifiableCredential', 'StatusList2021Credential'], issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', issuanceDate: '2024-03-20T16:00:18.000Z', credentialSubject: { encodedList: 'eJzt0dEJACAIBcCVdP/lQirIAaqfO1B46IdgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/lqjO3WZl9x9ihb/NU1jN+H3HbAJ1aBe0=', id: 'https://api.vidchain.net/api/v1/revocation/status-list/213', type: 'RevocationList2021', }, }; const credential = { iat: 1701180111, iss: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', vc: { '@context': ['https://www.w3.org/2018/credentials/v1'], id: 'urn:uuid:token-status-expects-jwt', issuer: 'did:ethr:0x23362bCD60f74f0960E99e07561974C278Af7a22', type: ['VerifiableCredential'], credentialSubject: { id: 'did:key:test' }, credentialStatus: { id: 'https://example.com/status/credential/1', type: 'TokenStatusList', statusListCredential: 'https://example.com/status-list/1', statusListIndex: '0', }, }, }; statusListCredentialFetcher.getStatusListCredential.mockResolvedValue( statusListCredential as any, ); await expect( revocationValidator.validate(credential as any), ).rejects.toThrow('TokenStatusList requires a JWT string'); }); });