Skip to content

Commit

Permalink
Add createRequestBody helper function.
Browse files Browse the repository at this point in the history
  • Loading branch information
JSAssassin committed May 13, 2022
1 parent ee262df commit ad5c9bc
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 89 deletions.
23 changes: 12 additions & 11 deletions tests/10-issue.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,18 @@ describe('StatusList2021 Credentials (Issue)', function() {
const {slc} = await getSlc({issuedVc});
testSlCredential({slCredential: slc});
});
it('Size of decoded "encodedList" MUST be 16kb', async function() {
this.test.cell = {columnId: issuerName, rowId: this.test.title};
const {slc: {credentialSubject}} = await getSlc({issuedVc});
const {encodedList} = credentialSubject;
// Uncompress encodedList
const decoded = await sl.decodeList({encodedList});
should.exist(decoded);
// decoded size should be 16kb
const decodedSize = (decoded.length / 8) / 1024;
decodedSize.should.equal(16);
});
it('MUST be 16kb in size when "encodedList" is decoded',
async function() {
this.test.cell = {columnId: issuerName, rowId: this.test.title};
const {slc: {credentialSubject}} = await getSlc({issuedVc});
const {encodedList} = credentialSubject;
// Uncompress encodedList
const decoded = await sl.decodeList({encodedList});
should.exist(decoded);
// decoded size should be 16kb
const decodedSize = (decoded.length / 8) / 1024;
decodedSize.should.equal(16);
});
});
}
});
95 changes: 26 additions & 69 deletions tests/30-interop.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,66 +5,39 @@

const chai = require('chai');
const {filterByTag} = require('vc-api-test-suite-implementations');
const {ISOTimeStamp, getCredentialStatus} = require('./helpers.js');
const {createValidVc, createRequestBody, getCredentialStatus} =
require('./helpers.js');
const {klona} = require('klona');
const {v4: uuidv4} = require('uuid');
const {validVc} = require('../credentials');

const should = chai.should();

// only use implementations with `StatusList2021` tags.
const {match, nonMatch} = filterByTag({issuerTags: ['StatusList2021']});

