Skip to content

Commit aa2aea5

Browse files
authored
e2e tests (#663)
1 parent 4938b3d commit aa2aea5

29 files changed

+1226
-184
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,4 @@ dist/
9090
ts-docs
9191
docs/
9292
.vscode/launch.json
93+
/target/

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ cache:
66
directories:
77
- "node_modules"
88
- .eslintcache
9+
jobs:
10+
include:
11+
- stage: e2e
12+
script: npm run test:e2e
13+
if: branch = e2e
914
before_script:
1015
- npm run build
1116
- if [ "$TRAVIS_NODE_VERSION" = "10" ] || [ "$TRAVIS_NODE_VERSION" = "12" ]; then npm run lint; fi

e2e/e2e-preset.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
nemesis:
2+
mosaics:
3+
- accounts: 10

e2e/infrastructure/AccountHttp.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe('AccountHttp', () => {
5757
let networkType: NetworkType;
5858

5959
before(() => {
60-
return helper.start().then(() => {
60+
return helper.start({ openListener: true }).then(() => {
6161
account = helper.account;
6262
account2 = helper.account2;
6363
multisigAccount = helper.multisigAccount;
@@ -73,12 +73,9 @@ describe('AccountHttp', () => {
7373
namespaceRepository = helper.repositoryFactory.createNamespaceRepository();
7474
});
7575
});
76-
before(() => {
77-
return helper.listener.open();
78-
});
7976

8077
after(() => {
81-
helper.listener.close();
78+
return helper.close();
8279
});
8380

8481
/**

e2e/infrastructure/BlockHttp.spec.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('BlockHttp', () => {
4444
let transactionHash;
4545

4646
before(() => {
47-
return helper.start().then(() => {
47+
return helper.start({ openListener: true }).then(() => {
4848
account = helper.account;
4949
account2 = helper.account2;
5050
generationHash = helper.generationHash;
@@ -54,12 +54,8 @@ describe('BlockHttp', () => {
5454
});
5555
});
5656

57-
before(() => {
58-
return helper.listener.open();
59-
});
60-
6157
after(() => {
62-
helper.listener.close();
58+
return helper.close();
6359
});
6460

6561
/**
@@ -69,7 +65,7 @@ describe('BlockHttp', () => {
6965
*/
7066

7167
describe('Setup Test Data', () => {
72-
it('Announce TransferTransaction', () => {
68+
it('Announce TransferTransaction FER', () => {
7369
const transferTransaction = TransferTransaction.create(
7470
Deadline.create(),
7571
account2.address,

e2e/infrastructure/ChainHttp.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ describe('ChainHttp', () => {
2323
let chainRepository: ChainRepository;
2424

2525
before(() => {
26-
return helper.start().then(() => {
26+
return helper.start({ openListener: false }).then(() => {
2727
chainRepository = helper.repositoryFactory.createChainRepository();
2828
});
2929
});
3030

31+
after(() => {
32+
return helper.close();
33+
});
34+
3135
describe('getBlockchainHeight', () => {
3236
it('should return blockchain height', async () => {
3337
const height = await chainRepository.getBlockchainHeight().toPromise();

e2e/infrastructure/IntegrationTestHelper.ts

Lines changed: 89 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,22 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import { combineLatest } from 'rxjs';
16+
import * as fs from 'fs';
17+
import * as path from 'path';
1718
import { map } from 'rxjs/operators';
19+
import { BootstrapService, BootstrapUtils, ConfigPreset, Preset, StartParams } from 'symbol-bootstrap';
1820
import { IListener } from '../../src/infrastructure/IListener';
1921
import { RepositoryFactory } from '../../src/infrastructure/RepositoryFactory';
2022
import { RepositoryFactoryHttp } from '../../src/infrastructure/RepositoryFactoryHttp';
2123
import { Account } from '../../src/model/account/Account';
24+
import { NetworkCurrencyLocal } from '../../src/model/mosaic/NetworkCurrencyLocal';
25+
import { NetworkCurrencyPublic } from '../../src/model/mosaic/NetworkCurrencyPublic';
26+
import { NamespaceId } from '../../src/model/namespace/NamespaceId';
2227
import { NetworkType } from '../../src/model/network/NetworkType';
2328
import { SignedTransaction } from '../../src/model/transaction/SignedTransaction';
2429
import { Transaction } from '../../src/model/transaction/Transaction';
2530
import { UInt64 } from '../../src/model/UInt64';
2631
import { TransactionService } from '../../src/service/TransactionService';
27-
import { NetworkCurrencyPublic } from '../../src/model/mosaic/NetworkCurrencyPublic';
28-
import { NetworkCurrencyLocal } from '../../src/model/mosaic/NetworkCurrencyLocal';
29-
import { NamespaceId } from '../../src/model/namespace/NamespaceId';
30-
import * as yaml from 'js-yaml';
31-
import * as path from 'path';
32-
import * as fs from 'fs';
3332

3433
export class IntegrationTestHelper {
3534
public apiUrl: string;
@@ -50,83 +49,95 @@ export class IntegrationTestHelper {
5049
public transactionService: TransactionService;
5150
public networkCurrencyNamespaceId: NamespaceId;
5251
public networkCurrencyDivisibility: number;
52+
public service = new BootstrapService();
53+
public config: StartParams;
54+
public startEachTime = true;
5355

54-
start(): Promise<IntegrationTestHelper> {
55-
return new Promise<IntegrationTestHelper>((resolve, reject) => {
56-
fs.readFile(path.resolve(__dirname, '../conf/network.conf'), (err, jsonData: any) => {
57-
if (err) {
58-
return reject(err);
59-
}
60-
const json = JSON.parse(jsonData);
61-
console.log(`Running tests against: ${json.apiUrl}`);
62-
this.apiUrl = json.apiUrl;
63-
this.repositoryFactory = new RepositoryFactoryHttp(json.apiUrl);
64-
this.transactionService = new TransactionService(
65-
this.repositoryFactory.createTransactionRepository(),
66-
this.repositoryFactory.createReceiptRepository(),
67-
);
68-
combineLatest(this.repositoryFactory.getGenerationHash(), this.repositoryFactory.getNetworkType()).subscribe(
69-
([generationHash, networkType]) => {
70-
this.networkType = networkType;
71-
this.generationHash = generationHash;
72-
this.account = this.createAccount(json.testAccount);
73-
this.account2 = this.createAccount(json.testAccount2);
74-
this.account3 = this.createAccount(json.testAccount3);
75-
this.multisigAccount = this.createAccount(json.multisigAccount);
76-
this.cosignAccount1 = this.createAccount(json.cosignatoryAccount);
77-
this.cosignAccount2 = this.createAccount(json.cosignatory2Account);
78-
this.cosignAccount3 = this.createAccount(json.cosignatory3Account);
79-
this.cosignAccount4 = this.createAccount(json.cosignatory4Account);
80-
this.harvestingAccount = this.createAccount(json.harvestingAccount);
81-
this.listener = this.repositoryFactory.createListener();
56+
private async startBootstrapServer(): Promise<{ accounts: string[]; apiUrl: string }> {
57+
this.config = {
58+
preset: Preset.bootstrap,
59+
reset: this.startEachTime,
60+
customPreset: './e2e/e2e-preset.yml',
61+
timeout: 60000 * 3,
62+
target: 'target/bootstrap-test',
63+
daemon: false,
64+
user: 'current',
65+
};
8266

83-
// What would be the best maxFee? In the future we will load the fee multiplier from rest.
84-
this.maxFee = UInt64.fromUint(1000000);
67+
console.log('Starting bootstrap server');
68+
const configResult = await this.service.start({ ...this.config, daemon: true });
69+
const accounts = configResult.addresses?.mosaics?.['currency'].map((n) => n.privateKey);
70+
if (!accounts) {
71+
throw new Error('Nemesis accounts could not be loaded!');
72+
}
73+
return { accounts, apiUrl: 'http://localhost:3000' };
74+
}
8575

86-
// network Currency
87-
this.networkCurrencyNamespaceId = this.apiUrl.toLowerCase().includes('localhost')
88-
? NetworkCurrencyLocal.NAMESPACE_ID
89-
: NetworkCurrencyPublic.NAMESPACE_ID;
90-
this.networkCurrencyDivisibility = this.apiUrl.toLowerCase().includes('localhost')
91-
? NetworkCurrencyLocal.DIVISIBILITY
92-
: NetworkCurrencyPublic.DIVISIBILITY;
76+
async close(): Promise<void> {
77+
if (this.listener && this.listener.isOpen()) await this.listener.close();
78+
if (this.config && this.startEachTime) {
79+
console.log('Stopping bootstrap server....');
80+
await this.service.stop(this.config);
81+
await BootstrapUtils.sleep(2000);
82+
}
83+
}
9384

94-
const bootstrapRoot =
95-
process.env.CATAPULT_SERVICE_BOOTSTRAP || path.resolve(__dirname, '../../../../catapult-service-bootstrap');
96-
const bootstrapPath = `${bootstrapRoot}/build/generated-addresses/addresses.yaml`;
97-
fs.readFile(bootstrapPath, (error: any, yamlData: any) => {
98-
if (error) {
99-
console.log(
100-
`catapult-service-bootstrap generated address could not be loaded from path ${bootstrapPath}. Ignoring and using accounts from network.conf.`,
101-
);
102-
return resolve(this);
103-
} else {
104-
console.log(`catapult-service-bootstrap generated address loaded from path ${bootstrapPath}.`);
105-
const parsedYaml = yaml.safeLoad(yamlData);
106-
this.account = this.createAccount(parsedYaml.nemesis_addresses[0]);
107-
this.account2 = this.createAccount(parsedYaml.nemesis_addresses[1]);
108-
this.account3 = this.createAccount(parsedYaml.nemesis_addresses[2]);
109-
this.multisigAccount = this.createAccount(parsedYaml.nemesis_addresses[3]);
110-
this.cosignAccount1 = this.createAccount(parsedYaml.nemesis_addresses[4]);
111-
this.cosignAccount2 = this.createAccount(parsedYaml.nemesis_addresses[5]);
112-
this.cosignAccount3 = this.createAccount(parsedYaml.nemesis_addresses[6]);
113-
this.cosignAccount4 = this.createAccount(parsedYaml.nemesis_addresses[7]);
114-
this.harvestingAccount = this.createAccount(parsedYaml.nemesis_addresses_harvesting[0]);
115-
return resolve(this);
116-
}
117-
});
118-
},
119-
(error) => {
120-
console.log('There has been an error loading the configuration. ', error);
121-
return reject(error);
122-
},
123-
);
124-
});
125-
});
85+
private async connectToExternalServer(): Promise<{ accounts: string[]; apiUrl: string }> {
86+
const json = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../conf/network.conf'), 'utf8'));
87+
const accounts = [
88+
json.testAccount.privateKey,
89+
json.testAccount2.privateKey,
90+
json.testAccount3.privateKey,
91+
json.multisigAccount.privateKey,
92+
json.cosignatoryAccount.privateKey,
93+
json.cosignatory2Account.privateKey,
94+
json.cosignatory3Account.privateKey,
95+
json.cosignatory4Account.privateKey,
96+
json.harvestingAccount.privateKey,
97+
];
98+
return { accounts, apiUrl: json.apiUrl };
12699
}
127100

128-
createAccount(data): Account {
129-
return Account.createFromPrivateKey(data.privateKey ? data.privateKey : data.private, this.networkType);
101+
async start({ openListener }: { openListener: boolean }): Promise<IntegrationTestHelper> {
102+
// await this.service.stop(this.config);
103+
const config = await this.startBootstrapServer();
104+
const accounts = config.accounts;
105+
this.apiUrl = config.apiUrl;
106+
this.repositoryFactory = new RepositoryFactoryHttp(this.apiUrl);
107+
this.transactionService = new TransactionService(
108+
this.repositoryFactory.createTransactionRepository(),
109+
this.repositoryFactory.createReceiptRepository(),
110+
);
111+
112+
this.networkType = await this.repositoryFactory.getNetworkType().toPromise();
113+
this.generationHash = await this.repositoryFactory.getGenerationHash().toPromise();
114+
115+
let index = 0;
116+
this.account = Account.createFromPrivateKey(accounts[index++], this.networkType);
117+
this.account2 = Account.createFromPrivateKey(accounts[index++], this.networkType);
118+
this.account3 = Account.createFromPrivateKey(accounts[index++], this.networkType);
119+
this.multisigAccount = Account.createFromPrivateKey(accounts[index++], this.networkType);
120+
this.cosignAccount1 = Account.createFromPrivateKey(accounts[index++], this.networkType);
121+
this.cosignAccount2 = Account.createFromPrivateKey(accounts[index++], this.networkType);
122+
this.cosignAccount3 = Account.createFromPrivateKey(accounts[index++], this.networkType);
123+
this.cosignAccount4 = Account.createFromPrivateKey(accounts[index++], this.networkType);
124+
this.harvestingAccount = Account.createFromPrivateKey(accounts[index++], this.networkType);
125+
126+
this.listener = this.repositoryFactory.createListener();
127+
128+
// What would be the best maxFee? In the future we will load the fee multiplier from rest.
129+
this.maxFee = UInt64.fromUint(1000000);
130+
this.networkCurrencyNamespaceId = this.apiUrl.toLowerCase().includes('localhost')
131+
? NetworkCurrencyLocal.NAMESPACE_ID
132+
: NetworkCurrencyPublic.NAMESPACE_ID;
133+
this.networkCurrencyDivisibility = this.apiUrl.toLowerCase().includes('localhost')
134+
? NetworkCurrencyLocal.DIVISIBILITY
135+
: NetworkCurrencyPublic.DIVISIBILITY;
136+
137+
if (openListener) {
138+
await this.listener.open();
139+
}
140+
return this;
130141
}
131142

132143
createNetworkCurrency(amount: number, isRelative = true): NetworkCurrencyPublic | NetworkCurrencyLocal {

e2e/infrastructure/Listener.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('Listener', () => {
4848
let transactionRepository: TransactionRepository;
4949

5050
before(() => {
51-
return helper.start().then(() => {
51+
return helper.start({ openListener: true }).then(() => {
5252
account = helper.account;
5353
account2 = helper.account2;
5454
multisigAccount = helper.multisigAccount;
@@ -60,12 +60,9 @@ describe('Listener', () => {
6060
transactionRepository = helper.repositoryFactory.createTransactionRepository();
6161
});
6262
});
63-
before(() => {
64-
return helper.listener.open();
65-
});
6663

6764
after(() => {
68-
helper.listener.close();
65+
return helper.close();
6966
});
7067
afterEach((done) => {
7168
// cold down

e2e/infrastructure/MetadataHttp.spec.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('MetadataHttp', () => {
4848
let metadataRepository: MetadataRepository;
4949

5050
before(() => {
51-
return helper.start().then(() => {
51+
return helper.start({ openListener: true }).then(() => {
5252
account = helper.account;
5353
accountAddress = helper.account.address;
5454
generationHash = helper.generationHash;
@@ -57,12 +57,8 @@ describe('MetadataHttp', () => {
5757
});
5858
});
5959

60-
before(() => {
61-
return helper.listener.open();
62-
});
63-
6460
after(() => {
65-
helper.listener.close();
61+
return helper.close();
6662
});
6763

6864
/**

e2e/infrastructure/MosaicHttp.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,17 @@ describe('MosaicHttp', () => {
4545
let networkType: NetworkType;
4646

4747
before(() => {
48-
return helper.start().then(() => {
48+
return helper.start({ openListener: true }).then(() => {
4949
account = helper.account;
5050
generationHash = helper.generationHash;
5151
networkType = helper.networkType;
5252
namespaceRepository = helper.repositoryFactory.createNamespaceRepository();
5353
mosaicRepository = helper.repositoryFactory.createMosaicRepository();
5454
});
5555
});
56-
before(() => {
57-
return helper.listener.open();
58-
});
5956

6057
after(() => {
61-
helper.listener.close();
58+
return helper.close();
6259
});
6360

6461
/**

0 commit comments

Comments
 (0)