-
Notifications
You must be signed in to change notification settings - Fork 25
Integration Tests: balance, tx-history, address-info and transaction routes #149
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 34 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
32d426c
test: Implementing first integrated tests with the fullnode
tuliomir 74ae7df
test: Working proof-of-concept
tuliomir b4d171f
refactor: moved integration test to separate folder + config file
tuliomir d7d9928
feat: first draft for logging test network transactions
tuliomir 5d809f1
test: first balance tests
tuliomir ffef8f4
feat: log filename indicates the suite it tested
tuliomir 1109c6c
test: implementing private network on docker images
tuliomir d352c11
test: mining private network on docker images
tuliomir 0011c2b
test: testing on github workflow
tuliomir 074f93b
fix: uploading artifacts despite failure for debugging
tuliomir 15f0952
feat: single command to build network environment, test and cleanup
tuliomir 48b6721
fix: delaying injectFundsIntoAddress to avoid workflow failures
tuliomir bca7248
test: create token test
tuliomir 6943285
test: testing failure, but did not work with local cache
tuliomir 79d82c4
test: tx history tests without error handling
tuliomir 499e6ca
test: address info tests without error handling
tuliomir cf62ff3
test: transaction route tests without error handling
tuliomir 8a560b5
chore: changed integration test workflow to run on dev and master
tuliomir b1b6637
docs: Adds various comments and documentations to the Integration Tests
tuliomir c0f84c5
fix: lgtm raised issues
tuliomir 97840f3
fix: mocked tests ignore paths
tuliomir 4c5505c
style: integration tests linting
tuliomir 9605fbe
fix: getRandomInt function had incorrect logic
tuliomir 3b0c73b
chore: removing proof of concept file
tuliomir 3562086
style: eslint fixes
tuliomir 88f7061
docs: clarifying jsdocs and comments
tuliomir b7c31f0
fix: minor failures on log helpers
tuliomir 693025a
test: new tests for locked balances
tuliomir f0adf8f
test: new assertions for transaction order
tuliomir b033b81
style: fix eslint parens
tuliomir f58a436
refactor: improve wallet startup's "status" validation
tuliomir 4b9be13
refactor: using the WalletHelper.createToken instead of a direct http
tuliomir 4173e04
fix: locked amount on addresses is not fixed as supposed
tuliomir 080bc76
refactor: improving lib code reuse
tuliomir a1e6341
Update __tests__/integration/utils/test-utils-integration.js
tuliomir ccdb2d8
Update __tests__/integration/utils/wallet-helper.js
tuliomir 7e43ad6
refactor: error handling on logger
tuliomir 41c4600
refactor: txLogger now using winston instead of direct fs
tuliomir e6dc2e4
refactor: txLogger adapter to better use of winston logs
tuliomir 72f8898
refactor: logs folder now fetched from config file
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"extends": "airbnb-base", | ||
"parser": "@babel/eslint-parser", | ||
"rules": { | ||
"arrow-parens": ["error", "as-needed"], | ||
"import/no-named-as-default": 0, | ||
"import/prefer-default-export": 0, | ||
"quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], | ||
"comma-dangle": 0, | ||
"object-curly-newline": ["error", {"ObjectPattern": { "multiline": true }}], | ||
"eqeqeq": [1, "allow-null"], | ||
"no-continue": 0, | ||
"no-cond-assign": 1, | ||
"no-constant-condition": 0, | ||
"no-control-regex": 1, | ||
"no-debugger": 1, | ||
"no-dupe-keys": 1, | ||
"no-ex-assign": 1, | ||
"no-extra-boolean-cast": 1, | ||
"no-func-assign": 1, | ||
"no-regex-spaces": 1, | ||
"no-unreachable": 1, | ||
"no-fallthrough": 1, | ||
"no-lone-blocks": 1, | ||
"no-delete-var": 1, | ||
"no-shadow": 1, | ||
"no-shadow-restricted-names": 1, | ||
"no-undef": 2, | ||
"no-undef-init": 1, | ||
"no-use-before-define": 0, | ||
"no-unused-vars": [1, {"vars": "all", "args": "none"}], | ||
"no-underscore-dangle": 0, | ||
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"], | ||
"no-await-in-loop": "off", | ||
"no-plusplus": "off", | ||
"guard-for-in": "off" | ||
}, | ||
"overrides": [ | ||
{ | ||
"files": [ | ||
"**/*.test.js" | ||
], | ||
"env": { | ||
"jest": true | ||
} | ||
} | ||
] | ||
} |
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,44 @@ | ||
name: integration-test | ||
on: | ||
push: | ||
branches: | ||
- master | ||
- dev | ||
tags: | ||
- v* | ||
pull_request: | ||
branches: | ||
- dev | ||
- master | ||
jobs: | ||
itest: | ||
runs-on: ubuntu-20.04 | ||
timeout-minutes: 20 | ||
|
||
strategy: | ||
matrix: | ||
node-version: [14.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
|
||
- name: Install dependencies | ||
run: npm install | ||
|
||
- name: Copy config file | ||
run: cp ./__tests__/integration/configuration/config.js.template ./src/config.js | ||
|
||
- name: Run the tests | ||
run: npm run test_integration | ||
|
||
- name: Upload debug transaction logs | ||
if: always() | ||
uses: actions/upload-artifact@v2 | ||
with: | ||
name: test-transacion-logs | ||
path: tmp |
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,176 @@ | ||
import { | ||
getRandomInt, | ||
HATHOR_TOKEN_ID, | ||
TestUtils, | ||
WALLET_CONSTANTS | ||
} from './utils/test-utils-integration'; | ||
import { WalletHelper } from './utils/wallet-helper'; | ||
|
||
describe('address-info routes', () => { | ||
let wallet1; | ||
let wallet2; | ||
const address1balance = getRandomInt(200, 100); | ||
let customTokenHash; | ||
|
||
beforeAll(async () => { | ||
try { | ||
// A random HTR value for the first wallet | ||
wallet1 = new WalletHelper('addinfo-1'); | ||
await wallet1.start(); | ||
await wallet1.injectFunds(address1balance, 1); | ||
|
||
// A fixed custom token amount for the second wallet | ||
wallet2 = new WalletHelper('addinfo-2'); | ||
await wallet2.start(); | ||
await wallet2.injectFunds(10); | ||
const customToken = await wallet2.createToken({ | ||
amount: 500, | ||
name: 'AddInfo Token', | ||
symbol: 'AIT', | ||
address: await wallet2.getAddressAt(1), | ||
change_address: await wallet2.getAddressAt(0) | ||
}); | ||
customTokenHash = customToken.hash; | ||
|
||
/* | ||
* The state here should be: | ||
* wallet1[1] with some value between 100 and 200 HTR | ||
* wallet2[0] with 5 HTR | ||
* wallet2[1] with 500 AIT | ||
*/ | ||
} catch (err) { | ||
TestUtils.logError(err.stack); | ||
} | ||
}); | ||
|
||
afterAll(async () => { | ||
await wallet1.stop(); | ||
await wallet2.stop(); | ||
}); | ||
|
||
it('should return results for an address (empty)', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ address: await wallet1.getAddressAt(0) }) | ||
.set({ 'x-wallet-id': wallet1.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(HATHOR_TOKEN_ID); | ||
expect(results.index).toBe(0); | ||
expect(results.total_amount_received).toBe(0); | ||
expect(results.total_amount_sent).toBe(0); | ||
expect(results.total_amount_available).toBe(0); | ||
expect(results.total_amount_locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return results for an address with a single receiving transaction', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ address: await wallet1.getAddressAt(1) }) | ||
.set({ 'x-wallet-id': wallet1.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(HATHOR_TOKEN_ID); | ||
expect(results.index).toBe(1); | ||
expect(results.total_amount_received).toBe(address1balance); | ||
expect(results.total_amount_sent).toBe(0); | ||
expect(results.total_amount_available).toBe(address1balance); | ||
expect(results.total_amount_locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return correct locked balance for an address with miner rewards', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ address: WALLET_CONSTANTS.genesis.addresses[1] }) // Miner rewards address | ||
.set({ 'x-wallet-id': WALLET_CONSTANTS.genesis.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(HATHOR_TOKEN_ID); | ||
expect(results.index).toBe(2); | ||
expect(results.total_amount_received).toBeGreaterThan(0); | ||
|
||
/* | ||
* According to the REWARD_SPEND_MIN_BLOCKS variable in the ./configuration/privnet.py file | ||
* the miner rewards are locked for exactly one block. Since we have only one miner reward | ||
* address, this value should be always 6400 or greater. | ||
* | ||
* Should another miner reward address be included later, this assertion must be recalculated. | ||
*/ | ||
expect(results.total_amount_locked).toBeGreaterThanOrEqual(6400); | ||
done(); | ||
}); | ||
|
||
it('should return results for an address with send/receive transactions', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ address: await wallet2.getAddressAt(0) }) | ||
.set({ 'x-wallet-id': wallet2.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(HATHOR_TOKEN_ID); | ||
expect(results.index).toBe(0); | ||
expect(results.total_amount_received).toBe(15); // 10 from genesis, 5 from token creation change | ||
expect(results.total_amount_sent).toBe(10); // token creation tx | ||
expect(results.total_amount_available).toBe(5); // change | ||
expect(results.total_amount_locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return results for custom token for an address (empty)', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ | ||
address: await wallet2.getAddressAt(0), | ||
token: customTokenHash, | ||
}) | ||
.set({ 'x-wallet-id': wallet2.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(customTokenHash); | ||
expect(results.index).toBe(0); | ||
expect(results.total_amount_received).toBe(0); | ||
expect(results.total_amount_sent).toBe(0); | ||
expect(results.total_amount_available).toBe(0); | ||
expect(results.total_amount_locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return results for custom token on an address with a single transaction', async done => { | ||
const response = await TestUtils.request | ||
.get('/wallet/address-info') | ||
.query({ | ||
address: await wallet2.getAddressAt(1), | ||
token: customTokenHash, | ||
}) | ||
.set({ 'x-wallet-id': wallet2.walletId }); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
const results = response.body; | ||
expect(results.success).toBeTruthy(); | ||
expect(results.token).toBe(customTokenHash); | ||
expect(results.index).toBe(1); | ||
expect(results.total_amount_received).toBe(500); | ||
expect(results.total_amount_sent).toBe(0); | ||
expect(results.total_amount_available).toBe(500); | ||
expect(results.total_amount_locked).toBe(0); | ||
done(); | ||
}); | ||
}); |
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,102 @@ | ||
import { getRandomInt, TestUtils, WALLET_CONSTANTS } from './utils/test-utils-integration'; | ||
import { WalletHelper } from './utils/wallet-helper'; | ||
|
||
describe('balance routes', () => { | ||
/** @type WalletHelper */ | ||
let wallet1; | ||
let wallet2; | ||
let wallet3; | ||
const wallet2Balance = getRandomInt(200); | ||
|
||
beforeAll(async () => { | ||
try { | ||
// First wallet, no balance | ||
wallet1 = new WalletHelper('balance1'); | ||
await wallet1.start(); | ||
|
||
// Second wallet, random balance | ||
wallet2 = new WalletHelper('balance2'); | ||
await wallet2.start(); | ||
await wallet2.injectFunds(wallet2Balance); | ||
|
||
// Third wallet, balance to be used for custom tokens | ||
wallet3 = new WalletHelper('custom3'); | ||
await wallet3.start(); | ||
await wallet3.injectFunds(100); | ||
} catch (err) { | ||
TestUtils.logError(err.stack); | ||
} | ||
}); | ||
|
||
afterAll(async () => { | ||
await wallet1.stop(); | ||
await wallet2.stop(); | ||
await wallet3.stop(); | ||
}); | ||
|
||
it('should return zero for an empty wallet', async done => { | ||
const balanceResult = await TestUtils.request | ||
.get('/wallet/balance') | ||
.set({ 'x-wallet-id': wallet1.walletId }); | ||
|
||
expect(balanceResult.body.available).toBe(0); | ||
expect(balanceResult.body.locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return correct balance for a wallet with one transaction', async done => { | ||
const balanceResult = await TestUtils.request | ||
.get('/wallet/balance') | ||
.set({ 'x-wallet-id': wallet2.walletId }); | ||
|
||
expect(balanceResult.body.available).toBe(wallet2Balance); | ||
expect(balanceResult.body.locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return some locked balance for the miner wallet', async done => { | ||
const balanceResult = await TestUtils.request | ||
.get('/wallet/balance') | ||
.set({ 'x-wallet-id': WALLET_CONSTANTS.genesis.walletId }); | ||
|
||
/* | ||
* According to the REWARD_SPEND_MIN_BLOCKS variable in the ./configuration/privnet.py file | ||
* the miner rewards are locked for exactly one block. Since we have only one miner reward | ||
* address, this value should be always 6400 or greater. | ||
* | ||
* Should another miner reward address be included later, this assertion must be recalculated. | ||
*/ | ||
expect(balanceResult.body.locked).toBeGreaterThanOrEqual(6400); | ||
done(); | ||
}); | ||
|
||
it('should return correct balance for a custom token (empty)', async done => { | ||
const balanceResult = await TestUtils.request | ||
.get('/wallet/balance') | ||
.query({ token: 'TST' }) | ||
.set({ 'x-wallet-id': wallet1.walletId }); | ||
|
||
expect(balanceResult.body.available).toBe(0); | ||
expect(balanceResult.body.locked).toBe(0); | ||
done(); | ||
}); | ||
|
||
it('should return correct balance for a custom token', async done => { | ||
const tokenAmount = getRandomInt(200, 100); | ||
const newToken = await wallet3.createToken({ | ||
name: 'Test Token', | ||
symbol: 'TST', | ||
amount: tokenAmount, | ||
}); | ||
const tokenHash = newToken.hash; | ||
|
||
const balanceResult = await TestUtils.request | ||
.get('/wallet/balance') | ||
.query({ token: tokenHash }) | ||
.set({ 'x-wallet-id': wallet3.walletId }); | ||
|
||
expect(balanceResult.body.available).toBe(tokenAmount); | ||
expect(balanceResult.body.locked).toBe(0); | ||
done(); | ||
}); | ||
}); |
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.
Uh oh!
There was an error while loading. Please reload this page.