test: 🚨 more server unit tests (#70)

* chore: πŸ”§ add tests

* fix: πŸ› network info resolver

* feat: ✨ init tests

* chore: πŸ”§ improve test

* chore: πŸ”§ more tests

* chore: πŸ”§ bitcoin resolvers

* chore: πŸ”§ more tests
This commit is contained in:
Anthony Potdevin 2020-06-13 11:46:20 +02:00 β€’ committed by GitHub
parent 25e4fef720
commit a78b6e96d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1051 additions and 64 deletions

View file

@ -16,4 +16,5 @@ module.exports = {
moduleNameMapper: {
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
},
modulePaths: ['<rootDir>/'],
};

315
package-lock.json generated
View file

@ -4630,6 +4630,15 @@
"@types/node": "*"
}
},
"@types/cors": {
"version": "2.8.6",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
"integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@ -5636,6 +5645,88 @@
"tslib": "^1.9.3"
}
},
"apollo-server": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server/-/apollo-server-2.14.4.tgz",
"integrity": "sha512-5RRs/UnzZMK+QGqCE8Wyfy5vNBFPmweFlkMRs966pM+6orN/g2GxxypKRsGa2rit2Wz0wki8vw+MjI80t2lPvg==",
"dev": true,
"requires": {
"apollo-server-core": "^2.14.4",
"apollo-server-express": "^2.14.4",
"express": "^4.0.0",
"graphql-subscriptions": "^1.0.0",
"graphql-tools": "^4.0.0"
},
"dependencies": {
"@apollographql/graphql-playground-html": {
"version": "1.6.26",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
"integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
"dev": true,
"requires": {
"xss": "^1.0.6"
}
},
"apollo-engine-reporting": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.0.1.tgz",
"integrity": "sha512-3OYYk7DqNuJ5xKYnyLy5O2n506jYSryim8WqzBTn9MRphRamwPFjHYQm+akPA60AubXrWnYa6A8euMAiQU0ttA==",
"dev": true,
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-graphql": "^0.4.0",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"async-retry": "^1.2.1",
"uuid": "^8.0.0"
}
},
"apollo-server-core": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.14.4.tgz",
"integrity": "sha512-aAfsvbJ2YrqAXDBgcBQocOmQJ5DkeOnEYQ6ADdkkDNU68V5yBRkAHLTOzPfbUlGHVrnOH8PT1FIVWwu5mBgkVA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/graphql-upload": "^8.0.0",
"@types/ws": "^7.0.0",
"apollo-cache-control": "^0.11.0",
"apollo-datasource": "^0.7.1",
"apollo-engine-reporting": "^2.0.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"apollo-tracing": "^0.11.0",
"fast-json-stable-stringify": "^2.0.0",
"graphql-extensions": "^0.12.3",
"graphql-tag": "^2.9.2",
"graphql-tools": "^4.0.0",
"graphql-upload": "^8.0.2",
"loglevel": "^1.6.7",
"sha.js": "^2.4.11",
"subscriptions-transport-ws": "^0.9.11",
"ws": "^6.0.0"
}
},
"graphql-extensions": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.3.tgz",
"integrity": "sha512-W7iT0kzlwTiZU7fXfw9IgWnsqVj7EFLd0/wVcZZRAbR8L3f4+YsGls0oxKdsrvYBnbG347BXKQmIyo6GTEk4XA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"apollo-server-env": "^2.4.4",
"apollo-server-types": "^0.5.0"
}
}
}
},
"apollo-server-caching": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.1.tgz",
@ -5687,6 +5778,111 @@
"resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.1.tgz",
"integrity": "sha512-7oEd6pUxqyWYUbQ9TA8tM0NU/3aGtXSEibo6+txUkuHe7QaxfZ2wHRp+pfT1LC1K3RXYjKj61/C2xEO19s3Kdg=="
},
"apollo-server-express": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.14.4.tgz",
"integrity": "sha512-g0ml0NGmghvJhTiXMR0HqDD8eTz77zdgzDG2XoqNoRehtVIsZq8fmKTagVt9cUKCKKiBPUF+4tqAGD9lnprUdw==",
"dev": true,
"requires": {
"@apollographql/graphql-playground-html": "1.6.26",
"@types/accepts": "^1.3.5",
"@types/body-parser": "1.19.0",
"@types/cors": "^2.8.4",
"@types/express": "4.17.4",
"accepts": "^1.3.5",
"apollo-server-core": "^2.14.4",
"apollo-server-types": "^0.5.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.17.1",
"graphql-subscriptions": "^1.0.0",
"graphql-tools": "^4.0.0",
"parseurl": "^1.3.2",
"subscriptions-transport-ws": "^0.9.16",
"type-is": "^1.6.16"
},
"dependencies": {
"@apollographql/graphql-playground-html": {
"version": "1.6.26",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
"integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
"dev": true,
"requires": {
"xss": "^1.0.6"
}
},
"@types/express": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.4.tgz",
"integrity": "sha512-DO1L53rGqIDUEvOjJKmbMEQ5Z+BM2cIEPy/eV3En+s166Gz+FeuzRerxcab757u/U4v4XF4RYrZPmqKa+aY/2w==",
"dev": true,
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"apollo-engine-reporting": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.0.1.tgz",
"integrity": "sha512-3OYYk7DqNuJ5xKYnyLy5O2n506jYSryim8WqzBTn9MRphRamwPFjHYQm+akPA60AubXrWnYa6A8euMAiQU0ttA==",
"dev": true,
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-graphql": "^0.4.0",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"async-retry": "^1.2.1",
"uuid": "^8.0.0"
}
},
"apollo-server-core": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.14.4.tgz",
"integrity": "sha512-aAfsvbJ2YrqAXDBgcBQocOmQJ5DkeOnEYQ6ADdkkDNU68V5yBRkAHLTOzPfbUlGHVrnOH8PT1FIVWwu5mBgkVA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/graphql-upload": "^8.0.0",
"@types/ws": "^7.0.0",
"apollo-cache-control": "^0.11.0",
"apollo-datasource": "^0.7.1",
"apollo-engine-reporting": "^2.0.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"apollo-tracing": "^0.11.0",
"fast-json-stable-stringify": "^2.0.0",
"graphql-extensions": "^0.12.3",
"graphql-tag": "^2.9.2",
"graphql-tools": "^4.0.0",
"graphql-upload": "^8.0.2",
"loglevel": "^1.6.7",
"sha.js": "^2.4.11",
"subscriptions-transport-ws": "^0.9.11",
"ws": "^6.0.0"
}
},
"graphql-extensions": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.3.tgz",
"integrity": "sha512-W7iT0kzlwTiZU7fXfw9IgWnsqVj7EFLd0/wVcZZRAbR8L3f4+YsGls0oxKdsrvYBnbG347BXKQmIyo6GTEk4XA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"apollo-server-env": "^2.4.4",
"apollo-server-types": "^0.5.0"
}
}
}
},
"apollo-server-micro": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/apollo-server-micro/-/apollo-server-micro-2.14.2.tgz",
@ -5707,6 +5903,84 @@
"apollo-server-types": "^0.5.0"
}
},
"apollo-server-testing": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-testing/-/apollo-server-testing-2.14.4.tgz",
"integrity": "sha512-4yaqj0eMpic9DhYsEG+lyAdLwRPacnU50DsBWlG6ckqhDlcIxCsJ+5zeDxUZRUeOorlDwxXOtHwRaTlPs0sj8g==",
"dev": true,
"requires": {
"apollo-server-core": "^2.14.4"
},
"dependencies": {
"@apollographql/graphql-playground-html": {
"version": "1.6.26",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
"integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
"dev": true,
"requires": {
"xss": "^1.0.6"
}
},
"apollo-engine-reporting": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.0.1.tgz",
"integrity": "sha512-3OYYk7DqNuJ5xKYnyLy5O2n506jYSryim8WqzBTn9MRphRamwPFjHYQm+akPA60AubXrWnYa6A8euMAiQU0ttA==",
"dev": true,
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-graphql": "^0.4.0",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"async-retry": "^1.2.1",
"uuid": "^8.0.0"
}
},
"apollo-server-core": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.14.4.tgz",
"integrity": "sha512-aAfsvbJ2YrqAXDBgcBQocOmQJ5DkeOnEYQ6ADdkkDNU68V5yBRkAHLTOzPfbUlGHVrnOH8PT1FIVWwu5mBgkVA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/graphql-upload": "^8.0.0",
"@types/ws": "^7.0.0",
"apollo-cache-control": "^0.11.0",
"apollo-datasource": "^0.7.1",
"apollo-engine-reporting": "^2.0.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"apollo-tracing": "^0.11.0",
"fast-json-stable-stringify": "^2.0.0",
"graphql-extensions": "^0.12.3",
"graphql-tag": "^2.9.2",
"graphql-tools": "^4.0.0",
"graphql-upload": "^8.0.2",
"loglevel": "^1.6.7",
"sha.js": "^2.4.11",
"subscriptions-transport-ws": "^0.9.11",
"ws": "^6.0.0"
}
},
"graphql-extensions": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.3.tgz",
"integrity": "sha512-W7iT0kzlwTiZU7fXfw9IgWnsqVj7EFLd0/wVcZZRAbR8L3f4+YsGls0oxKdsrvYBnbG347BXKQmIyo6GTEk4XA==",
"dev": true,
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"apollo-server-env": "^2.4.4",
"apollo-server-types": "^0.5.0"
}
}
}
},
"apollo-server-types": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.0.tgz",
@ -9205,6 +9479,12 @@
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
},
"cssfilter": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
"integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=",
"dev": true
},
"cssnano": {
"version": "4.1.10",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz",
@ -12537,6 +12817,15 @@
"yup": "^0.27.0"
}
},
"graphql-subscriptions": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.1.0.tgz",
"integrity": "sha512-6WzlBFC0lWmXJbIVE8OgFgXIP4RJi3OQgTPa0DVMsDXdpRDjTsM1K9wfl5HSYX7R87QAGlvcv2Y4BIZa/ItonA==",
"dev": true,
"requires": {
"iterall": "^1.2.1"
}
},
"graphql-tag": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.3.tgz",
@ -14637,6 +14926,16 @@
}
}
},
"jest-fetch-mock": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz",
"integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==",
"dev": true,
"requires": {
"cross-fetch": "^3.0.4",
"promise-polyfill": "^8.1.3"
}
},
"jest-get-type": {
"version": "25.2.6",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz",
@ -19999,6 +20298,12 @@
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
},
"promise-polyfill": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
"integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==",
"dev": true
},
"prompts": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz",
@ -24407,6 +24712,16 @@
"@babel/runtime-corejs3": "^7.8.3"
}
},
"xss": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.7.tgz",
"integrity": "sha512-A9v7tblGvxu8TWXQC9rlpW96a+LN1lyw6wyhpTmmGW+FwRMactchBR3ROKSi33UPCUcUHSu8s9YP6F+K3Mw//w==",
"dev": true,
"requires": {
"commander": "^2.20.3",
"cssfilter": "0.0.10"
}
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View file

