--- a/tests/package.json +++ b/tests/package.json @@ -28,7 +28,8 @@ "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts", "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts", "testToggleContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/toggleContractWhiteList.test.ts", - "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts" + "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts", + "testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts" }, "author": "", "license": "Apache 2.0", --- a/tests/src/substrate/get-balance.ts +++ b/tests/src/substrate/get-balance.ts @@ -3,12 +3,12 @@ // file 'LICENSE', which is part of this source code package. // -import { ApiPromise } from "@polkadot/api"; -import promisifySubstrate from "./promisify-substrate"; -import {AccountInfo} from "@polkadot/types/interfaces/system"; +import { ApiPromise } from '@polkadot/api'; +import {AccountInfo} from '@polkadot/types/interfaces/system'; +import promisifySubstrate from './promisify-substrate'; -export default async function getBalance(api: ApiPromise, accounts: string[]): Promise { - const balance = promisifySubstrate(api, (accounts: string[]) => api.query.system.account.multi(accounts)); +export default async function getBalance(api: ApiPromise, accounts: string[]): Promise> { + const balance = promisifySubstrate(api, (acc: string[]) => api.query.system.account.multi(acc)); const responce = await balance(accounts) as unknown as AccountInfo[]; - return responce.map(r => r.data.free.toBigInt().valueOf()); + return responce.map((r) => r.data.free.toBigInt().valueOf()); } --- a/tests/src/substrate/substrate-api.ts +++ b/tests/src/substrate/substrate-api.ts @@ -58,21 +58,22 @@ return TransactionStatus.Fail; } -export function submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic): Promise { - return new Promise(async function(resolve, reject) { +export function +submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic): Promise { + return new Promise(async (resolve, reject) => { try { await transaction.signAndSend(sender, ({ events = [], status }) => { const transactionStatus = getTransactionStatus(events, status); - if (transactionStatus == TransactionStatus.Success) { + if (transactionStatus === TransactionStatus.Success) { resolve(events); - } else if (transactionStatus == TransactionStatus.Fail) { + } else if (transactionStatus === TransactionStatus.Fail) { console.log(`Something went wrong with transaction. Status: ${status}`); reject(events); } }); } catch (e) { - console.log("Error: ", e); + console.log('Error: ', e); reject(e); } }); --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -3,49 +3,99 @@ // file 'LICENSE', which is part of this source code package. // -import { expect, assert } from "chai"; -import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api"; -import { alicesPublicKey, bobsPublicKey, ferdiesPublicKey } from "./accounts"; -import privateKey from "./substrate/privateKey"; -import getBalance from "./substrate/get-balance"; -import { BigNumber } from 'bignumber.js'; -import { findUnusedAddress } from './util/helpers' +import { ApiPromise } from '@polkadot/api'; +import { expect } from 'chai'; +import { alicesPublicKey, bobsPublicKey } from './accounts'; +import getBalance from './substrate/get-balance'; +import privateKey from './substrate/privateKey'; +import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api'; +import { + approveExpectSuccess, + createCollectionExpectSuccess, createItemExpectSuccess, + findUnusedAddress, + getCreateCollectionResult, + getCreateItemResult, + transferExpectSuccess, +} from './util/helpers'; -describe('Transfer', () => { - it('Balance transfers', async () => { - await usingApi(async api => { +describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => { + it('Balance transfers and check balance', async () => { + await usingApi(async (api: ApiPromise) => { const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); const alicePrivateKey = privateKey('//Alice'); - + const transfer = api.tx.balances.transfer(bobsPublicKey, 1n); - const result = await submitTransactionAsync(alicePrivateKey, transfer); + const events = await submitTransactionAsync(alicePrivateKey, transfer); + const result = getCreateItemResult(events); + // tslint:disable-next-line:no-unused-expression + expect(result.success).to.be.true; const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); + // tslint:disable-next-line:no-unused-expression expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true; + // tslint:disable-next-line:no-unused-expression expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true; }); }); it('Inability to pay fees error message is correct', async () => { - await usingApi(async api => { + await usingApi(async (api) => { // Find unused address const pk = await findUnusedAddress(api); - const error = console.error; - const log = console.log; - console.log = function () {}; - console.error = function () {}; - const badTransfer = api.tx.balances.transfer(bobsPublicKey, 1n); - const badTransaction = async function () { - const result = await submitTransactionAsync(pk, badTransfer); + // const events = await submitTransactionAsync(pk, badTransfer); + const badTransaction = async () => { + const events = await submitTransactionAsync(pk, badTransfer); + const result = getCreateCollectionResult(events); + // tslint:disable-next-line:no-unused-expression + expect(result.success).to.be.false; }; - await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees"); - - console.log = log; - console.error = error; + expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low'); }); }); + + it('Create collection, balance transfers and check balance', async () => { + const Alice = privateKey('//Alice'); + const Bob = privateKey('//Bob'); + const Charlie = privateKey('//CHARLIE'); + // nft + const nftCollectionId = await createCollectionExpectSuccess(); + const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); + + await transferExpectSuccess(nftCollectionId, newNftTokenId, Alice, Bob, 1, 'NFT'); + + // fungible + const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); + const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible'); + await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob); + await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible'); + // reFungible + const reFungibleCollectionId = await + createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); + await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); + await transferExpectSuccess(reFungibleCollectionId, + newReFungibleTokenId, Alice, Bob, 1, 'ReFungible'); + }); +}); + +describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => { + it('Transfer with not existed collection_id', async () => { + + }); + it('Transfer with deleted collection_id', async () => { + + }); + it('Transfer with not existed item_id', async () => { + + }); + it('Transfer with deleted item_id', async () => { + + }); + it('Transfer with recipient that is not owner', async () => { + + }); }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -462,6 +462,40 @@ } export async function +transferExpectSuccess(collectionId: number, + tokenId: number, + sender: IKeyringPair, + recipient: IKeyringPair, + value: number = 1, + type: string = 'NFT') { + await usingApi(async (api: ApiPromise) => { + let balanceBefore = new BN(0); + if (type === 'Fungible') { + balanceBefore = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN; + } + const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value); + const events = await submitTransactionAsync(sender, transferTx); + const result = getCreateItemResult(events); + // tslint:disable-next-line:no-unused-expression + expect(result.success).to.be.true; + if (type === 'NFT') { + const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType; + expect(nftItemData.Owner.toString()).to.be.equal(recipient.address); + } + if (type === 'Fungible') { + const balanceAfter = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN; + expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value); + } + if (type === 'ReFungible') { + const nftItemData = + await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType; + expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(recipient.address); + expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value); + } + }); +} + +export async function approveExpectFail(collectionId: number, tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) { await usingApi(async (api: ApiPromise) => {