thunderhub/server/helpers/__tests__/fileHelpers.test.ts
2020-11-28 12:40:12 +01:00

330 lines
8.6 KiB
TypeScript

import { existsSync, readFileSync } from 'fs';
import path from 'path';
import {
getParsedAccount,
hashPasswords,
getAccountsFromYaml,
AccountType,
} from '../fileHelpers';
const mockedExistsSync: jest.Mock = existsSync as any;
const mockedReadFileSync: jest.Mock = readFileSync as any;
jest.mock('fs');
describe('getParsedAccount', () => {
const masterPassword = 'master password';
it('returns null without an account name', () => {
const raw = {
lndDir: 'LND DIR',
name: '',
certificate: 'RAW CERT',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
};
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account).toBeNull();
});
it('returns null on invalid network', () => {
const raw = {
lndDir: 'LND DIR',
name: 'name',
certificate: 'RAW CERT',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
network: 'foo' as any,
};
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account).toBeNull();
});
it('returns null without an account server url', () => {
const raw = {
name: 'NAME',
certificate: 'RAW CERT',
serverUrl: '',
macaroon: 'RAW MACAROON',
};
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account).toBeNull();
});
it('defaults to given bitcoin network', () => {
const raw = {
name: 'NAME',
serverUrl: 'server.url',
lndDir: 'lnd dir',
};
mockedExistsSync.mockReturnValue(true);
mockedReadFileSync.mockImplementation(file => {
if ((file as string).includes('tls.cert')) {
return 'cert';
}
if ((file as string).includes(path.join('regtest', 'admin.macaroon'))) {
return 'macaroon';
}
return 'something else ';
});
const account = getParsedAccount(raw, 0, masterPassword, 'regtest');
expect(account?.macaroon).toContain('macaroon');
});
it('picks up other networks', () => {
const raw = {
name: 'NAME',
serverUrl: 'server.url',
lndDir: 'lnd dir',
network: 'testnet',
} as const;
mockedExistsSync.mockReturnValue(true);
mockedReadFileSync.mockImplementation(file => {
if ((file as string).includes('tls.cert')) {
return 'cert';
}
if ((file as string).includes(path.join('testnet', 'admin.macaroon'))) {
return 'macaroon';
}
return 'something else ';
});
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.macaroon).toContain('macaroon');
});
describe('macaroon handling', () => {
it('defaults to raw macaroon', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificate: 'RAW CERT',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
macaroonPath: 'MACAROON PATH',
};
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.macaroon).toBe('RAW MACAROON');
});
it('falls back to macaroon path after that', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificate: 'RAW CERT',
certificatePath: 'CERT PATH',
serverUrl: 'server.url',
macaroon: '',
macaroonPath: 'MACAROON PATH',
};
mockedExistsSync.mockReturnValueOnce(true);
mockedReadFileSync.mockImplementationOnce(file => {
if ((file as string).includes(raw.macaroonPath)) {
return 'yay';
} else {
return 'nay';
}
});
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.macaroon).toBe('yay');
});
it('falls back to lnd dir finally', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificate: 'RAW CERT',
certificatePath: 'CERT PATH',
serverUrl: 'server.url',
macaroon: '',
macaroonPath: '',
};
mockedExistsSync.mockReturnValueOnce(true);
mockedReadFileSync.mockImplementationOnce(file => {
if ((file as string).includes(raw.lndDir)) {
return 'yay';
} else {
return 'nay';
}
});
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.macaroon).toBe('yay');
});
});
describe('certificate handling', () => {
it('defaults to raw certificate', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificate: 'RAW CERT',
certificatePath: 'CERT PATH',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
};
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.cert).toBe('RAW CERT');
});
it('falls back to certificate path after that', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificatePath: 'CERT PATH',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
};
mockedExistsSync.mockReturnValueOnce(true);
mockedReadFileSync.mockImplementationOnce(file => {
if ((file as string).includes(raw.certificatePath)) {
return 'yay';
} else {
return 'nay';
}
});
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.cert).toBe('yay');
});
it('falls back to lnd dir finally', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
};
mockedExistsSync.mockReturnValueOnce(true);
mockedReadFileSync.mockImplementationOnce(file => {
if ((file as string).includes(raw.lndDir)) {
return 'yay';
} else {
return 'nay';
}
});
const account = getParsedAccount(raw, 0, masterPassword, 'mainnet');
expect(account?.cert).toBe('yay');
});
});
});
describe('encrypted accounts', () => {
it('returns correct props when encrypted', () => {
const raw: AccountType = {
name: 'NAME',
certificate: 'RAW CERT',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
encrypted: true,
};
const account = getParsedAccount(raw, 0, 'master password', 'mainnet');
expect(account?.encrypted).toBeTruthy();
expect(account?.macaroon).toBe(raw.macaroon);
expect((account as any)?.encryptedMacaroon).toBe(raw.macaroon);
});
it('returns correct props when not encrypted', () => {
const raw = {
lndDir: 'LND DIR',
name: 'NAME',
certificate: 'RAW CERT',
serverUrl: 'server.url',
macaroon: 'RAW MACAROON',
};
const account = getParsedAccount(raw, 0, 'master password', 'mainnet');
expect(account?.encrypted).toBeFalsy();
expect(account).not.toHaveProperty('encryptedMacaroon');
});
});
describe('hashPasswords', () => {
it('does not throw on missing master password', () => {
const config = {
hashed: false,
masterPassword: null,
defaultNetwork: null,
accounts: [],
};
expect(hashPasswords(false, config, 'file-path')).toEqual({
accounts: [],
defaultNetwork: null,
hashed: false,
masterPassword: null,
});
});
});
describe('getAccountsFromYaml', () => {
it('needs either account password or master password', () => {
const conf = {
hashed: false,
masterPassword: 'masterPassword',
defaultNetwork: null,
accounts: [
{
name: 'first account',
serverUrl: 'server.url',
password: 'accountPassword',
certificate: 'cert',
macaroon: 'macaroon',
},
],
};
// no password and no account password
expect(
getAccountsFromYaml(
{
...conf,
masterPassword: null,
accounts: [
{
...conf.accounts[0],
password: null,
},
],
},
'file-path'
)
).toHaveLength(0);
// just master password
expect(
getAccountsFromYaml(
{
...conf,
accounts: [
{
...conf.accounts[0],
password: null,
},
],
},
'file-path'
)
).toHaveLength(1);
// just account password
expect(
getAccountsFromYaml(
{
...conf,
masterPassword: null,
accounts: [
{
...conf.accounts[0],
password: 'accountPassword',
},
],
},
'file-path'
)
).toHaveLength(1);
});
});