describe('StatusList2021 Credentials (Interop)', function() {
// this will tell the report
// to make an interop matrix with this suite
this.matrix = true;
this.report = true;
this.implemented = [...match.keys()];
this.rowLabel = 'Test Name';
this.columnLabel = 'Implementation';
this.notImplemented = [...nonMatch.keys()];
// the reportData will be displayed under the test title
for(const [issuerName, {issuers}] of match) {
let issuedVc;
before(async function() {
const issuer = issuers.find(issuer => issuer.tags.has('StatusList2021'));
const expires = () => {
const date = new Date();
date.setMonth(date.getMonth() + 2);
return ISOTimeStamp({date});
};
const {issuer: {id: issuerId}} = issuer;
const body = {
credential: {
...validVc,
id: `urn:uuid:${uuidv4()}`,
issuanceDate: ISOTimeStamp(),
expirationDate: expires(),
issuer: issuerId
}
};
const {result} = await issuer.issue({body});
if(result) {
issuedVc = result.data.verifiableCredential;
}
const credential = createValidVc({issuerId});
const body = {credential};
const {data} = await issuer.issue({body});
issuedVc = data;
});
// this sends a credential issued by the implementation
// to each verifier
for(const [verifierName, {verifiers}] of match) {
const verifier = verifiers.find(verifier =>
verifier.tags.has('StatusList2021'));
it(`MUST successfully verify VC issued by ${issuerName}`,
async function() {
// this tells the test report which cell in the interop matrix
// the result goes in
this.test.cell = {columnId: verifierName, rowId: this.test.title};
const body = {
verifiableCredential: issuedVc,
options: {
checks: ['proof', 'credentialStatus']
}
};
const body = createRequestBody({vc: issuedVc});
const {result, error} = await verifier.verify({body});
should.exist(result);
should.not.exist(error);
Expand All @@ -79,11 +52,6 @@ describe('StatusList2021 Credentials (Interop)', function() {
});
it(`MUST revoke a credential and fail to verify revoked credential`,
async function() {
// FIXME: Currently this test uses credential with 2020 status
// type.

// this tells the test report which cell in the interop matrix
// the result goes in
this.test.cell = {columnId: verifierName, rowId: this.test.title};
// copy vc issued
const vc = klona(issuedVc);
Expand All @@ -93,42 +61,35 @@ describe('StatusList2021 Credentials (Interop)', function() {
statusInfo.status.should.equal(false);

// verification of the credential should pass
const body = {
verifiableCredential: vc,
options: {
checks: ['proof', 'credentialStatus']
}
};
const {result: result1, error: err1} = await verifier.verify(
{body});
{body: createRequestBody({vc})});
should.exist(result1);
should.not.exist(err1);
result1.status.should.equal(200);
should.exist(result1.data);
// verifier responses vary but are all objects
result1.data.should.be.an('object');
result1.data.verified.should.equal(true);
result1.data.statusResult.verified.should.equal(true);

const issuer = issuers.find(issuer =>
issuer.tags.has('StatusList2021'));
const body2 = {
credentialId: vc.id,
credentialStatus: {
type: 'RevocationList2020Status'
}
};
// Then revoke the VC
const {result: result2, error: err2} = await issuer.setStatus(
{body: body2});
// Then revoke the VC
const body = createRequestBody({
vc, setStatus: true, statusPurpose: 'revocation'});
const {
result: result2,
error: err2
} = await issuer.setStatus({body});
should.not.exist(err2);
should.exist(result2);
result2.status.should.equal(200);
const publishSlcEndpoint =
`${statusInfo.statusListCredential}/publish`;
// force publication of new SLC
const {result: result3, error: err3} = await issuer.publishSlc(
{endpoint: publishSlcEndpoint, body: {}});
`${statusInfo.statusListCredential}/publish`;
// force publication of new SLC
const {
result: result3,
error: err3
} = await issuer.publishSlc({endpoint: publishSlcEndpoint, body: {}});
should.not.exist(err3);
should.exist(result3);
result3.status.should.equal(204);
Expand All @@ -139,15 +100,11 @@ describe('StatusList2021 Credentials (Interop)', function() {
status.should.equal(true);

// try to verify the credential again, should fail since it
// has been revoked
const body3 = {
verifiableCredential: vc,
options: {
checks: ['proof', 'credentialStatus']
}
};
const {result: result4, error: err4} = await verifier.verify(
{body: body3});
// has now been revoked
const {
result: result4,
error: err4
} = await verifier.verify({body: createRequestBody({vc})});
should.not.exist(result4);
should.exist(err4);
should.exist(err4.data);
Expand Down
48 changes: 39 additions & 9 deletions tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,17 @@ const ISOTimeStamp = ({date = new Date()} = {}) => {
};

const getCredentialStatus = async ({verifiableCredential}) => {
// get SLC for the VC
const {credentialStatus} = verifiableCredential;
// FIXME: support `statusListCredential` as well
const {revocationListCredential} = credentialStatus;
const {statusListCredential} = credentialStatus;
// get StatusList Credential for the VC
const {data: slc} = await httpClient.get(
revocationListCredential, {agent});

const {encodedList} = slc.credentialSubject;
statusListCredential, {agent});
const {credentialSubject: {encodedList}} = slc;
const list = await decodeList({encodedList});
// FIXME: support `statusListIndex` as well
const statusListIndex = parseInt(
credentialStatus.revocationListIndex, 10);
credentialStatus.statusListIndex, 10);
const status = list.getStatus(statusListIndex);
return {status, statusListCredential: revocationListCredential};
return {status, statusListCredential};
};

const expires = () => {
Expand All @@ -57,7 +54,40 @@ const getSlc = async ({issuedVc}) => {
return {slc: document};
};

/**
* Creates a request body.
*
* @param {object} options - The options to use.
* @param {object} options.vc - The verifiable credential to send in request.
* @param {boolean} options.setStatus - The verifiable credential to send in
* request.
* @param {string} [options.statusPurpose] - The purpose of the status entry.
* "statusPurpose" must be set if "setStatus" is set to true. The values
* "revocation" or "suspension" must be used.
*
* @returns {object} - A request body.
*/
const createRequestBody = ({vc, setStatus = false, statusPurpose}) => {
let body = {
verifiableCredential: vc,
options: {
checks: ['proof', 'credentialStatus'],
}
};
if(setStatus) {
body = {
credentialId: vc.id,
credentialStatus: {
type: 'StatusList2021Entry',
statusPurpose
}
};
}
return body;
};

module.exports = {
createRequestBody,
createValidVc,
getCredentialStatus,
getSlc,
Expand Down

0 comments on commit ad5c9bc

Please sign in to comment.