integration tests: various fixes
This commit is contained in:
parent
499e003ff8
commit
70d0199572
@ -22,8 +22,8 @@ import { CoinConfig, defaultCoinConfig } from "./harness/denomStructures.js";
|
|||||||
import {
|
import {
|
||||||
GlobalTestState,
|
GlobalTestState,
|
||||||
setupDb,
|
setupDb,
|
||||||
FakeBankService,
|
|
||||||
ExchangeService,
|
ExchangeService,
|
||||||
|
FakebankService,
|
||||||
} from "./harness/harness.js";
|
} from "./harness/harness.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,9 +35,11 @@ import {
|
|||||||
export async function runEnv1(t: GlobalTestState): Promise<void> {
|
export async function runEnv1(t: GlobalTestState): Promise<void> {
|
||||||
const db = await setupDb(t);
|
const db = await setupDb(t);
|
||||||
|
|
||||||
const bank = await FakeBankService.create(t, {
|
const bank = await FakebankService.create(t, {
|
||||||
currency: "TESTKUDOS",
|
currency: "TESTKUDOS",
|
||||||
httpPort: 8082,
|
httpPort: 8082,
|
||||||
|
allowRegistrations: true,
|
||||||
|
database: db.connStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exchange = ExchangeService.create(t, {
|
const exchange = ExchangeService.create(t, {
|
||||||
|
@ -775,11 +775,21 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
/**
|
/**
|
||||||
* Implementation of the bank service using the "taler-fakebank-run" tool.
|
* Implementation of the bank service using the "taler-fakebank-run" tool.
|
||||||
*/
|
*/
|
||||||
class FakebankService extends BankServiceBase implements BankServiceHandle {
|
export class FakebankService
|
||||||
|
extends BankServiceBase
|
||||||
|
implements BankServiceHandle
|
||||||
|
{
|
||||||
proc: ProcessWrapper | undefined;
|
proc: ProcessWrapper | undefined;
|
||||||
|
|
||||||
http = new NodeHttpLib();
|
http = new NodeHttpLib();
|
||||||
|
|
||||||
|
// We store "created" accounts during setup and
|
||||||
|
// register them after startup.
|
||||||
|
private accounts: {
|
||||||
|
accountName: string;
|
||||||
|
accountPassword: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
static async create(
|
static async create(
|
||||||
gc: GlobalTestState,
|
gc: GlobalTestState,
|
||||||
bc: BankConfig,
|
bc: BankConfig,
|
||||||
@ -791,6 +801,7 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
config.setString("bank", "serve", "http");
|
config.setString("bank", "serve", "http");
|
||||||
config.setString("bank", "max_debt_bank", `${bc.currency}:999999`);
|
config.setString("bank", "max_debt_bank", `${bc.currency}:999999`);
|
||||||
config.setString("bank", "max_debt", bc.maxDebt ?? `${bc.currency}:100`);
|
config.setString("bank", "max_debt", bc.maxDebt ?? `${bc.currency}:100`);
|
||||||
|
config.setString("bank", "ram_limit", `${1024}`);
|
||||||
const cfgFilename = gc.testDir + "/bank.conf";
|
const cfgFilename = gc.testDir + "/bank.conf";
|
||||||
config.write(cfgFilename);
|
config.write(cfgFilename);
|
||||||
|
|
||||||
@ -798,6 +809,9 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSuggestedExchange(e: ExchangeServiceInterface, exchangePayto: string) {
|
setSuggestedExchange(e: ExchangeServiceInterface, exchangePayto: string) {
|
||||||
|
if (!!this.proc) {
|
||||||
|
throw Error("Can't set suggested exchange while bank is running.");
|
||||||
|
}
|
||||||
const config = Configuration.load(this.configFile);
|
const config = Configuration.load(this.configFile);
|
||||||
config.setString("bank", "suggested_exchange", e.baseUrl);
|
config.setString("bank", "suggested_exchange", e.baseUrl);
|
||||||
config.write(this.configFile);
|
config.write(this.configFile);
|
||||||
@ -816,10 +830,10 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
accountName: string,
|
accountName: string,
|
||||||
password: string,
|
password: string,
|
||||||
): Promise<HarnessExchangeBankAccount> {
|
): Promise<HarnessExchangeBankAccount> {
|
||||||
// FIXME: Is there a better place to do this initialization?
|
this.accounts.push({
|
||||||
await this.start();
|
accountName,
|
||||||
await this.pingUntilAvailable();
|
accountPassword: password,
|
||||||
await BankApi.registerAccount(this, accountName, password);
|
});
|
||||||
return {
|
return {
|
||||||
accountName: accountName,
|
accountName: accountName,
|
||||||
accountPassword: password,
|
accountPassword: password,
|
||||||
@ -833,15 +847,25 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
|
logger.info("starting fakebank");
|
||||||
if (this.proc) {
|
if (this.proc) {
|
||||||
logger.info("fakebank already running, not starting again");
|
logger.info("fakebank already running, not starting again");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.proc = this.globalTestState.spawnService(
|
this.proc = this.globalTestState.spawnService(
|
||||||
"taler-fakebank-run",
|
"taler-fakebank-run",
|
||||||
["-c", this.configFile],
|
[
|
||||||
|
"-c",
|
||||||
|
this.configFile,
|
||||||
|
"--signup-bonus",
|
||||||
|
`${this.bankConfig.currency}:100`,
|
||||||
|
],
|
||||||
"bank",
|
"bank",
|
||||||
);
|
);
|
||||||
|
await this.pingUntilAvailable();
|
||||||
|
for (const acc of this.accounts) {
|
||||||
|
await BankApi.registerAccount(this, acc.accountName, acc.accountPassword);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async pingUntilAvailable(): Promise<void> {
|
async pingUntilAvailable(): Promise<void> {
|
||||||
@ -853,86 +877,8 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
|
|||||||
// Use libeufin bank instead of pybank.
|
// Use libeufin bank instead of pybank.
|
||||||
const useLibeufinBank = false;
|
const useLibeufinBank = false;
|
||||||
|
|
||||||
/**
|
export type BankService = BankServiceHandle;
|
||||||
* Return a euFin or a pyBank implementation of
|
export const BankService = FakebankService;
|
||||||
* the exported BankService class. This allows
|
|
||||||
* to "dynamically export" such class depending
|
|
||||||
* on a particular env variable.
|
|
||||||
*/
|
|
||||||
function getBankServiceImpl(): {
|
|
||||||
prototype: typeof FakebankService.prototype;
|
|
||||||
create: typeof FakebankService.create;
|
|
||||||
} {
|
|
||||||
if (useLibeufinBank)
|
|
||||||
return {
|
|
||||||
prototype: LibEuFinBankService.prototype,
|
|
||||||
create: LibEuFinBankService.create,
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
prototype: FakebankService.prototype,
|
|
||||||
create: FakebankService.create,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BankService = FakebankService;
|
|
||||||
export const BankService = getBankServiceImpl();
|
|
||||||
|
|
||||||
export class FakeBankService {
|
|
||||||
proc: ProcessWrapper | undefined;
|
|
||||||
|
|
||||||
static fromExistingConfig(gc: GlobalTestState): FakeBankService {
|
|
||||||
const cfgFilename = gc.testDir + "/bank.conf";
|
|
||||||
logger.info("reading fakebank config from", cfgFilename);
|
|
||||||
const config = Configuration.load(cfgFilename);
|
|
||||||
const bc: FakeBankConfig = {
|
|
||||||
currency: config.getString("taler", "currency").required(),
|
|
||||||
httpPort: config.getNumber("bank", "http_port").required(),
|
|
||||||
};
|
|
||||||
return new FakeBankService(gc, bc, cfgFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(
|
|
||||||
gc: GlobalTestState,
|
|
||||||
bc: FakeBankConfig,
|
|
||||||
): Promise<FakeBankService> {
|
|
||||||
const config = new Configuration();
|
|
||||||
setTalerPaths(config, gc.testDir + "/talerhome");
|
|
||||||
config.setString("taler", "currency", bc.currency);
|
|
||||||
config.setString("bank", "http_port", `${bc.httpPort}`);
|
|
||||||
config.setString("bank", "ram_limit", `${1024}`);
|
|
||||||
const cfgFilename = gc.testDir + "/bank.conf";
|
|
||||||
config.write(cfgFilename);
|
|
||||||
return new FakeBankService(gc, bc, cfgFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
get baseUrl(): string {
|
|
||||||
return `http://localhost:${this.bankConfig.httpPort}/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get port() {
|
|
||||||
return this.bankConfig.httpPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
private constructor(
|
|
||||||
private globalTestState: GlobalTestState,
|
|
||||||
private bankConfig: FakeBankConfig,
|
|
||||||
private configFile: string,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async start(): Promise<void> {
|
|
||||||
this.proc = this.globalTestState.spawnService(
|
|
||||||
"taler-fakebank-run",
|
|
||||||
["-c", this.configFile],
|
|
||||||
"fakebank",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async pingUntilAvailable(): Promise<void> {
|
|
||||||
// Fakebank doesn't have "/config", so we ping just "/".
|
|
||||||
const url = `http://localhost:${this.bankConfig.httpPort}/`;
|
|
||||||
await pingProc(this.proc, url, "bank");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExchangeConfig {
|
export interface ExchangeConfig {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -691,8 +691,8 @@ export class LibeufinCli {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const stdout = await sh(
|
const stdout = await sh(
|
||||||
this.globalTestState,
|
this.globalTestState,
|
||||||
"libeufin-cli-submitpayment",
|
"libeufin-cli-submitpayments",
|
||||||
`libeufin-cli accounts submit-payment` +
|
`libeufin-cli accounts submit-payments` +
|
||||||
` --payment-uuid=${paymentUuid}` +
|
` --payment-uuid=${paymentUuid}` +
|
||||||
` ${details.nexusBankAccountName}`,
|
` ${details.nexusBankAccountName}`,
|
||||||
{
|
{
|
||||||
|
@ -43,10 +43,10 @@ export async function runBankApiTest(t: GlobalTestState) {
|
|||||||
const db = await setupDb(t);
|
const db = await setupDb(t);
|
||||||
|
|
||||||
const bank = await BankService.create(t, {
|
const bank = await BankService.create(t, {
|
||||||
allowRegistrations: true,
|
|
||||||
currency: "TESTKUDOS",
|
currency: "TESTKUDOS",
|
||||||
database: db.connStr,
|
|
||||||
httpPort: 8082,
|
httpPort: 8082,
|
||||||
|
database: db.connStr,
|
||||||
|
allowRegistrations: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exchange = ExchangeService.create(t, {
|
const exchange = ExchangeService.create(t, {
|
||||||
|
@ -17,17 +17,9 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import {
|
import { j2s } from "@gnu-taler/taler-util";
|
||||||
ConfirmPayResultType,
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
j2s,
|
import { GlobalTestState } from "../harness/harness.js";
|
||||||
PreparePayResultType,
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { Wallet, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
|
||||||
import {
|
|
||||||
GlobalTestState,
|
|
||||||
MerchantPrivateApi,
|
|
||||||
WithAuthorization,
|
|
||||||
} from "../harness/harness.js";
|
|
||||||
import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
|
import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +54,7 @@ export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
|
|||||||
// Abort it
|
// Abort it
|
||||||
|
|
||||||
await BankApi.abortWithdrawalOperation(bank, user, wop);
|
await BankApi.abortWithdrawalOperation(bank, user, wop);
|
||||||
|
//await BankApi.confirmWithdrawalOperation(bank, user, wop);
|
||||||
|
|
||||||
// Withdraw
|
// Withdraw
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
WalletCli,
|
WalletCli,
|
||||||
setupDb,
|
setupDb,
|
||||||
ExchangeService,
|
ExchangeService,
|
||||||
FakeBankService,
|
FakebankService,
|
||||||
} from "../harness/harness.js";
|
} from "../harness/harness.js";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
|
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
|
||||||
@ -36,9 +36,12 @@ export async function runWithdrawalFakebankTest(t: GlobalTestState) {
|
|||||||
|
|
||||||
const db = await setupDb(t);
|
const db = await setupDb(t);
|
||||||
|
|
||||||
const bank = await FakeBankService.create(t, {
|
const bank = await FakebankService.create(t, {
|
||||||
currency: "TESTKUDOS",
|
currency: "TESTKUDOS",
|
||||||
httpPort: 8082,
|
httpPort: 8082,
|
||||||
|
allowRegistrations: true,
|
||||||
|
// Not used by fakebank
|
||||||
|
database: db.connStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exchange = ExchangeService.create(t, {
|
const exchange = ExchangeService.create(t, {
|
||||||
|
@ -106,7 +106,7 @@ export namespace BankApi {
|
|||||||
const url = new URL("testing/register", bank.bankAccessApiBaseUrl);
|
const url = new URL("testing/register", bank.bankAccessApiBaseUrl);
|
||||||
const resp = await bank.http.postJson(url.href, { username, password });
|
const resp = await bank.http.postJson(url.href, { username, password });
|
||||||
let paytoUri = `payto://x-taler-bank/localhost/${username}`;
|
let paytoUri = `payto://x-taler-bank/localhost/${username}`;
|
||||||
if (resp.status !== 200 && resp.status !== 202) {
|
if (resp.status !== 200 && resp.status !== 202 && resp.status !== 204) {
|
||||||
logger.error(`${j2s(await resp.json())}`);
|
logger.error(`${j2s(await resp.json())}`);
|
||||||
throw TalerError.fromDetail(
|
throw TalerError.fromDetail(
|
||||||
TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
|
TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
|
||||||
@ -209,7 +209,7 @@ export namespace BankApi {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
`accounts/${bankUser.username}/withdrawals/${wopi.withdrawal_id}/abort`,
|
`accounts/${bankUser.username}/withdrawals/${wopi.withdrawal_id}/abort`,
|
||||||
bank.baseUrl,
|
bank.bankAccessApiBaseUrl,
|
||||||
);
|
);
|
||||||
const resp = await bank.http.postJson(
|
const resp = await bank.http.postJson(
|
||||||
url.href,
|
url.href,
|
||||||
|
@ -90,16 +90,21 @@ export async function withdrawTestBalance(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
req: WithdrawTestBalanceRequest,
|
req: WithdrawTestBalanceRequest,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const bankBaseUrl = req.bankBaseUrl;
|
|
||||||
const amount = req.amount;
|
const amount = req.amount;
|
||||||
const exchangeBaseUrl = req.exchangeBaseUrl;
|
const exchangeBaseUrl = req.exchangeBaseUrl;
|
||||||
|
|
||||||
const bankUser = await registerRandomBankUser(ws.http, bankBaseUrl);
|
logger.trace(
|
||||||
|
`Registered bank user, bank access base url ${req.bankAccessApiBaseUrl}`,
|
||||||
|
);
|
||||||
|
const bankUser = await registerRandomBankUser(
|
||||||
|
ws.http,
|
||||||
|
req.bankAccessApiBaseUrl,
|
||||||
|
);
|
||||||
logger.trace(`Registered bank user ${JSON.stringify(bankUser)}`);
|
logger.trace(`Registered bank user ${JSON.stringify(bankUser)}`);
|
||||||
|
|
||||||
const wresp = await createDemoBankWithdrawalUri(
|
const wresp = await createDemoBankWithdrawalUri(
|
||||||
ws.http,
|
ws.http,
|
||||||
bankBaseUrl,
|
req.bankAccessApiBaseUrl,
|
||||||
bankUser,
|
bankUser,
|
||||||
amount,
|
amount,
|
||||||
);
|
);
|
||||||
@ -112,7 +117,7 @@ export async function withdrawTestBalance(
|
|||||||
|
|
||||||
await confirmBankWithdrawalUri(
|
await confirmBankWithdrawalUri(
|
||||||
ws.http,
|
ws.http,
|
||||||
bankBaseUrl,
|
req.bankAccessApiBaseUrl,
|
||||||
bankUser,
|
bankUser,
|
||||||
wresp.withdrawal_id,
|
wresp.withdrawal_id,
|
||||||
);
|
);
|
||||||
@ -133,13 +138,13 @@ function getMerchantAuthHeader(m: MerchantBackendInfo): Record<string, string> {
|
|||||||
*/
|
*/
|
||||||
export async function createDemoBankWithdrawalUri(
|
export async function createDemoBankWithdrawalUri(
|
||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
bankBaseUrl: string,
|
bankAccessApiBaseUrl: string,
|
||||||
bankUser: BankUser,
|
bankUser: BankUser,
|
||||||
amount: AmountString,
|
amount: AmountString,
|
||||||
): Promise<BankWithdrawalResponse> {
|
): Promise<BankWithdrawalResponse> {
|
||||||
const reqUrl = new URL(
|
const reqUrl = new URL(
|
||||||
`accounts/${bankUser.username}/withdrawals`,
|
`accounts/${bankUser.username}/withdrawals`,
|
||||||
bankBaseUrl,
|
bankAccessApiBaseUrl,
|
||||||
).href;
|
).href;
|
||||||
const resp = await http.postJson(
|
const resp = await http.postJson(
|
||||||
reqUrl,
|
reqUrl,
|
||||||
@ -161,13 +166,13 @@ export async function createDemoBankWithdrawalUri(
|
|||||||
|
|
||||||
async function confirmBankWithdrawalUri(
|
async function confirmBankWithdrawalUri(
|
||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
bankBaseUrl: string,
|
bankAccessApiBaseUrl: string,
|
||||||
bankUser: BankUser,
|
bankUser: BankUser,
|
||||||
withdrawalId: string,
|
withdrawalId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reqUrl = new URL(
|
const reqUrl = new URL(
|
||||||
`accounts/${bankUser.username}/withdrawals/${withdrawalId}/confirm`,
|
`accounts/${bankUser.username}/withdrawals/${withdrawalId}/confirm`,
|
||||||
bankBaseUrl,
|
bankAccessApiBaseUrl,
|
||||||
).href;
|
).href;
|
||||||
const resp = await http.postJson(
|
const resp = await http.postJson(
|
||||||
reqUrl,
|
reqUrl,
|
||||||
@ -187,9 +192,9 @@ async function confirmBankWithdrawalUri(
|
|||||||
|
|
||||||
async function registerRandomBankUser(
|
async function registerRandomBankUser(
|
||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
bankBaseUrl: string,
|
bankAccessApiBaseUrl: string,
|
||||||
): Promise<BankUser> {
|
): Promise<BankUser> {
|
||||||
const reqUrl = new URL("testing/register", bankBaseUrl).href;
|
const reqUrl = new URL("testing/register", bankAccessApiBaseUrl).href;
|
||||||
const randId = makeId(8);
|
const randId = makeId(8);
|
||||||
const bankUser: BankUser = {
|
const bankUser: BankUser = {
|
||||||
// euFin doesn't allow resource names to have upper case letters.
|
// euFin doesn't allow resource names to have upper case letters.
|
||||||
@ -377,7 +382,7 @@ export async function runIntegrationTest(
|
|||||||
await withdrawTestBalance(ws, {
|
await withdrawTestBalance(ws, {
|
||||||
amount: Amounts.stringify(withdrawAmountTwo),
|
amount: Amounts.stringify(withdrawAmountTwo),
|
||||||
bankBaseUrl: args.bankBaseUrl,
|
bankBaseUrl: args.bankBaseUrl,
|
||||||
bankAccessApiBaseUrl: args.bankBaseUrl,
|
bankAccessApiBaseUrl: args.bankAccessApiBaseUrl,
|
||||||
exchangeBaseUrl: args.exchangeBaseUrl,
|
exchangeBaseUrl: args.exchangeBaseUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -376,6 +376,9 @@ export async function getBankWithdrawalInfo(
|
|||||||
`withdrawal-operation/${uriResult.withdrawalOperationId}`,
|
`withdrawal-operation/${uriResult.withdrawalOperationId}`,
|
||||||
uriResult.bankIntegrationApiBaseUrl,
|
uriResult.bankIntegrationApiBaseUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logger.info(`bank withdrawal status URL: ${reqUrl.href}}`);
|
||||||
|
|
||||||
const resp = await http.get(reqUrl.href);
|
const resp = await http.get(reqUrl.href);
|
||||||
const status = await readSuccessResponseJsonOrThrow(
|
const status = await readSuccessResponseJsonOrThrow(
|
||||||
resp,
|
resp,
|
||||||
|
Loading…
Reference in New Issue
Block a user