node-btcpay/tests/core/client.spec.ts
2021-05-11 15:03:09 +00:00

183 lines
5.4 KiB
TypeScript

import * as elliptic from 'elliptic';
import * as puppeteer from 'puppeteer';
import { Browser, Page } from 'puppeteer';
import { BTCPayClient } from '../../src/core/client';
import { Cryptography as myCrypto } from '../../src/core/cryptography';
const IGNORE_SANDBOX_ERROR = process.env['BTCPAY_IGNORE_SANDBOX_ERROR'];
const USER_NAME = 'test@example.com';
const PASSWORD = 'satoshinakamoto';
const URL = 'http://127.0.0.1:49392';
const MY_PRIVATE_KEY = Buffer.from(
'31eb31ecf1a640c9d1e0a1105501f36235f8c7d51d67dcf74ccc968d74cb6b25',
'hex',
);
let STORE_ID = '';
const WINDOW_WIDTH = 1920;
const WINDOW_HEIGHT = 1080;
let INVOICE_ID = '';
const HEADLESS = true;
const loginAndGetPairingCode = async (): Promise<{
browser: Browser;
page: Page;
pairingCode: string;
}> => {
const newTokenName = 'autotest ' + new Date().getTime();
const browser = await puppeteer
.launch({
headless: HEADLESS,
args: ['--window-size=' + WINDOW_WIDTH + ',' + WINDOW_HEIGHT],
})
.then(
(v) => v, // if success, passthrough
// if error, check for env and ignore sandbox and warn.
(err) => {
if (IGNORE_SANDBOX_ERROR === '1') {
console.warn(
'WARNING!!! Error occurred, Chromium will be started ' +
"without sandbox. This won't guarantee success.",
);
return puppeteer.launch({
headless: HEADLESS,
ignoreDefaultArgs: ['--disable-extensions'],
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--window-size=' + WINDOW_WIDTH + ',' + WINDOW_HEIGHT,
],
});
} else {
console.warn(
'If "No usable sandbox!" error, retry test with ' +
'BTCPAY_IGNORE_SANDBOX_ERROR=1',
);
throw err;
}
},
);
const page = (await browser.pages())[0];
await page.setViewport({ width: WINDOW_WIDTH, height: WINDOW_HEIGHT });
try {
await page.goto(URL + '/Account/Login');
} catch (e) {
if (e.message === `net::ERR_CONNECTION_REFUSED at ${URL}/Account/Login`) {
browser.close();
console.log(
'Please start docker container locally:\n' +
'docker run -p 127.0.0.1:49392:49392 junderw/btcpay-client-test-server',
);
return {
page,
browser,
pairingCode: '',
};
}
throw e;
}
await page.click('#LoginButton');
await page.goto(URL + '/stores');
await page.waitForSelector('#CreateStore');
await page.click(
'table.table.table-sm.table-responsive-md > tbody > ' +
'tr:nth-of-type(1) > td:nth-of-type(3) > a:nth-of-type(2)',
);
await page.waitForSelector('#Id');
const idElement = await page.$$('#Id');
STORE_ID = (await idElement[0]
.getProperty('value')
.then((v) => v?.jsonValue())) as string;
await page.goto(URL + '/stores/' + STORE_ID + '/Tokens/Create');
await page.waitForSelector('input#Label');
await page.waitForSelector('[type="submit"]');
await page.type('#Label', newTokenName);
await page.click('[type="submit"]');
await page.waitForSelector('button[type="submit"]');
await page.click('[type="submit"]');
await page.waitForSelector('div.alert.alert-success.alert-dismissible');
const contents = await page.evaluate(() => {
const el = document.querySelector(
'div.alert.alert-success.alert-dismissible',
);
if (el === null) {
return '';
}
return el.innerHTML;
});
const pairingCode = (contents.match(
/Server initiated pairing code: (\S{7})/,
) || [])[1];
if (!pairingCode) {
throw new Error('Could not get pairing code');
}
return {
browser,
page,
pairingCode,
};
};
let MY_KEYPAIR: elliptic.ec.KeyPair;
let client: BTCPayClient;
describe('btcpay.core.client', () => {
beforeAll(async () => {
jest.setTimeout(20000); // browser takes a while
MY_KEYPAIR = myCrypto.load_keypair(MY_PRIVATE_KEY);
client = new BTCPayClient(URL, MY_KEYPAIR);
});
it('should pair with server', async () => {
const pairingData = await loginAndGetPairingCode();
const myClient = new BTCPayClient(URL, MY_KEYPAIR);
const result = await myClient.pair_client(pairingData.pairingCode);
client = new BTCPayClient(URL, MY_KEYPAIR, result);
expect(result.merchant).toBeDefined();
pairingData.browser.close();
await expect(myClient.pair_client('hduheufhfuf')).rejects.toThrow(
/^pairing code is not valid$/,
);
});
it('should get rates', async () => {
const results = await client.get_rates(['LTC_USD', 'BTC_USD'], STORE_ID);
expect(results[0].rate).toBeDefined();
});
it('should create an invoice', async () => {
const results = await client.create_invoice({
currency: 'USD',
price: 1.12,
});
INVOICE_ID = results.id;
expect(results.bitcoinAddress).toBeDefined();
await expect(
client.create_invoice({
currency: 'KDFAHKJFKJ',
price: 1.12,
}),
).rejects.toThrow(/^Currency is invalid$/);
await expect(
client.create_invoice({
currency: 'USD',
// @ts-ignore
price: 'xkhdfhu',
}),
).rejects.toThrow(/^Price must be a float$/);
});
it('should get invoice', async () => {
const results = await client.get_invoice(INVOICE_ID);
expect(results.id).toBe(INVOICE_ID);
});
it('should get multiple invoices', async () => {
const results = await client.get_invoices();
expect(results[0].bitcoinAddress).toBeDefined();
});
});