From 3f53ccda4c2b72bf7ebb045d7dc5df0fd3003640 Mon Sep 17 00:00:00 2001 From: Dave Longley Date: Wed, 21 Feb 2024 23:18:09 -0500 Subject: [PATCH] Add more tests and assertions for status list creation. --- test/mocha/20-status.js | 164 +++++++++++++++++++++++++++++++++++++++- test/mocha/helpers.js | 5 ++ 2 files changed, 166 insertions(+), 3 deletions(-) diff --git a/test/mocha/20-status.js b/test/mocha/20-status.js index 8be2de9..8bc748c 100644 --- a/test/mocha/20-status.js +++ b/test/mocha/20-status.js @@ -51,10 +51,89 @@ describe('status APIs', () => { should.exist(result.id); result.id.should.equal(statusListId); - // FIXME: get status list and make assertions on it + // get status list and make assertions on it + const slc = await helpers.getStatusListCredential({statusListId}); + should.exist(slc); + slc.should.include.keys([ + 'id', 'credentialSubject', 'issuanceDate', 'expirationDate' + ]); + slc.id.should.equal(statusListOptions.credentialId); + slc.id.should.equal(statusListId); + slc.credentialSubject.should.include.keys([ + 'id', 'type', 'encodedList', 'statusPurpose' + ]); }); - // FIXME: add test with `credential ID` that doesn't match status instance + it('creates a status list with non-equal credential ID', async () => { + // suffix must match + const suffix = `/status-lists/${uuid()}`; + const statusListId = `${statusInstanceId}${suffix}`; + const statusListOptions = { + credentialId: `https://foo.example/anything/111${suffix}`, + type: 'StatusList2021', + indexAllocator: `urn:uuid:${uuid()}`, + length: 131072, + statusPurpose: 'revocation' + }; + let error; + let result; + try { + result = await helpers.createStatusList({ + url: statusListId, + capabilityAgent, + capability: statusInstanceRootZcap, + statusListOptions + }); + } catch(e) { + error = e; + } + assertNoError(error); + should.exist(result.id); + result.id.should.equal(statusListId); + + // get status list and make assertions on it + const slc = await helpers.getStatusListCredential({statusListId}); + should.exist(slc); + slc.should.include.keys([ + 'id', 'credentialSubject', 'issuanceDate', 'expirationDate' + ]); + slc.id.should.equal(statusListOptions.credentialId); + slc.id.should.not.equal(statusListId); + slc.credentialSubject.should.include.keys([ + 'id', 'type', 'encodedList', 'statusPurpose' + ]); + }); + + it('create fails w/ non-matching credential ID suffix', async () => { + // suffix must match + const localId = uuid(); + const suffix = `/status-lists/${localId}`; + const statusListId = `${statusInstanceId}${suffix}`; + const statusListOptions = { + credentialId: `https://foo.example/not-allowed/${localId}`, + type: 'StatusList2021', + indexAllocator: `urn:uuid:${uuid()}`, + length: 131072, + statusPurpose: 'revocation' + }; + let error; + let result; + try { + result = await helpers.createStatusList({ + url: statusListId, + capabilityAgent, + capability: statusInstanceRootZcap, + statusListOptions + }); + } catch(e) { + error = e; + } + should.not.exist(result); + should.exist(error); + error.data.message.should.equal( + 'Credential ID must end in status list suffix ' + + `("/status-lists/${localId}").`); + }); it('creates a terse "StatusList2021" status list', async () => { const statusListId = `${statusInstanceId}/status-lists/revocation/0`; @@ -81,7 +160,86 @@ describe('status APIs', () => { should.exist(result.id); result.id.should.equal(statusListId); - // FIXME: get status list and make assertions on it + // get status list and make assertions on it + const slc = await helpers.getStatusListCredential({statusListId}); + should.exist(slc); + slc.should.include.keys([ + 'id', 'credentialSubject', 'issuanceDate', 'expirationDate' + ]); + slc.id.should.equal(statusListId); + slc.credentialSubject.should.include.keys([ + 'id', 'type', 'encodedList', 'statusPurpose' + ]); + }); + + it('creates a terse status list with non-equal credential ID', async () => { + // suffix must match + const suffix = `/status-lists/revocation/0`; + const statusListId = `${statusInstanceId}${suffix}`; + const statusListOptions = { + credentialId: `https://foo.example/anything/111/${suffix}`, + type: 'StatusList2021', + indexAllocator: `urn:uuid:${uuid()}`, + length: 131072, + statusPurpose: 'revocation' + }; + let error; + let result; + try { + result = await helpers.createStatusList({ + url: statusListId, + capabilityAgent, + capability: statusInstanceRootZcap, + statusListOptions + }); + } catch(e) { + error = e; + } + assertNoError(error); + should.exist(result.id); + result.id.should.equal(statusListId); + + // get status list and make assertions on it + const slc = await helpers.getStatusListCredential({statusListId}); + should.exist(slc); + slc.should.include.keys([ + 'id', 'credentialSubject', 'issuanceDate', 'expirationDate' + ]); + slc.id.should.equal(statusListOptions.credentialId); + slc.id.should.not.equal(statusListId); + slc.credentialSubject.should.include.keys([ + 'id', 'type', 'encodedList', 'statusPurpose' + ]); + }); + + it('create terse fails w/ non-matching credential ID suffix', async () => { + // suffix must match + const suffix = `/status-lists/revocation/0`; + const statusListId = `${statusInstanceId}${suffix}`; + const statusListOptions = { + credentialId: `https://foo.example/not-allowed/revocation/0`, + type: 'StatusList2021', + indexAllocator: `urn:uuid:${uuid()}`, + length: 131072, + statusPurpose: 'revocation' + }; + let error; + let result; + try { + result = await helpers.createStatusList({ + url: statusListId, + capabilityAgent, + capability: statusInstanceRootZcap, + statusListOptions + }); + } catch(e) { + error = e; + } + should.not.exist(result); + should.exist(error); + error.data.message.should.equal( + 'Credential ID must end in status list suffix ' + + '("/status-lists/revocation/0").'); }); }); diff --git a/test/mocha/helpers.js b/test/mocha/helpers.js index fb2c577..91674bb 100644 --- a/test/mocha/helpers.js +++ b/test/mocha/helpers.js @@ -297,6 +297,11 @@ export async function getCredentialStatus({ return {status, statusListCredential, statusListIndex}; } +export async function getStatusListCredential({statusListId}) { + const {data: slc} = await httpClient.get(statusListId, {agent: httpsAgent}); + return slc; +} + export async function provisionDependencies() { const secret = '53ad64ce-8e1d-11ec-bb12-10bf48838a41'; const handle = 'test';