@ -106,6 +106,8 @@
"@types/styled-theming": "^2.2.3",
"@typescript-eslint/eslint-plugin": "^3.1.0",
"@typescript-eslint/parser": "^3.1.0",
"apollo-server": "^2.14.4",
"apollo-server-testing": "^2.14.4",
"babel-jest": "^26.0.1",
"babel-loader": "^8.1.0",
"babel-plugin-inline-react-svg": "^1.1.1",
@ -124,6 +126,7 @@
"fast-diff": "^1.2.0",
"husky": "^4.2.5",
"jest": "^26.0.1",
"jest-fetch-mock": "^3.0.3",
"lint-staged": "^10.2.9",
"prettier": "^2.0.5",
"standard-version": "^8.0.0",

View file

@ -11,9 +11,9 @@ import AES from 'crypto-js/aes';
import CryptoJS from 'crypto-js';
import { logger } from './logger';
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
const { nodeEnv } = serverRuntimeConfig;
const { noClient } = publicRuntimeConfig;
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig() || {};
const { nodeEnv } = serverRuntimeConfig || {};
const { noClient } = publicRuntimeConfig || {};
type LndAuthType = {
cert: string;
@ -37,7 +37,7 @@ export const getCorrectAuth = (
auth: AuthType,
context: ContextType
): LndAuthType => {
if (auth.type === 'test' && nodeEnv === 'development') {
if (auth.type === 'test' && nodeEnv !== 'production') {
return {
host: process.env.TEST_HOST,
macaroon: process.env.TEST_MACAROON,

View file

@ -1,37 +1,23 @@
import { createLogger, format, transports } from 'winston';
import getConfig from 'next/config';
const { serverRuntimeConfig } = getConfig();
const { serverRuntimeConfig = {} } = getConfig() || {};
const { logLevel } = serverRuntimeConfig;
const combinedFormat =
// nodeEnv === 'development' ?
format.combine(
format.label({ label: 'THUB' }),
format.splat(),
format.colorize(),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
format.printf(
(info: any) =>
`${info.timestamp} ${info.level} [${info.label}]: ${info.message}`
)
);
// : format.combine(
// format.label({
// label: path.basename(
// process && process.mainModule ? process.mainModule.filename : ''
// ),
// }),
// format.splat(),
// format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
// format.printf(
// (info: any) =>
// `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`
// )
// );
const combinedFormat = format.combine(
format.label({ label: 'THUB' }),
format.splat(),
format.colorize(),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
format.printf(
(info: any) =>
`${info.timestamp} ${info.level} [${info.label}]: ${info.message}`
)
);
export const logger = createLogger({
level: logLevel,
format: combinedFormat,
transports: [new transports.Console()],
silent: process.env.NODE_ENV === 'test' ? true : false,
});

View file

@ -0,0 +1,73 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Account Resolvers getServerAccounts full accounts 1`] = `
Object {
"data": Object {
"getServerAccounts": Array [
Object {
"id": "accountID",
"loggedIn": true,
"name": "account",
"type": "server",
},
Object {
"id": "sso",
"loggedIn": true,
"name": "SSO Account",
"type": "sso",
},
],
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Account Resolvers getServerAccounts without SSO 1`] = `
Object {
"data": Object {
"getServerAccounts": Array [
Object {
"id": "accountID",
"loggedIn": true,
"name": "account",
"type": "server",
},
],
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Account Resolvers getServerAccounts without accounts 1`] = `
Object {
"data": Object {
"getServerAccounts": Array [
Object {
"id": "accountID",
"loggedIn": true,
"name": "account",
"type": "server",
},
],
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;

View file

@ -0,0 +1,43 @@
import testServer from 'server/tests/testServer';
import { GET_SERVER_ACCOUNTS } from 'src/graphql/queries/getServerAccounts';
import { ContextMockNoSSO } from 'server/tests/testMocks';
jest.mock('ln-service');
describe('Account Resolvers', () => {
describe('getServerAccounts', () => {
test('full accounts', async () => {
const { query } = testServer();
const res = await query({
query: GET_SERVER_ACCOUNTS,
variables: { auth: { type: 'test' } },
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
test('without SSO', async () => {
const { query } = testServer(ContextMockNoSSO);
const res = await query({
query: GET_SERVER_ACCOUNTS,
variables: { auth: { type: 'test' } },
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
test('without accounts', async () => {
const { query } = testServer(ContextMockNoSSO);
const res = await query({
query: GET_SERVER_ACCOUNTS,
variables: { auth: { type: 'test' } },
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
});
});

View file

@ -7,7 +7,7 @@ export const accountResolvers = {
Query: {
getServerAccounts: async (
_: undefined,
params: any,
__: undefined,
context: ContextType
) => {
const { ip, accounts, account, sso, ssoVerified } = context;

View file

@ -8,8 +8,8 @@ import cookie from 'cookie';
import { requestLimiter } from 'server/helpers/rateLimiter';
import AES from 'crypto-js/aes';
const { serverRuntimeConfig } = getConfig();
const { cookiePath, nodeEnv } = serverRuntimeConfig;
const { serverRuntimeConfig } = getConfig() || {};
const { cookiePath, nodeEnv } = serverRuntimeConfig || {};
export const authResolvers = {
Query: {

View file

@ -0,0 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Bitcoin Resolvers getBitcoinFees failure 1`] = `
Object {
"data": Object {
"getBitcoinFees": null,
},
"errors": Array [
[GraphQLError: Problem getting Bitcoin fees.],
],
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Bitcoin Resolvers getBitcoinFees success 1`] = `
Object {
"data": Object {
"getBitcoinFees": Object {
"fast": 3,
"halfHour": 2,
"hour": 1,
},
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Bitcoin Resolvers getBitcoinPrice failure 1`] = `
Object {
"data": Object {
"getBitcoinPrice": null,
},
"errors": Array [
[GraphQLError: Problem getting Bitcoin price.],
],
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Bitcoin Resolvers getBitcoinPrice success 1`] = `
Object {
"data": Object {
"getBitcoinPrice": "{\\"price\\":\\"price\\"}",
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;

View file

@ -0,0 +1,75 @@
import testServer from 'server/tests/testServer';
import fetchMock from 'jest-fetch-mock';
import { GraphQLError } from 'graphql';
import { GET_BITCOIN_PRICE } from 'src/graphql/queries/getBitcoinPrice';
import { GET_BITCOIN_FEES } from 'src/graphql/queries/getBitcoinFees';
describe('Bitcoin Resolvers', () => {
beforeEach(() => {
fetchMock.resetMocks();
});
describe('getBitcoinPrice', () => {
test('success', async () => {
fetchMock.mockResponseOnce(JSON.stringify({ price: 'price' }));
const { query } = testServer();
const res = await query({
query: GET_BITCOIN_PRICE,
});
expect(res.errors).toBe(undefined);
expect(fetchMock).toBeCalledWith('https://blockchain.info/ticker');
expect(res).toMatchSnapshot();
});
test('failure', async () => {
fetchMock.mockRejectOnce(new Error('Error'));
const { query } = testServer();
const res = await query({
query: GET_BITCOIN_PRICE,
});
expect(res.errors).toStrictEqual([
new GraphQLError('Problem getting Bitcoin price.'),
]);
expect(res).toMatchSnapshot();
});
});
describe('getBitcoinFees', () => {
test('success', async () => {
fetchMock.mockResponseOnce(
JSON.stringify({
fastestFee: 3,
halfHourFee: 2,
hourFee: 1,
})
);
const { query } = testServer();
const res = await query({
query: GET_BITCOIN_FEES,
});
expect(res.errors).toBe(undefined);
expect(fetchMock).toBeCalledWith(
'https://bitcoinfees.earn.com/api/v1/fees/recommended'
);
expect(res).toMatchSnapshot();
});
test('failure', async () => {
fetchMock.mockRejectOnce(new Error('Error'));
const { query } = testServer();
const res = await query({
query: GET_BITCOIN_FEES,
});
expect(res.errors).toStrictEqual([
new GraphQLError('Problem getting Bitcoin fees.'),
]);
expect(res).toMatchSnapshot();
});
});
});

View file

@ -7,7 +7,7 @@ export const bitcoinResolvers = {
Query: {
getBitcoinPrice: async (
_: undefined,
params: any,
__: undefined,
context: ContextType
) => {
await requestLimiter(context.ip, 'bitcoinPrice');

View file

@ -0,0 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Chain Resolvers getChainBalance 1`] = `
Object {
"data": Object {
"getChainBalance": 1000000,
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`Chain Resolvers getPendingChainBalance 1`] = `
Object {
"data": Object {
"getPendingChainBalance": 1000000,
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;

View file

@ -0,0 +1,36 @@
import { AuthMock } from 'server/tests/testMocks';
import testServer from 'server/tests/testServer';
import gql from 'graphql-tag';
jest.mock('ln-service');
describe('Chain Resolvers', () => {
test('getChainBalance', async () => {
const getChainBalance = gql`
query($auth: authType!) {
getChainBalance(auth: $auth)
}
`;
const { query } = testServer();
const res = await query({
query: getChainBalance,
variables: AuthMock,
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
test('getPendingChainBalance', async () => {
const getPendingChainBalance = gql`
query($auth: authType!) {
getPendingChainBalance(auth: $auth)
}
`;
const { query } = testServer();
const res = await query({
query: getPendingChainBalance,
variables: AuthMock,
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
});

View file

@ -5,8 +5,8 @@ import { logger } from 'server/helpers/logger';
import { appUrls } from 'server/utils/appUrls';
import { getHodlParams } from 'server/helpers/hodlHelpers';
const { serverRuntimeConfig } = getConfig();
const { hodlKey } = serverRuntimeConfig;
const { serverRuntimeConfig } = getConfig() || {};
const { hodlKey } = serverRuntimeConfig || {};
const defaultQuery = {
filters: {},

View file

@ -37,6 +37,7 @@ import { githubResolvers } from './github/resolvers';
import { routeTypes } from './route/types';
import { generalResolvers } from './resolvers';
import { macaroonResolvers } from './macaroon/resolvers';
import { networkResolvers } from './network/resolvers';
const typeDefs = [
generalTypes,
@ -80,7 +81,8 @@ const resolvers = merge(
transactionResolvers,
healthResolvers,
githubResolvers,
macaroonResolvers
macaroonResolvers,
networkResolvers
);
export default makeExecutableSchema({ typeDefs, resolvers });

View file

@ -0,0 +1,68 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LnPay Resolvers getLnPay failure 1`] = `
Object {
"data": Object {
"getLnPay": null,
},
"errors": Array [
[GraphQLError: NoLnPayInvoice],
],
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`LnPay Resolvers getLnPay success 1`] = `
Object {
"data": Object {
"getLnPay": "paymentRequest",
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`LnPay Resolvers getLnPayInfo failure 1`] = `
Object {
"data": Object {
"getLnPayInfo": null,
},
"errors": Array [
[GraphQLError: NoLnPay],
],
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;
exports[`LnPay Resolvers getLnPayInfo success 1`] = `
Object {
"data": Object {
"getLnPayInfo": Object {
"max": 1000,
"min": 1,
},
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;

View file

@ -0,0 +1,68 @@
import testServer from 'server/tests/testServer';
import { GET_LN_PAY } from 'src/graphql/queries/getLnPay';
import fetchMock from 'jest-fetch-mock';
import { GraphQLError } from 'graphql';
import { GET_LN_PAY_INFO } from 'src/graphql/queries/getLnPayInfo';
describe('LnPay Resolvers', () => {
beforeEach(() => {
fetchMock.resetMocks();
});
describe('getLnPay', () => {
test('success', async () => {
fetchMock.mockResponseOnce(JSON.stringify({ pr: 'paymentRequest' }));
const { query } = testServer();
const res = await query({
query: GET_LN_PAY,
variables: { amount: 100 },
});
expect(res.errors).toBe(undefined);
expect(fetchMock).toBeCalledWith(
'https://thunderhub.io/api/lnpay?amount=100'
);
expect(res).toMatchSnapshot();
});
test('failure', async () => {
fetchMock.mockRejectOnce(new Error('Error'));
const { query } = testServer();
const res = await query({
query: GET_LN_PAY,
variables: { amount: 100 },
});
expect(res.errors).toStrictEqual([new GraphQLError('NoLnPayInvoice')]);
expect(res).toMatchSnapshot();
});
});
describe('getLnPayInfo', () => {
test('success', async () => {
fetchMock.mockResponseOnce(
JSON.stringify({ maxSendable: 1000, minSendable: 1 })
);
const { query } = testServer();
const res = await query({
query: GET_LN_PAY_INFO,
});
expect(res.errors).toBe(undefined);
expect(fetchMock).toBeCalledWith('https://thunderhub.io/api/lnpay');
expect(res).toMatchSnapshot();
});
test('failure', async () => {
fetchMock.mockRejectOnce(new Error('Error'));
const { query } = testServer();
const res = await query({
query: GET_LN_PAY_INFO,
});
expect(res.errors).toStrictEqual([new GraphQLError('NoLnPay')]);
expect(res).toMatchSnapshot();
});
});
});

View file

@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Network Resolvers getNetworkInfo success 1`] = `
Object {
"data": Object {
"getNetworkInfo": Object {
"averageChannelSize": "1000",
"channelCount": 123,
"maxChannelSize": 456,
"medianChannelSize": 789,
"minChannelSize": 100,
"nodeCount": 10000,
"notRecentlyUpdatedPolicyCount": 10,
"totalCapacity": "10000",
},
},
"errors": undefined,
"extensions": undefined,
"http": Object {
"headers": Headers {
Symbol(map): Object {},
},
},
}
`;

View file

@ -0,0 +1,20 @@
import testServer from 'server/tests/testServer';
import { GET_NETWORK_INFO } from 'src/graphql/queries/getNetworkInfo';
jest.mock('ln-service');
describe('Network Resolvers', () => {
describe('getNetworkInfo', () => {
test('success', async () => {
const { query } = testServer();
const res = await query({
query: GET_NETWORK_INFO,
variables: { auth: { type: 'test' } },
});
expect(res.errors).toBe(undefined);
expect(res).toMatchSnapshot();
});
});
});

View file

@ -1,12 +1,8 @@
import { getNetworkInfo as getLnNetworkInfo } from 'ln-service';
import { getNetworkInfo } from 'ln-service';
import { ContextType } from 'server/types/apiTypes';
import { logger } from 'server/helpers/logger';
import { requestLimiter } from 'server/helpers/rateLimiter';
import {
getAuthLnd,
getErrorMsg,
getCorrectAuth,
} from 'server/helpers/helpers';
import { getLnd } from 'server/helpers/helpers';
import { to } from 'server/helpers/async';
interface NetworkInfoProps {
average_channel_size: number;
@ -24,26 +20,20 @@ export const networkResolvers = {
getNetworkInfo: async (_: undefined, params: any, context: ContextType) => {
await requestLimiter(context.ip, 'networkInfo');
const auth = getCorrectAuth(params.auth, context);
const lnd = getAuthLnd(auth);
const lnd = getLnd(params.auth, context);
try {
const info: NetworkInfoProps = await getLnNetworkInfo({ lnd });
const info: NetworkInfoProps = await to(getNetworkInfo({ lnd }));
return {
averageChannelSize: info.average_channel_size,
channelCount: info.channel_count,
maxChannelSize: info.max_channel_size,
medianChannelSize: info.median_channel_size,
minChannelSize: info.min_channel_size,
nodeCount: info.node_count,
notRecentlyUpdatedPolicyCount: info.not_recently_updated_policy_count,
totalCapacity: info.total_capacity,
};
} catch (error) {
logger.error('Error getting network info: %o', error);
throw new Error(getErrorMsg(error));
}
return {
averageChannelSize: info.average_channel_size,
channelCount: info.channel_count,
maxChannelSize: info.max_channel_size,
medianChannelSize: info.median_channel_size,
minChannelSize: info.min_channel_size,
nodeCount: info.node_count,
notRecentlyUpdatedPolicyCount: info.not_recently_updated_policy_count,
totalCapacity: info.total_capacity,
};
},
},
};

View file

@ -21,7 +21,7 @@ export const nodeTypes = gql`
closed_channels_count: Int
alias: String
current_block_hash: String
current_block_height: Boolean
current_block_height: Int
is_synced_to_chain: Boolean
is_synced_to_graph: Boolean
latest_block_at: String

View file

@ -0,0 +1,91 @@
export const getNetworkInfo = () =>
Promise.resolve({
average_channel_size: 1000,
channel_count: 123,
max_channel_size: 456,
median_channel_size: 789,
min_channel_size: 100,
node_count: 10000,
not_recently_updated_policy_count: 10,
total_capacity: 10000,
});
export const getWalletInfo = () =>
Promise.resolve({
chains: ['abc', 'def'],
color: 'color',
active_channels_count: 1,
alias: 'TestNode',
current_block_hash: 'asd',
current_block_height: 123456,
is_synced_to_chain: true,
is_synced_to_graph: true,
latest_block_at: 'time',
peers_count: 1,
pending_channels_count: 2,
public_key: 'key',
uris: ['uri', 'uri2'],
version: 'version',
});
export const getClosedChannels = () =>
Promise.resolve({
channels: [
{
capacity: 10000,
close_confirm_height: 123,
close_transaction_id: 'fghijk',
final_local_balance: 123,
final_time_locked_balance: 123,
id: 'id',
is_breach_close: false,
is_cooperative_close: true,
is_funding_cancel: false,
is_local_force_close: false,
is_remote_force_close: false,
partner_public_key: 'abcdef',
transaction_id: '123',
transaction_vout: 1,
},
{
capacity: 10000,
close_confirm_height: 123,
close_transaction_id: 'fghijk',
final_local_balance: 123,
final_time_locked_balance: 123,
id: 'id',
is_breach_close: false,
is_cooperative_close: true,
is_funding_cancel: false,
is_local_force_close: false,
is_remote_force_close: false,
partner_public_key: 'abcdef',
transaction_id: '123',
transaction_vout: 1,
},
{
capacity: 10000,
close_confirm_height: 123,
close_transaction_id: 'fghijk',
final_local_balance: 123,
final_time_locked_balance: 123,
id: 'id',
is_breach_close: false,
is_cooperative_close: true,
is_funding_cancel: false,
is_local_force_close: false,
is_remote_force_close: false,
partner_public_key: 'abcdef',
transaction_id: '123',
transaction_vout: 1,
},
],
});
export const getChainBalance = () =>
Promise.resolve({ chain_balance: 1000000 });
export const getPendingChainBalance = () =>
Promise.resolve({ pending_chain_balance: 1000000 });
export const authenticatedLndGrpc = jest.fn().mockReturnValue({});

75
server/tests/testMocks.ts Normal file
View file

@ -0,0 +1,75 @@
import { ServerResponse } from 'http';
import { ContextType } from 'server/types/apiTypes';
export const AuthMock = {
auth: {
type: 'test',
},
};
export const ContextMock: ContextType = {
ip: '1.2.3.4',
secret: '123456789',
ssoVerified: true,
account: {
id: 'accountID',
password: 'password',
},
sso: {
macaroon: 'macaroon',
cert: 'cert',
host: 'host',
},
accounts: [
{
name: 'account',
id: 'accountID',
host: 'host',
macaroon: 'macaroon',
cert: 'cert',
},
],
res: {} as ServerResponse,
};
export const ContextMockNoAccounts: ContextType = {
ip: '1.2.3.4',
secret: '123456789',
ssoVerified: true,
account: {
id: 'accountID',
password: 'password',
},
sso: {
macaroon: 'macaroon',
cert: 'cert',
host: 'host',
},
accounts: [],
res: {} as ServerResponse,
};
export const ContextMockNoSSO: ContextType = {
ip: '1.2.3.4',
secret: '123456789',
ssoVerified: true,
account: {
id: 'accountID',
password: 'password',
},
sso: {
macaroon: null,
cert: null,
host: null,
},
accounts: [
{
name: 'account',
id: 'accountID',
host: 'host',
macaroon: 'macaroon',
cert: 'cert',
},
],
res: {} as ServerResponse,
};

View file

@ -0,0 +1,13 @@
import {
createTestClient,
ApolloServerTestClient,
} from 'apollo-server-testing';
import { ApolloServer } from 'apollo-server';
import schema from 'server/schema';
import { ContextMock } from 'server/tests/testMocks';
export default function testServer(context?: any): ApolloServerTestClient {
return createTestClient(
new ApolloServer({ schema, context: context || ContextMock })
);
}

View file

@ -1 +1,4 @@
import '@testing-library/jest-dom/extend-expect';
import fetchMock from 'jest-fetch-mock';
fetchMock.enableMocks();

View file

@ -401,7 +401,7 @@ export type NodeInfoType = {
closed_channels_count?: Maybe<Scalars['Int']>;
alias?: Maybe<Scalars['String']>;
current_block_hash?: Maybe<Scalars['String']>;
current_block_height?: Maybe<Scalars['Boolean']>;
current_block_height?: Maybe<Scalars['Int']>;
is_synced_to_chain?: Maybe<Scalars['Boolean']>;
is_synced_to_graph?: Maybe<Scalars['Boolean']>;
latest_block_at?: Maybe<Scalars['String']>;