-
Notifications
You must be signed in to change notification settings - Fork 15
test: Shared tests for internal wallet methods #1047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
7cc02fa
refactor!: unify changeServer to async
tuliomir 60dd062
test: extract shared network query tests
tuliomir a764b06
test: extract shared server change tests
tuliomir aeb370c
test: extract fullnode-specific internal tests
tuliomir 52195b7
chore: fix lint warnings from extraction
tuliomir 24070dd
fix: adapt tests to facade semantics
tuliomir 82bdfee
fix: address code review feedback
tuliomir e0e11ac
fix: protects originalServerUrl
tuliomir 3f6fcb1
fix: originalServerUrl issues
tuliomir 5181f23
fix: rename misleading test, remove clearListeners
tuliomir 7a17dee
test: strengthen changeServer tests for both facades
tuliomir cad509a
Merge branch 'master' into test/internal-methods-shared
tuliomir File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /** | ||
| * Copyright (c) Hathor Labs and its affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| /** | ||
| * Fullnode-facade internal method tests. | ||
| * | ||
| * Tests HathorWallet-only features: debug mode toggling and storage reload | ||
| * via onConnectionChangedState. These are side-effect tests that mutate | ||
| * wallet state. | ||
| * | ||
| * Shared internal tests live in `shared/internal.test.ts`. | ||
| * Shared server change tests live in `shared/server_changes.test.ts`. | ||
| */ | ||
|
|
||
| import HathorWallet from '../../../src/new/wallet'; | ||
| import { ConnectionState } from '../../../src/wallet/types'; | ||
| import { GenesisWalletHelper } from '../helpers/genesis-wallet.helper'; | ||
| import { generateWalletHelper } from '../helpers/wallet.helper'; | ||
|
|
||
| describe('[Fullnode] internal methods', () => { | ||
| let gWallet: HathorWallet; | ||
| let hWallet: HathorWallet; | ||
|
|
||
| beforeAll(async () => { | ||
| const { hWallet: ghWallet } = await GenesisWalletHelper.getSingleton(); | ||
| gWallet = ghWallet; | ||
| hWallet = await generateWalletHelper(); | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| await hWallet.stop(); | ||
| }); | ||
|
|
||
| it('should test the debug methods', async () => { | ||
| expect(gWallet.debug).toStrictEqual(false); | ||
|
|
||
| gWallet.enableDebugMode(); | ||
| expect(gWallet.debug).toStrictEqual(true); | ||
|
|
||
| gWallet.disableDebugMode(); | ||
| expect(gWallet.debug).toStrictEqual(false); | ||
| }); | ||
|
|
||
| it('should call processHistory when connection state changes to CONNECTED', async () => { | ||
| await GenesisWalletHelper.injectFunds(hWallet, await hWallet.getAddressAtIndex(0), 10n); | ||
| const spy = jest.spyOn(hWallet.storage, 'processHistory'); | ||
| // Simulate that we received an event of the connection becoming active | ||
| await hWallet.onConnectionChangedState(ConnectionState.CONNECTED); | ||
| expect(spy).toHaveBeenCalledTimes(1); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,16 +9,10 @@ import { | |
| waitUntilNextTimestamp, | ||
| } from './helpers/wallet.helper'; | ||
| import { NATIVE_TOKEN_UID, TOKEN_MELT_MASK, TOKEN_MINT_MASK } from '../../src/constants'; | ||
| import { | ||
| FULLNODE_NETWORK_NAME, | ||
| FULLNODE_URL, | ||
| NETWORK_NAME, | ||
| WALLET_CONSTANTS, | ||
| } from './configuration/test-constants'; | ||
| import { WALLET_CONSTANTS } from './configuration/test-constants'; | ||
| import dateFormatter from '../../src/utils/date'; | ||
| import { AddressError } from '../../src/errors'; | ||
| import { precalculationHelpers } from './helpers/wallet-precalculation.helper'; | ||
| import { ConnectionState } from '../../src/wallet/types'; | ||
| import HathorWallet from '../../src/new/wallet'; | ||
| import { MemoryStore } from '../../src/storage'; | ||
| import { IHistoryTx } from '../../src/types'; | ||
|
|
@@ -1617,94 +1611,6 @@ describe('getAuthorityUtxos', () => { | |
| }); | ||
| }); | ||
|
|
||
| // This section tests methods that have side effects impacting the whole wallet. Executing it last. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. <3 |
||
| describe('internal methods', () => { | ||
| /** @type HathorWallet */ | ||
| let gWallet; | ||
| /** @type HathorWallet */ | ||
| let hWallet; | ||
| beforeAll(async () => { | ||
| const { hWallet: ghWallet } = await GenesisWalletHelper.getSingleton(); | ||
| gWallet = ghWallet; | ||
| hWallet = await generateWalletHelper(); | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| hWallet.stop(); | ||
| await GenesisWalletHelper.clearListeners(); | ||
| await gWallet.stop(); | ||
| }); | ||
|
|
||
| it('should test the debug methods', async () => { | ||
| expect(gWallet.debug).toStrictEqual(false); | ||
|
|
||
| gWallet.enableDebugMode(); | ||
| expect(gWallet.debug).toStrictEqual(true); | ||
|
|
||
| gWallet.disableDebugMode(); | ||
| expect(gWallet.debug).toStrictEqual(false); | ||
| }); | ||
|
|
||
| it('should test network-related methods', async () => { | ||
| // GetServerUrl fetching from the live fullnode connection | ||
| expect(await gWallet.getServerUrl()).toStrictEqual(FULLNODE_URL); | ||
| expect(await gWallet.getNetwork()).toStrictEqual(NETWORK_NAME); | ||
| expect(await gWallet.getNetworkObject()).toMatchObject({ | ||
| name: NETWORK_NAME, | ||
| versionBytes: { p2pkh: 73, p2sh: 135 }, // Calculated for the privnet.py config file | ||
| bitcoreNetwork: { | ||
| name: expect.stringContaining(NETWORK_NAME), | ||
| alias: 'test', // this is the alias for the testnet network | ||
| pubkeyhash: 73, | ||
| scripthash: 135, | ||
| }, | ||
| }); | ||
|
|
||
| // GetVersionData fetching from the live fullnode server | ||
| expect(await gWallet.getVersionData()).toMatchObject({ | ||
| timestamp: expect.any(Number), | ||
| version: expect.any(String), | ||
| network: FULLNODE_NETWORK_NAME, | ||
| minWeight: expect.any(Number), | ||
| minTxWeight: expect.any(Number), | ||
| minTxWeightCoefficient: expect.any(Number), | ||
| minTxWeightK: expect.any(Number), | ||
| tokenDepositPercentage: 0.01, | ||
| rewardSpendMinBlocks: expect.any(Number), | ||
| maxNumberInputs: 255, | ||
| maxNumberOutputs: 255, | ||
| }); | ||
| }); | ||
|
|
||
| it('should change servers', async () => { | ||
| // Changing from our integration test privatenet to the testnet | ||
| gWallet.changeServer('https://node1.testnet.hathor.network/v1a/'); | ||
| const serverChangeTime = Date.now().valueOf(); | ||
| await delay(100); | ||
|
|
||
| // Validating the server change with getVersionData | ||
| let networkData = await gWallet.getVersionData(); | ||
| expect(networkData.timestamp).toBeGreaterThan(serverChangeTime); | ||
| expect(networkData.network).toMatch(/^testnet.*/); | ||
|
|
||
| await gWallet.changeServer(FULLNODE_URL); | ||
| await delay(100); | ||
|
|
||
| // Reverting to the privatenet | ||
| networkData = await gWallet.getVersionData(); | ||
| expect(networkData.timestamp).toBeGreaterThan(serverChangeTime + 200); | ||
| expect(networkData.network).toStrictEqual(FULLNODE_NETWORK_NAME); | ||
| }); | ||
|
|
||
| it('should reload the storage', async () => { | ||
| await GenesisWalletHelper.injectFunds(hWallet, await hWallet.getAddressAtIndex(0), 10n); | ||
| const spy = jest.spyOn(hWallet.storage, 'processHistory'); | ||
| // Simulate that we received an event of the connection becoming active | ||
| await hWallet.onConnectionChangedState(ConnectionState.CONNECTED); | ||
| expect(spy).toHaveBeenCalledTimes(1); | ||
| }); | ||
| }); | ||
|
|
||
| describe('index-limit address scanning policy', () => { | ||
| /** @type HathorWallet */ | ||
| let hWallet; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /** | ||
| * Copyright (c) Hathor Labs and its affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| import axios from 'axios'; | ||
| import type { FuzzyWalletType, IWalletTestAdapter } from '../adapters/types'; | ||
| import { FullnodeWalletTestAdapter } from '../adapters/fullnode.adapter'; | ||
| import { ServiceWalletTestAdapter } from '../adapters/service.adapter'; | ||
| import { FULLNODE_NETWORK_NAME, FULLNODE_URL, NETWORK_NAME } from '../configuration/test-constants'; | ||
| import Network from '../../../src/models/network'; | ||
| import { loggers } from '../utils/logger.util'; | ||
|
|
||
| // XXX: onConnectionChangedState has different behavior between facades | ||
| // (fullnode calls reloadStorage/processHistory, service emits 'reload-data'). | ||
| // It needs refactoring before it can be tested here as a shared test. | ||
|
|
||
| const adapters: IWalletTestAdapter[] = [ | ||
| new FullnodeWalletTestAdapter(), | ||
| new ServiceWalletTestAdapter(), | ||
| ]; | ||
|
|
||
| /** | ||
| * Minimum expected shape for getVersionData across both facades. | ||
| * Both facades should query the fullnode /version endpoint and return | ||
| * the same data. If a backend inconsistency is found for a specific | ||
| * facade, adjust the corresponding adapter's `versionDataOverrides` | ||
| * or skip individual fields here rather than duplicating the test. | ||
| */ | ||
| const baseVersionDataExpectation = { | ||
| timestamp: expect.any(Number), | ||
| version: expect.any(String), | ||
| network: FULLNODE_NETWORK_NAME, | ||
| minWeight: expect.any(Number), | ||
| minTxWeight: expect.any(Number), | ||
| minTxWeightCoefficient: expect.any(Number), | ||
| minTxWeightK: expect.any(Number), | ||
| tokenDepositPercentage: expect.any(Number), | ||
| rewardSpendMinBlocks: expect.any(Number), | ||
| maxNumberInputs: expect.any(Number), | ||
| maxNumberOutputs: expect.any(Number), | ||
| }; | ||
|
|
||
| describe.each(adapters)('[Shared] internal methods — $name', adapter => { | ||
| beforeAll(async () => { | ||
| await adapter.suiteSetup(); | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| await adapter.suiteTeardown(); | ||
| }); | ||
|
|
||
| describe('network query methods', () => { | ||
| let wallet: FuzzyWalletType; | ||
|
|
||
| beforeAll(async () => { | ||
| const result = await adapter.createWallet(); | ||
| wallet = result.wallet; | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| await adapter.stopWallet(wallet); | ||
| }); | ||
|
|
||
| it('getServerUrl returns the configured fullnode URL', () => { | ||
| expect(wallet.getServerUrl()).toBe(FULLNODE_URL); | ||
| }); | ||
|
|
||
| it('getNetwork returns the correct network name', () => { | ||
| expect(wallet.getNetwork()).toBe(NETWORK_NAME); | ||
| }); | ||
|
|
||
| it('getNetworkObject returns a Network instance with correct properties', () => { | ||
| const networkObj = wallet.getNetworkObject(); | ||
| expect(networkObj).toBeInstanceOf(Network); | ||
| expect(networkObj.name).toBe(NETWORK_NAME); | ||
| expect(networkObj).toMatchObject({ | ||
| versionBytes: { p2pkh: 73, p2sh: 135 }, | ||
| bitcoreNetwork: { | ||
| name: expect.stringContaining(NETWORK_NAME), | ||
| alias: 'test', | ||
| pubkeyhash: 73, | ||
| scripthash: 135, | ||
| }, | ||
| }); | ||
| }); | ||
|
|
||
| it('getVersionData returns valid version info from the fullnode', async () => { | ||
| const versionData = await wallet.getVersionData(); | ||
| expect(versionData).toMatchObject(baseVersionDataExpectation); | ||
| }); | ||
|
|
||
| it('getVersionData matches data from a direct fullnode request', async () => { | ||
| const versionData = await wallet.getVersionData(); | ||
|
|
||
| // The raw fullnode /version endpoint returns snake_case keys. | ||
| // Both facades transform these to camelCase in getVersionData(). | ||
| const directResponse = await axios | ||
| .get('version', { | ||
| baseURL: FULLNODE_URL, | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| }) | ||
| .catch(e => { | ||
| loggers.test!.log(`Received an error on /version: ${e}`); | ||
| if (e.response) { | ||
| return e.response; | ||
| } | ||
| throw e; | ||
| }); | ||
| expect(directResponse.status).toBe(200); | ||
|
|
||
| // Map raw snake_case keys to the camelCase keys returned by the facades. | ||
| // This allows us to verify both facades faithfully represent the fullnode. | ||
| const rawToFacade: Record<string, string> = { | ||
| version: 'version', | ||
| network: 'network', | ||
| min_weight: 'minWeight', | ||
| min_tx_weight: 'minTxWeight', | ||
| min_tx_weight_coefficient: 'minTxWeightCoefficient', | ||
| min_tx_weight_k: 'minTxWeightK', | ||
| token_deposit_percentage: 'tokenDepositPercentage', | ||
| reward_spend_min_blocks: 'rewardSpendMinBlocks', | ||
| max_number_inputs: 'maxNumberInputs', | ||
| max_number_outputs: 'maxNumberOutputs', | ||
| }; | ||
|
|
||
| const fullnodeData = directResponse.data; | ||
| for (const [rawKey, facadeKey] of Object.entries(rawToFacade)) { | ||
| expect(fullnodeData).toHaveProperty(rawKey); | ||
| expect(versionData).toHaveProperty(facadeKey); | ||
| expect(versionData[facadeKey]).toStrictEqual(fullnodeData[rawKey]); | ||
| } | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you using the published url?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to switch to another valid network to validate the connection works well and the internal methods return actual content and not stale cache. The public testnet seemed like a good candidate for that.