From 6b80f084f57049d065141d03c7e230beb4bc87ca Mon Sep 17 00:00:00 2001 From: Bartosz Solka Date: Thu, 8 Feb 2024 11:07:20 +0100 Subject: [PATCH] Added tests; minor refactoring Signed-off-by: Bartosz Solka --- src/HederaNFTSDK.ts | 4 +- src/functions/mintSharedMetadataFunction.ts | 8 +-- src/types/validateProps.ts | 2 +- src/utils/validateProps.ts | 14 ++-- test/unit/increaseNFTSupply.test.ts | 74 +++++++++++++++---- test/unit/validateProps.test.ts | 78 +++++++++++++++++---- 6 files changed, 139 insertions(+), 41 deletions(-) diff --git a/src/HederaNFTSDK.ts b/src/HederaNFTSDK.ts index 53e290a..6470137 100644 --- a/src/HederaNFTSDK.ts +++ b/src/HederaNFTSDK.ts @@ -121,7 +121,7 @@ export class HederaNFTSDK { nftId: NftId; amount: number; batchSize?: number; - supplyKey: PrivateKey; + supplyKey?: PrivateKey; mirrorNodeUrl?: string; }) { return increaseNFTSupply({ @@ -130,7 +130,7 @@ export class HederaNFTSDK { nftId: nftId, amount: amount, batchSize, - supplyKey, + supplyKey: supplyKey || PrivateKey.fromString(this.privateKey), mirrorNodeUrl, }); } diff --git a/src/functions/mintSharedMetadataFunction.ts b/src/functions/mintSharedMetadataFunction.ts index c7ae2b0..856299f 100644 --- a/src/functions/mintSharedMetadataFunction.ts +++ b/src/functions/mintSharedMetadataFunction.ts @@ -1,8 +1,8 @@ import { MintedNFTType, MintTokenType } from '../types/mintToken'; -import { mintToken } from './mintToken'; -import { validateProps } from '../utils/validateProps'; -import { MintingError } from '../utils/mintingError'; import { dictionary } from '../utils/constants/dictionary'; +import { MintingError } from '../utils/mintingError'; +import { validatePropsForSharedNFTMinting } from '../utils/validateProps'; +import { mintToken } from './mintToken'; export const mintSharedMetadataFunction = async ({ client, @@ -12,7 +12,7 @@ export const mintSharedMetadataFunction = async ({ metaData, supplyKey, }: MintTokenType) => { - validateProps({ tokenId, amount, metaData, supplyKey, batchSize }); + validatePropsForSharedNFTMinting({ tokenId, amount, metaData, supplyKey, batchSize }); const mintedNFTs: MintedNFTType[] = []; // Example if amount = 8 and batchSize = 5. NumberOfCalls should be 2. So 8/5 = 1.6. Math.ceil(1.6) = 2. Because Math.ceil rounds up to the next largest integer. diff --git a/src/types/validateProps.ts b/src/types/validateProps.ts index ce51974..590e5a0 100644 --- a/src/types/validateProps.ts +++ b/src/types/validateProps.ts @@ -1,6 +1,6 @@ import { Client, NftId, PrivateKey } from '@hashgraph/sdk'; -export type PropsType = { +export type sharedMintingValidationProps = { batchSize?: number; tokenId?: string; amount?: number; diff --git a/src/utils/validateProps.ts b/src/utils/validateProps.ts index 37a7ea5..c013dc6 100644 --- a/src/utils/validateProps.ts +++ b/src/utils/validateProps.ts @@ -1,12 +1,12 @@ import { - PropsType, + sharedMintingValidationProps, validateCreateCollectionProps, uniqueMintingValidationProps, increaseNFTSupplyValidationProps, } from '../types/validateProps'; import { dictionary } from './constants/dictionary'; -export const validateProps = (props: PropsType) => { +export const validatePropsForSharedNFTMinting = (props: sharedMintingValidationProps) => { validateSupplyKey(props); validateBatchSize(props); validateTokenId(props); @@ -68,13 +68,13 @@ const validateClient = (props: validateCreateCollectionProps) => { } }; -const validateSupplyKey = (props: PropsType) => { +const validateSupplyKey = (props: sharedMintingValidationProps) => { if (Object.prototype.hasOwnProperty.call(props, 'supplyKey')) { if (!props.supplyKey) throw new Error(dictionary.hederaActions.supplyKeyRequired); } }; -const validateBatchSize = (props: PropsType) => { +const validateBatchSize = (props: sharedMintingValidationProps) => { if (Object.prototype.hasOwnProperty.call(props, 'batchSize')) { if (!props.batchSize) throw new Error(dictionary.mintToken.batchSizeUndefined); if (props.batchSize > 10) throw new Error(dictionary.hederaActions.maxBatchSize); @@ -82,7 +82,7 @@ const validateBatchSize = (props: PropsType) => { } }; -const validateTokenId = (props: PropsType) => { +const validateTokenId = (props: sharedMintingValidationProps) => { if (Object.prototype.hasOwnProperty.call(props, 'tokenId')) { if (!props.tokenId) throw new Error(dictionary.hederaActions.tokenIdRequired); } @@ -94,13 +94,13 @@ const validateNFTId = (props: increaseNFTSupplyValidationProps) => { } }; -const validateAmount = (props: PropsType) => { +const validateAmount = (props: sharedMintingValidationProps) => { if (Object.prototype.hasOwnProperty.call(props, 'amount')) { if (!props.amount || props.amount < 1) throw new Error(dictionary.hederaActions.minAmount); } }; -const validateMetaData = (props: PropsType) => { +const validateMetaData = (props: sharedMintingValidationProps) => { if (Object.prototype.hasOwnProperty.call(props, 'metaData')) { if (!props.metaData) throw new Error(dictionary.hederaActions.metadataRequired); } diff --git a/test/unit/increaseNFTSupply.test.ts b/test/unit/increaseNFTSupply.test.ts index 41ffbd9..ad562b7 100644 --- a/test/unit/increaseNFTSupply.test.ts +++ b/test/unit/increaseNFTSupply.test.ts @@ -13,16 +13,22 @@ jest.mock('../../src/utils/validateProps', () => ({ validatePropsForIncreaseNFTSupply: jest.fn(), })); const mockedAxios = axios as jest.Mocked; +const metadata = 'testMetadata'; +const mockResponse = { + //encoding 'testMetadata' as base64 encoded string + metadata: btoa(metadata), +}; +beforeAll(() => { + mockedAxios.get.mockResolvedValue({ + data: mockResponse + }); +}); beforeEach(() => { jest.clearAllMocks(); }); describe('increaseNFTSupply', () => { - const mockMetaData = { - // mock metadata object - }; - const mockNftId = { tokenId: TokenId.fromString('0.0.453'), serial: 1, @@ -32,7 +38,7 @@ describe('increaseNFTSupply', () => { const generatedSupplyKey = PrivateKey.generate(); const mockIncreaseNFTSupplyType: IncreaseNFTSupplyType = { - client: {ledgerId: LedgerId.TESTNET} as Client, + client: { ledgerId: LedgerId.TESTNET } as Client, network: 'testnet', nftId: mockNftId, amount: 10, @@ -42,13 +48,6 @@ describe('increaseNFTSupply', () => { }; it('should validate props before increasing NFT supply', async () => { - const mockResponse = { - metadata: "testMetadata" - }; - mockedAxios.get.mockResolvedValue({ - data: mockResponse - }); - await increaseNFTSupply(mockIncreaseNFTSupplyType); expect((validatePropsForIncreaseNFTSupply as jest.Mock)).toHaveBeenCalledWith({ @@ -58,4 +57,55 @@ describe('increaseNFTSupply', () => { batchSize: 5, }); }); + + it('should increase supply when called with valid props', async () => { + await increaseNFTSupply(mockIncreaseNFTSupplyType); + + expect(mockedAxios.get).toHaveBeenCalledWith('mirrorNodeUrl/tokens/0.0.453/nfts/1'); + expect(mockedAxios.get).toHaveBeenCalledTimes(1); + expect((require('../../src/functions/mintSharedMetadataFunction').mintSharedMetadataFunction as jest.Mock)).toHaveBeenCalledTimes(1); + }); + + it('should call mintSharedMetadataFunction with the correct parameters', async () => { + await increaseNFTSupply(mockIncreaseNFTSupplyType); + + expect((require('../../src/functions/mintSharedMetadataFunction').mintSharedMetadataFunction as jest.Mock)).toHaveBeenCalledWith({ + client: mockIncreaseNFTSupplyType.client, + tokenId: mockIncreaseNFTSupplyType.nftId.tokenId.toString(), + amount: mockIncreaseNFTSupplyType.amount, + batchSize: mockIncreaseNFTSupplyType.batchSize, + metaData: metadata, + supplyKey: mockIncreaseNFTSupplyType.supplyKey, + }); + }); + + it('should call passed mirrorNodeUrl when provided', async () => { + await increaseNFTSupply(mockIncreaseNFTSupplyType); + + expect(mockedAxios.get).toHaveBeenCalledWith('mirrorNodeUrl/tokens/0.0.453/nfts/1'); + }); + + it('should get correct mirror node url for mainnet', async () => { + const mockIncreaseNFTSupplyTypeMainnet = { + ...mockIncreaseNFTSupplyType, + network: 'mainnet', + mirrorNodeUrl: undefined, + }; + + await increaseNFTSupply(mockIncreaseNFTSupplyTypeMainnet); + + expect(mockedAxios.get).toHaveBeenCalledWith('https://mainnet-public.mirrornode.hedera.com/api/v1/tokens/0.0.453/nfts/1'); + }); + + it('should get correct mirror node url for testnet', async () => { + const mockIncreaseNFTSupplyTypeTestnet = { + ...mockIncreaseNFTSupplyType, + network: 'testnet', + mirrorNodeUrl: undefined, + }; + + await increaseNFTSupply(mockIncreaseNFTSupplyTypeTestnet); + + expect(mockedAxios.get).toHaveBeenCalledWith('https://testnet.mirrornode.hedera.com/api/v1/tokens/0.0.453/nfts/1'); + }); }); \ No newline at end of file diff --git a/test/unit/validateProps.test.ts b/test/unit/validateProps.test.ts index 7f4e145..2a2cfbf 100644 --- a/test/unit/validateProps.test.ts +++ b/test/unit/validateProps.test.ts @@ -1,7 +1,8 @@ -import { PrivateKey } from '@hashgraph/sdk'; +import { NftId, PrivateKey } from '@hashgraph/sdk'; import { - validateProps, + validatePropsForSharedNFTMinting, validatePropsForCreateCollection, + validatePropsForIncreaseNFTSupply, validatePropsForUniqueNFTMinting, } from '../../src/utils/validateProps'; import { dictionary } from '../../src/utils/constants/dictionary'; @@ -10,25 +11,25 @@ import { myAccountId, myPrivateKey } from '../__mocks__/consts'; describe('validateProps_Value_Errors', () => { it('should throw an error if batchSize is greater than 10', () => { - expect(() => validateProps({ batchSize: 11 })).toThrow(dictionary.hederaActions.maxBatchSize); + expect(() => validatePropsForSharedNFTMinting({ batchSize: 11 })).toThrow(dictionary.hederaActions.maxBatchSize); }); it('should throw an error if batchSize is less than 1', () => { - expect(() => validateProps({ batchSize: -1 })).toThrow(dictionary.hederaActions.minBatchSize); + expect(() => validatePropsForSharedNFTMinting({ batchSize: -1 })).toThrow(dictionary.hederaActions.minBatchSize); }); it('should throw an error if tokenId is not provided', () => { - expect(() => validateProps({ tokenId: '' })).toThrow(dictionary.hederaActions.tokenIdRequired); + expect(() => validatePropsForSharedNFTMinting({ tokenId: '' })).toThrow(dictionary.hederaActions.tokenIdRequired); }); it('should throw an error if metaData is not provided', () => { - expect(() => validateProps({ metaData: '' })).toThrow( + expect(() => validatePropsForSharedNFTMinting({ metaData: '' })).toThrow( dictionary.hederaActions.metadataRequired ); }); it('should throw an error if supplyKey is not provided', () => { - expect(() => validateProps({ supplyKey: undefined })).toThrow( + expect(() => validatePropsForSharedNFTMinting({ supplyKey: undefined })).toThrow( dictionary.hederaActions.supplyKeyRequired ); }); @@ -36,20 +37,20 @@ describe('validateProps_Value_Errors', () => { describe('validateProps_MultipleProps_Errors', () => { it('should throw an error if batchSize is undefined and tokenId is valid', () => { - expect(() => validateProps({ batchSize: undefined, tokenId: 'token123' })).toThrow( + expect(() => validatePropsForSharedNFTMinting({ batchSize: undefined, tokenId: 'token123' })).toThrow( dictionary.mintToken.batchSizeUndefined ); }); it('should throw an error if amount is undefined and metaData is valid', () => { - expect(() => validateProps({ amount: undefined, metaData: 'metadata123' })).toThrow( + expect(() => validatePropsForSharedNFTMinting({ amount: undefined, metaData: 'metadata123' })).toThrow( dictionary.hederaActions.minAmount ); }); it('should throw an error if supplyKey is undefined and pathToMetadataURIsFile is valid', () => { expect(() => - validateProps({ + validatePropsForSharedNFTMinting({ supplyKey: undefined, batchSize: 9, }) @@ -59,24 +60,24 @@ describe('validateProps_MultipleProps_Errors', () => { describe('validateProps_Success', () => { it('should not throw an error if batchSize is a number between 1 and 10', () => { - expect(() => validateProps({ batchSize: 5 })).not.toThrow(); + expect(() => validatePropsForSharedNFTMinting({ batchSize: 5 })).not.toThrow(); }); it('should not throw an error if tokenId is a string', () => { - expect(() => validateProps({ tokenId: 'token123' })).not.toThrow(); + expect(() => validatePropsForSharedNFTMinting({ tokenId: 'token123' })).not.toThrow(); }); it('should not throw an error if amount is a number greater than 0', () => { - expect(() => validateProps({ amount: 5 })).not.toThrow(); + expect(() => validatePropsForSharedNFTMinting({ amount: 5 })).not.toThrow(); }); it('should not throw an error if metaData is a string', () => { - expect(() => validateProps({ metaData: 'metadata123' })).not.toThrow(); + expect(() => validatePropsForSharedNFTMinting({ metaData: 'metadata123' })).not.toThrow(); }); it('should not throw an error if supplyKey is a PrivateKey', () => { const privateKey = PrivateKey.generate(); - expect(() => validateProps({ supplyKey: privateKey })).not.toThrow(); + expect(() => validatePropsForSharedNFTMinting({ supplyKey: privateKey })).not.toThrow(); }); }); @@ -176,3 +177,50 @@ describe('validatePropsForCreateCollection', () => { ).toThrow(new Error(dictionary.createCollection.clientRequired)); }); }); + +describe('validatePropsForIncreaseNFTSupply', () => { + it('should throw an error if nftId is not provided', () => { + expect(() => + validatePropsForIncreaseNFTSupply({ + amount: 10, + batchSize: 5, + supplyKey: PrivateKey.generate(), + nftId: undefined, + }) + ).toThrow(new Error(dictionary.hederaActions.nftIdRequired)); + }); + + it('should throw an error if amount is not provided', () => { + expect(() => + validatePropsForIncreaseNFTSupply({ + nftId: NftId.fromString('0.0.453/1'), + batchSize: 5, + supplyKey: PrivateKey.generate(), + amount: undefined, + }) + ).toThrow(new Error(dictionary.hederaActions.minAmount)); + }); + + it('should throw an error if supplyKey is not provided', () => { + expect(() => + validatePropsForIncreaseNFTSupply({ + nftId: NftId.fromString('0.0.453/1'), + amount: 10, + batchSize: 5, + supplyKey: undefined, + }) + ).toThrow(new Error(dictionary.hederaActions.supplyKeyRequired)); + }); + + it('should throw an error if batchSize is not provided', () => { + expect(() => + validatePropsForIncreaseNFTSupply({ + nftId: NftId.fromString('0.0.453/1'), + amount: 10, + supplyKey: PrivateKey.generate(), + batchSize: undefined, + }) + ).toThrow(new Error(dictionary.mintToken.batchSizeUndefined)); + }); + +});