git.delta.rocks / unique-network / refs/commits / 63d47c8ea132

difftreelog

Add properties negative tests

Max Andreev2022-12-12parent: #ff6d017.patch.diff
in: master

1 file changed

modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {IKeyringPair} from '@polkadot/types/types';
18import {Contract} from 'web3-eth-contract';
17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';19import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';
18import {IKeyringPair} from '@polkadot/types/types';
19import {ITokenPropertyPermission, TCollectionMode} from '../util/playgrounds/types';20import {ITokenPropertyPermission, TCollectionMode} from '../util/playgrounds/types';
20import {Pallets} from '../util';21import {Pallets} from '../util';
21import {UniqueNFTCollection, UniqueRFTCollection} from '../util/playgrounds/unique';22import {UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection} from '../util/playgrounds/unique';
2223
23describe('EVM token properties', () => {24describe('EVM token properties', () => {
24 let donor: IKeyringPair;25 let donor: IKeyringPair;
88 expect(properties).to.deep.equal(testCase.expectedProps);89 expect(properties).to.deep.equal(testCase.expectedProps);
89 }));90 }));
90 91
91 async function checkProps(helper: EthUniqueHelper, mode: TCollectionMode) {92 [
93 {mode: 'nft' as const, requiredPallets: [Pallets.ReFungible]},
94 {mode: 'rft' as const, requiredPallets: []},
95 ].map(testCase =>
96 itEth.ifWithPallets(`Can be multiple set/read for ${testCase.mode}`, testCase.requiredPallets, async({helper}) => {
92 const caller = await helper.eth.createAccountWithBalance(donor);97 const caller = await helper.eth.createAccountWithBalance(donor);
93 98
94 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });99 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });
95 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,100 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,
96 collectionAdmin: true,101 collectionAdmin: true,
97 mutable: true}}; });102 mutable: true}}; });
98 103
99 const collection = await helper[mode].mintCollection(alice, {104 const collection = await helper[testCase.mode].mintCollection(alice, {
100 tokenPrefix: 'ethp',105 tokenPrefix: 'ethp',
101 tokenPropertyPermissions: permissions,106 tokenPropertyPermissions: permissions,
102 }) as UniqueNFTCollection | UniqueRFTCollection;107 }) as UniqueNFTCollection | UniqueRFTCollection;
103 108
104 const token = await collection.mintToken(alice);109 const token = await collection.mintToken(alice);
105 110
106 const valuesBefore = await token.getProperties(properties.map(p => p.key));111 const valuesBefore = await token.getProperties(properties.map(p => p.key));
107 expect(valuesBefore).to.be.deep.equal([]);112 expect(valuesBefore).to.be.deep.equal([]);
108 113
109 114
110 await collection.addAdmin(alice, {Ethereum: caller});115 await collection.addAdmin(alice, {Ethereum: caller});
111 116
112 const address = helper.ethAddress.fromCollectionId(collection.collectionId);117 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
113 const contract = helper.ethNativeContract.collection(address, mode, caller);118 const contract = helper.ethNativeContract.collection(address, testCase.mode, caller);
114 119
115 expect(await contract.methods.properties(token.tokenId, []).call()).to.be.deep.equal([]);
116
117 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});120 expect(await contract.methods.properties(token.tokenId, []).call()).to.be.deep.equal([]);
118
119 const values = await token.getProperties(properties.map(p => p.key));
120 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));
121
122 expect(await contract.methods.properties(token.tokenId, []).call()).to.be.like(properties
123 .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); }));
124
125 expect(await contract.methods.properties(token.tokenId, [properties[0].key]).call())
126 .to.be.like([helper.ethProperty.property(properties[0].key, properties[0].value.toString())]);
127 }
128 121
129 itEth('Can be multiple set/read for NFT ', async({helper}) => {122 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});
130 await checkProps(helper, 'nft');
131 });
132 123
133 itEth.ifWithPallets('Can be multiple set/read for RFT ', [Pallets.ReFungible], async({helper}) => {124 const values = await token.getProperties(properties.map(p => p.key));
125 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));
126
127 expect(await contract.methods.properties(token.tokenId, []).call()).to.be.like(properties
128 .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); }));
134 await checkProps(helper, 'rft');129
130 expect(await contract.methods.properties(token.tokenId, [properties[0].key]).call())
131 .to.be.like([helper.ethProperty.property(properties[0].key, properties[0].value.toString())]);
135 });132 }));
136 133
137 itEth('Can be deleted', async({helper}) => {134 [
135 {mode: 'nft' as const, requiredPallets: [Pallets.ReFungible]},
136 {mode: 'rft' as const, requiredPallets: []},
137 ].map(testCase =>
138 itEth.ifWithPallets(`Can be deleted fro ${testCase.mode}`, testCase.requiredPallets, async({helper}) => {
138 const caller = await helper.eth.createAccountWithBalance(donor);139 const caller = await helper.eth.createAccountWithBalance(donor);
139 const collection = await helper.nft.mintCollection(alice, {140 const collection = await helper[testCase.mode].mintCollection(alice, {
140 tokenPropertyPermissions: [{141 tokenPropertyPermissions: [{
141 key: 'testKey',142 key: 'testKey',
142 permission: {143 permission: {
143 mutable: true,144 mutable: true,
144 collectionAdmin: true,145 collectionAdmin: true,
146 },
145 },147 },
146 },148 {
147 {149 key: 'testKey_1',
148 key: 'testKey_1',
149 permission: {150 permission: {
150 mutable: true,151 mutable: true,
151 collectionAdmin: true,152 collectionAdmin: true,
152 },153 },
153 }],154 }],
154 });155 });
155 156
156 const token = await collection.mintToken(alice);157 const token = await collection.mintToken(alice);
157 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}, {key: 'testKey_1', value: 'testValue_1'}]);158 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}, {key: 'testKey_1', value: 'testValue_1'}]);
159 expect(await token.getProperties()).to.has.length(2);
158160
159 await collection.addAdmin(alice, {Ethereum: caller});161 await collection.addAdmin(alice, {Ethereum: caller});
160162
161 const address = helper.ethAddress.fromCollectionId(collection.collectionId);163 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
162 const contract = helper.ethNativeContract.collection(address, 'nft', caller);164 const contract = helper.ethNativeContract.collection(address, testCase.mode, caller);
163165
164 await contract.methods.deleteProperties(token.tokenId, ['testKey', 'testKey_1']).send({from: caller});166 await contract.methods.deleteProperties(token.tokenId, ['testKey', 'testKey_1']).send({from: caller});
165167
166 const result = await token.getProperties(['testKey']);168 const result = await token.getProperties(['testKey', 'testKey_1']);
167 expect(result.length).to.equal(0);169 expect(result.length).to.equal(0);
168 });170 }));
169171
170 itEth('Can be read', async({helper}) => {172 itEth('Can be read', async({helper}) => {
171 const caller = helper.eth.createAccount();173 const caller = helper.eth.createAccount();
186188
187 const value = await contract.methods.property(token.tokenId, 'testKey').call();189 const value = await contract.methods.property(token.tokenId, 'testKey').call();
188 expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));190 expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));
191 });
192});
193
194describe('EVM token properties negative', () => {
195 let donor: IKeyringPair;
196 let alice: IKeyringPair;
197 let caller: string;
198 let aliceCollection: UniqueNFTCollection;
199 let token: UniqueNFToken;
200 const tokenProps = [{key: 'testKey_1', value: 'testValue_1'}, {key: 'testKey_2', value: 'testValue_2'}];
201 let collectionEvm: Contract;
202
203 before(async function() {
204 await usingEthPlaygrounds(async (helper, privateKey) => {
205 donor = await privateKey({filename: __filename});
206 [alice] = await helper.arrange.createAccounts([100n], donor);
207 });
208 });
209
210 beforeEach(async () => {
211 // 1. create collection with props: testKey_1, testKey_2
212 // 2. create token and set props testKey_1, testKey_2
213 await usingEthPlaygrounds(async (helper) => {
214 aliceCollection = await helper.nft.mintCollection(alice, {
215 tokenPropertyPermissions: [{
216 key: 'testKey_1',
217 permission: {
218 mutable: true,
219 collectionAdmin: true,
220 },
221 },
222 {
223 key: 'testKey_2',
224 permission: {
225 mutable: true,
226 collectionAdmin: true,
227 },
228 }],
229 });
230 token = await aliceCollection.mintToken(alice);
231 await token.setProperties(alice, tokenProps);
232 collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true);
233 });
234 });
235
236 [
237 {method: 'setProperty', methodParams: [tokenProps[1].key, Buffer.from('newValue')]},
238 {method: 'setProperties', methodParams: [[{key: tokenProps[1].key, value: Buffer.from('newValue')}]]},
239 ].map(testCase =>
240 itEth(`[${testCase.method}] Cannot set properties of non-owned collection`, async ({helper}) => {
241 caller = await helper.eth.createAccountWithBalance(donor);
242 collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true);
243 // Caller an owner and not an admin, so he cannot set properties:
244 // FIXME: Can setProperties as non owner and non admin
245 await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission');
246 await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).send({from: caller})).to.be.rejected;
247
248 // Props have not changed:
249 const expectedProps = tokenProps.map(p => helper.ethProperty.property(p.key, p.value.toString()));
250 const actualProps = await collectionEvm.methods.properties(token.tokenId, []).call();
251 expect(actualProps).to.deep.eq(expectedProps);
252 }));
253
254 [
255 {method: 'setProperty', methodParams: ['testKey_3', Buffer.from('testValue3')]},
256 {method: 'setProperties', methodParams: [[{key: 'testKey_3', value: Buffer.from('testValue3')}]]},
257 ].map(testCase =>
258 itEth(`[${testCase.method}] Cannot set non-existing properties`, async ({helper}) => {
259 caller = await helper.eth.createAccountWithBalance(donor);
260 collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true);
261 await helper.collection.addAdmin(alice, aliceCollection.collectionId, {Ethereum: caller});
262
263 await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission');
264 await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).send({from: caller})).to.be.rejected;
265
266 // Props have not changed:
267 const actualProps = await collectionEvm.methods.properties(token.tokenId, ['testKey2']).call();
268 expect(actualProps).to.deep.eq(tokenProps
269 .map(p => { return helper.ethProperty.property(p.key, p.value.toString());
270 }));
271 }));
272
273 itEth('Cannot delete properties of non-owned collection', async () => {
274
275 });
276
277 itEth('Cannot delete non-existing properties', async () => {
278
189 });279 });
190});280});