github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/kat/src/test/corda/assets/authored-private-structured.ts (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import { app, mockEventStreamWebSocket } from '../../common'; 16 import { v4 as uuidV4 } from 'uuid'; 17 import { testContent } from '../../samples'; 18 import nock from 'nock'; 19 import request from 'supertest'; 20 import assert from 'assert'; 21 import { IDBAssetDefinition, IDBAssetInstance} from '../../../lib/interfaces'; 22 import * as utils from '../../../lib/utils'; 23 24 export const testAssetsAuthoredPrivateStructured = () => { 25 26 describe('Assets: authored - structured', async () => { 27 28 let assetDefinitionID = uuidV4(); 29 const assetDefinitionName = 'authored - private - structured'; 30 const timestamp = new Date(); 31 32 describe('Create asset definition', () => { 33 34 it('Checks that the asset definition can be added', async () => { 35 36 nock('https://apigateway.kaleido.io') 37 .post('/createAssetDefinition') 38 .reply(200); 39 40 nock('https://ipfs.kaleido.io') 41 .post('/api/v0/add') 42 .reply(200, { Hash: 'Qmf71q7zspRmzvH6yVhkrpWCnK54rvxyj6XSTJ5tgBiZfV' }); 43 44 const result = await request(app) 45 .post('/api/v1/assets/definitions') 46 .send({ 47 name: assetDefinitionName, 48 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 49 assetDefinitionID, 50 isContentPrivate: true, 51 isContentUnique: true, 52 contentSchema: testContent.schema.object 53 }) 54 .expect(200); 55 assert.deepStrictEqual(result.body.status, 'submitted'); 56 57 const getAssetDefinitionsResponse = await request(app) 58 .get('/api/v1/assets/definitions') 59 .expect(200); 60 const assetDefinition = getAssetDefinitionsResponse.body.find((assetDefinition: IDBAssetDefinition) => assetDefinition.name === 'authored - private - structured'); 61 assert.strictEqual(assetDefinition.assetDefinitionID, assetDefinitionID); 62 assert.strictEqual(assetDefinition.author, 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US'); 63 assert.strictEqual(assetDefinition.isContentPrivate, true); 64 assert.strictEqual(assetDefinition.isContentUnique, true); 65 assert.deepStrictEqual(assetDefinition.contentSchema, testContent.schema.object); 66 assert.strictEqual(assetDefinition.name, 'authored - private - structured'); 67 assert.strictEqual(typeof assetDefinition.submitted, 'number'); 68 }); 69 70 }); 71 72 describe('Asset instances', async () => { 73 74 let assetInstanceID: string; 75 76 describe('Asset instances - argument validation', async () => { 77 it('Attempting to add an asset instance without specifying participants should raise an error', async () => { 78 const result = await request(app) 79 .post(`/api/v1/assets/${assetDefinitionID}`) 80 .send({ 81 content: { 82 my_content_string: 'test sample content string', 83 my_content_number: 124, 84 my_content_boolean: false 85 }, 86 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US' 87 }) 88 .expect(400); 89 assert.deepStrictEqual(result.body, { error: 'Missing asset participants' }); 90 }); 91 92 it('Attempting to add an asset instance without specifying participants should raise an error', async () => { 93 const result = await request(app) 94 .post(`/api/v1/assets/${assetDefinitionID}`) 95 .send({ 96 content: { 97 my_content_string: 'test sample content string', 98 my_content_number: 124, 99 my_content_boolean: false 100 }, 101 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 102 participants: ['CN=Node of node3 for env1, O=Kaleido, L=Raleigh, C=US'] 103 }) 104 .expect(400); 105 assert.deepStrictEqual(result.body, { error: `One or more participants are not registered` }); 106 }); 107 108 it('Attempting to set an asset instance property without specifying key should raise an error', async () => { 109 const result = await request(app) 110 .put(`/api/v1/assets/some-asset-def-id/some-asset-id`) 111 .send({ 112 action: 'set-property', 113 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 114 }) 115 .expect(400); 116 assert.deepStrictEqual(result.body, { error: `Missing asset property key` }); 117 }); 118 119 it('Attempting to set an asset instance property without specifying value should raise an error', async () => { 120 const result = await request(app) 121 .put(`/api/v1/assets/some-asset-def-id/some-asset-id`) 122 .send({ 123 action: 'set-property', 124 key: 'key', 125 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 126 }) 127 .expect(400); 128 assert.deepStrictEqual(result.body, { error: `Missing asset property value` }); 129 }); 130 }); 131 132 it('Checks that an asset instance can be created', async () => { 133 134 nock('https://apigateway.kaleido.io') 135 .post('/createAssetInstance') 136 .reply(200); 137 138 const result = await request(app) 139 .post(`/api/v1/assets/${assetDefinitionID}`) 140 .send({ 141 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 142 content: testContent.sample.object, 143 participants: ['CN=Node of node2 for env1, O=Kaleido, L=Raleigh, C=US'] 144 }) 145 .expect(200); 146 assert.deepStrictEqual(result.body.status, 'submitted'); 147 assetInstanceID = result.body.assetInstanceID; 148 149 const getAssetInstancesResponse = await request(app) 150 .get(`/api/v1/assets/${assetDefinitionID}`) 151 .expect(200); 152 const assetInstance = getAssetInstancesResponse.body.find((assetInstance: IDBAssetInstance) => assetInstance.assetInstanceID === assetInstanceID); 153 assert.strictEqual(assetInstance.author, 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US'); 154 assert.strictEqual(assetInstance.assetDefinitionID, assetDefinitionID); 155 assert.strictEqual(assetInstance.contentHash, testContent.sample.docExchangeSha256); 156 assert.deepStrictEqual(assetInstance.content, testContent.sample.object); 157 assert.strictEqual(typeof assetInstance.submitted, 'number'); 158 159 const getAssetInstanceResponse = await request(app) 160 .get(`/api/v1/assets/${assetDefinitionID}/${assetInstanceID}`) 161 .expect(200); 162 assert.deepStrictEqual(assetInstance, getAssetInstanceResponse.body); 163 164 }); 165 166 it('Checks that the event stream notification for confirming the asset instance creation is handled', async () => { 167 const eventPromise = new Promise<void>((resolve) => { 168 mockEventStreamWebSocket.once('send', message => { 169 assert.strictEqual(message, '{"type":"ack","topic":"dev"}'); 170 resolve(); 171 }) 172 }); 173 const assetData: any = { 174 assetDefinitionID: assetDefinitionID, 175 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 176 assetInstanceID: assetInstanceID, 177 contentHash: testContent.sample.docExchangeSha256, 178 participants: ['CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 'CN=Node of node2 for env1, O=Kaleido, L=Raleigh, C=US'] 179 }; 180 mockEventStreamWebSocket.emit('message', JSON.stringify([{ 181 signature: utils.contractEventSignaturesCorda.ASSET_INSTANCE_CREATED, 182 data: {data: assetData}, 183 stateRef: { 184 txhash: "25D867CC5D19AB40AE46E6262F3C274A6B772D68A0AA522F4C5A96196EAF5FCE", 185 index: 0 186 }, 187 subId: "sb-f5abe54b-53fb-4f63-8236-f3a8a6bc1c60", 188 recordedTime: timestamp.toISOString(), 189 consumedTime: null 190 }])); 191 await eventPromise; 192 }); 193 194 it('Checks that the asset instance is confirmed', async () => { 195 const getAssetInstancesResponse = await request(app) 196 .get(`/api/v1/assets/${assetDefinitionID}`) 197 .expect(200); 198 const assetInstance = getAssetInstancesResponse.body.find((assetInstance: IDBAssetInstance) => assetInstance.assetInstanceID === assetInstanceID); 199 assert.strictEqual(assetInstance.author, 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US'); 200 assert.strictEqual(assetInstance.assetDefinitionID, assetDefinitionID); 201 assert.strictEqual(assetInstance.contentHash, testContent.sample.docExchangeSha256); 202 assert.deepStrictEqual(assetInstance.content, testContent.sample.object); 203 assert.strictEqual(assetInstance.timestamp, timestamp.getTime()); 204 assert.strictEqual(typeof assetInstance.submitted, 'number'); 205 assert.strictEqual(assetInstance.transactionHash, '25D867CC5D19AB40AE46E6262F3C274A6B772D68A0AA522F4C5A96196EAF5FCE'); 206 assert.deepStrictEqual(assetInstance.participants, ['CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 'CN=Node of node2 for env1, O=Kaleido, L=Raleigh, C=US']) 207 const getAssetInstanceResponse = await request(app) 208 .get(`/api/v1/assets/${assetDefinitionID}/${assetInstanceID}`) 209 .expect(200); 210 assert.deepStrictEqual(assetInstance, getAssetInstanceResponse.body); 211 }); 212 213 it('Checks that the asset instance property can be set', async () => { 214 nock('https://apigateway.kaleido.io') 215 .post('/setAssetInstanceProperty') 216 .reply(200); 217 218 const result = await request(app) 219 .put(`/api/v1/assets/${assetDefinitionID}/${assetInstanceID}`) 220 .send({ 221 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 222 action: 'set-property', 223 key: 'key1', 224 value: 'value1' 225 }) 226 .expect(200); 227 assert.deepStrictEqual(result.body.status, 'submitted'); 228 229 const getAssetInstancesResponse = await request(app) 230 .get(`/api/v1/assets/${assetDefinitionID}`) 231 .expect(200); 232 const assetInstance = getAssetInstancesResponse.body.find((assetInstance: IDBAssetInstance) => assetInstance.assetInstanceID === assetInstanceID); 233 assert.strictEqual(assetInstance.author, 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US'); 234 assert.strictEqual(assetInstance.properties[assetInstance.author]['key1'].value, 'value1'); 235 assert.strictEqual(typeof assetInstance.properties[assetInstance.author]['key1'].submitted, 'number'); 236 const getAssetInstanceResponse = await request(app) 237 .get(`/api/v1/assets/${assetDefinitionID}/${assetInstanceID}`) 238 .expect(200); 239 assert.deepStrictEqual(assetInstance, getAssetInstanceResponse.body); 240 241 }); 242 243 it('Checks that the event stream notification for confirming the asset instance set property is handled', async () => { 244 const eventPromise = new Promise<void>((resolve) => { 245 mockEventStreamWebSocket.once('send', message => { 246 assert.strictEqual(message, '{"type":"ack","topic":"dev"}'); 247 resolve(); 248 }) 249 }); 250 const assetData: any = { 251 assetDefinitionID: assetDefinitionID, 252 author: 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 253 assetInstanceID: assetInstanceID, 254 key: 'key1', 255 value: 'value1', 256 participants: ['CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 'CN=Node of node2 for env1, O=Kaleido, L=Raleigh, C=US'] 257 }; 258 mockEventStreamWebSocket.emit('message', JSON.stringify([{ 259 signature: utils.contractEventSignaturesCorda.ASSET_PROPERTY_SET, 260 data: {data: assetData}, 261 stateRef: { 262 txhash: "35D867CC5D19AB40AE46E6262F3C274A6B772D68A0AA522F4C5A96196EAF5FCE", 263 index: 0 264 }, 265 subId: "sb-f5abe54b-53fb-4f63-8236-f3a8a6bc1c60", 266 recordedTime: timestamp.toISOString(), 267 consumedTime: null 268 }])); 269 await eventPromise; 270 }); 271 272 it('Checks that the asset instance property set is confirmed', async () => { 273 const getAssetInstancesResponse = await request(app) 274 .get(`/api/v1/assets/${assetDefinitionID}`) 275 .expect(200); 276 const assetInstance = getAssetInstancesResponse.body.find((assetInstance: IDBAssetInstance) => assetInstance.assetInstanceID === assetInstanceID); 277 assert.strictEqual(assetInstance.author, 'CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US'); 278 assert.strictEqual(assetInstance.assetDefinitionID, assetDefinitionID); 279 assert.strictEqual(assetInstance.contentHash, testContent.sample.docExchangeSha256); 280 assert.deepStrictEqual(assetInstance.content, testContent.sample.object); 281 assert.strictEqual(assetInstance.timestamp, timestamp.getTime()); 282 assert.strictEqual(typeof assetInstance.submitted, 'number'); 283 assert.strictEqual(assetInstance.transactionHash, '25D867CC5D19AB40AE46E6262F3C274A6B772D68A0AA522F4C5A96196EAF5FCE'); 284 assert.deepStrictEqual(assetInstance.participants, ['CN=Node of node1 for env1, O=Kaleido, L=Raleigh, C=US', 'CN=Node of node2 for env1, O=Kaleido, L=Raleigh, C=US']) 285 assert.strictEqual(assetInstance.properties[assetInstance.author]['key1'].value, 'value1'); 286 assert.strictEqual(typeof assetInstance.properties[assetInstance.author]['key1'].submitted, 'number'); 287 assert.strictEqual(assetInstance.properties[assetInstance.author]['key1'].history[assetInstance.timestamp].transactionHash, '35D867CC5D19AB40AE46E6262F3C274A6B772D68A0AA522F4C5A96196EAF5FCE'); 288 289 const getAssetInstanceResponse = await request(app) 290 .get(`/api/v1/assets/${assetDefinitionID}/${assetInstanceID}`) 291 .expect(200); 292 assert.deepStrictEqual(assetInstance, getAssetInstanceResponse.body); 293 }); 294 295 }); 296 297 }); 298 };