[WIP] start adding unit test to repo

@types
neeboo 6 years ago
parent d61358d7cf
commit e7ace6f172
  1. 8
      examples/testNode.js
  2. 3
      package.json
  3. 27
      packages/harmony-account/src/wallet.ts
  4. 12
      packages/harmony-crypto/src/keystore.ts
  5. 2
      packages/harmony-crypto/src/types.ts
  6. 32
      packages/harmony-utils/__test__/fixture.ts
  7. 3
      packages/harmony-utils/__test__/tsconfig.json
  8. 83
      packages/harmony-utils/__test__/validators.test.ts
  9. 15
      packages/harmony-utils/src/validators.ts
  10. 5
      packages/harmony-utils/tsconfig.test.json
  11. 32
      scripts/jest/jest.build.config.js
  12. 31
      scripts/jest/jest.src.config.js
  13. 2
      tsconfig.test.json

@ -124,5 +124,9 @@ const acc = wallet.addByPrivateKey(
// console.log(getContractAddress(acc.publicKey, 248));
const harmony = new Harmony('https://devnet.harmony.one');
console.log(harmony.blockchain);
const harmony = new Harmony('https://dev-api.zilliqa.com');
const file =
'{"version":3,"id":"05D302EE-23DC-48C4-B89C-CAAAC1C780C4","x-ethers":{"gethFilename":"UTC--2018-01-26T20-25-02.0Z--15db397ed5f682acb22b0afc6c8de4cdfbda7cbc","mnemonicCiphertext":"b92c7c3da540ae7beee55365fb330c33","mnemonicCounter":"a65d689a73c096025f2acae3f7068510","client":"ethers/iOS","version":"0.1"},"Crypto":{"ciphertext":"fa6ff2374087a089ec9fcba3bc21389f5e26ec2932c95b608ebe0218efab83c6","cipherparams":{"iv":"5ddca45b254406516ca2c97d18d5dfd9"},"kdf":"scrypt","kdfparams":{"r":8,"p":1,"n":262144,"dklen":32,"salt":"864a474f8586ab0fa97ed9240ae6227b2b22b48bdf298137c355e4a07eb19831"},"mac":"eaa89325acedbf88c0893e53c8c8d426b590655746c66da9cd76e4f72d84084f","cipher":"aes-128-ctr"},"address":"15db397ed5f682acb22b0afc6c8de4cdfbda7cbc"}';
const acc2 = new Account().fromFile(file, 'password').then(console.log);

@ -16,7 +16,8 @@
"bundle": "ts-node -P scripts/tsconfig.json scripts/bundle.ts umd,esm",
"clean": "lerna clean --yes && lerna run clean && rimraf includes",
"schema": "ts-node -P scripts/tsconfig.json scripts/typings/schema.ts core",
"test": "cross-env TEST_ENV=unit jest -c jest.config.js --rootDir=.",
"test": "cross-env TEST_ENV=unit jest -c scripts/jest/jest.config.js --rootDir=.",
"test:src": "cross-env NODE_ENV=test jest --config ./scripts/jest/jest.src.config.js --silent --runInBand --no-cache",
"test:build": "cross-env TEST_ENV=unit jest -c jest.build.config.js",
"test:integration": "cross-env TEST_ENV=integration jest -c jest.iconfig.js --runInBand --verbose --collectCoverage=false",
"release": "yarn bootstrap && yarn bundle && lerna publish --exact",

@ -42,7 +42,7 @@ class Wallet {
}
const seed = bip39.mnemonicToSeed(phrase);
const hdKey = hdkey.fromMasterSeed(seed);
//TODO:hdkey should apply to Harmony's settings
// TODO:hdkey should apply to Harmony's settings
const childKey = hdKey.derive(`m/44'/313'/0'/0/${index}`);
const privateKey = childKey.privateKey.toString('hex');
return this.addByPrivateKey(privateKey);
@ -68,6 +68,31 @@ class Wallet {
throw error;
}
}
/**
* @function createAccount
* @description create a new account using Mnemonic
* @return {Account} {description}
*/
async createAccount(
password?: string,
options?: EncryptOptions,
): Promise<Account> {
const words = this.generateMnemonic();
const acc = this.addByMnemonic(words);
if (acc.address && password) {
const encrypted = await this.encryptAccount(
acc.address,
password,
options,
);
return encrypted;
} else if (acc.address && !password) {
return acc;
} else {
throw new Error('create acount failed');
}
}
/**
* @function encryptAccount
* @memberof Wallet

@ -119,7 +119,7 @@ export const encrypt = async (
version: 3,
id: uuid.v4({ random: uuidRandom || hexToIntArray(randomBytes(16)) }),
address: address.toLowerCase().replace('0x', ''),
crypto: {
Crypto: {
ciphertext: ciphertext.toString('hex'),
cipherparams: {
iv: iv.toString('hex'),
@ -142,13 +142,13 @@ export const decrypt = async (
keystore: Keystore,
password: string,
): Promise<string> => {
const ciphertext = Buffer.from(keystore.crypto.ciphertext, 'hex');
const iv = Buffer.from(keystore.crypto.cipherparams.iv, 'hex');
const { kdfparams } = keystore.crypto;
const ciphertext = Buffer.from(keystore.Crypto.ciphertext, 'hex');
const iv = Buffer.from(keystore.Crypto.cipherparams.iv, 'hex');
const { kdfparams } = keystore.Crypto;
const derivedKey = await getDerivedKey(
Buffer.from(password),
keystore.crypto.kdf,
keystore.Crypto.kdf,
kdfparams,
);
@ -157,7 +157,7 @@ export const decrypt = async (
'',
);
if (mac.toUpperCase() !== keystore.crypto.mac.toUpperCase()) {
if (mac.toUpperCase() !== keystore.Crypto.mac.toUpperCase()) {
return Promise.reject(new Error('Failed to decrypt.'));
}

@ -24,7 +24,7 @@ export interface EncryptOptions {
export interface Keystore {
address: string;
crypto: {
Crypto: {
cipher: string;
cipherparams: {
iv: string;

@ -0,0 +1,32 @@
// import BN from 'bn.js';
export const basicType = {
zero: 0,
float: 0.1,
text: 'testString',
jsonString:
'{"name":"@harmony/utils","version":"0.0.48","description":"utils for harmony"}',
hexNumber: 0x123,
hexString: '0x123',
bool: true,
undefined,
null: null,
// tslint:disable-next-line: no-empty
function: () => {},
array: [1, 2, 3],
object: {},
};
export const advanceType = {
privateKey:
'0x97d2d3a21d829800eeb01aa7f244926f993a1427d9ba79d9dc3bf14fe04d9e37',
publicKey:
'0x028fe48b60c4511f31cf58906ddaa8422725d9313d4b994fab598d2cf220146228',
address: '0x84fece7d1f5629bc728c956ffd313dd0c3ac8f17',
hexAddress: '0x84fece7d1f5629bc728c956ffd313dd0c3ac8f17',
checkSumAddress: '0x84fece7d1f5629Bc728c956Ffd313dD0C3AC8f17',
hex: '0x8423',
hash: 'F5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B',
byStrX: '0x84fece7d1f5629bc728c956ffd313dd0c3ac8f17',
url: 'https://www.zilliqa.com',
};

@ -0,0 +1,3 @@
{
"extends": "../tsconfig.test.json"
}

@ -0,0 +1,83 @@
import * as validators from '../src/validators';
import { basicType, advanceType } from './fixture';
function expector(fun: any, val: any, bool: boolean) {
return expect(fun(val)).toEqual(bool);
}
function mapTest(testObject: any, testTrue: string[], testFunc: any) {
const keys = Object.keys(testObject);
keys.forEach((k: string) => {
if (testTrue.includes(k)) {
expector(testFunc, testObject[k], true);
} else {
expector(testFunc, testObject[k], false);
}
});
}
describe('test transformer', () => {
it('test isNumber', () => {
const beTrue = ['zero', 'float', 'hexNumber'];
mapTest(basicType, beTrue, validators.isNumber);
});
it('test isInt', () => {
const beTrue = ['zero', 'hexNumber'];
mapTest(basicType, beTrue, validators.isInt);
});
it('test isString', () => {
const beTrue = ['text', 'hexString', 'jsonString'];
mapTest(basicType, beTrue, validators.isString);
});
it('test isBoolean', () => {
const beTrue = ['bool'];
mapTest(basicType, beTrue, validators.isBoolean);
});
it('test isArray', () => {
const beTrue = ['array'];
mapTest(basicType, beTrue, validators.isArray);
});
it('test isJsonString', () => {
const beTrue = ['jsonString'];
mapTest(basicType, beTrue, validators.isJsonString);
});
it('test isObject', () => {
const beTrue = ['object'];
mapTest(basicType, beTrue, validators.isObject);
});
it('test isFunction', () => {
const beTrue = ['function'];
mapTest(basicType, beTrue, validators.isFunction);
});
it('test isPubKey', () => {
const beTrue = ['publicKey'];
mapTest({ ...advanceType }, beTrue, validators.isPublicKey);
});
it('test isAddress', () => {
const beTrue = ['address', 'hexAddress', 'checkSumAddress', 'byStrX'];
mapTest({ ...advanceType }, beTrue, validators.isAddress);
});
it('test isPrivateKey', () => {
const beTrue = ['privateKey', 'hash'];
mapTest({ ...advanceType }, beTrue, validators.isPrivateKey);
});
it('test isHex', () => {
const beTrue = [
'privateKey',
'publicKey',
'address',
'hexString',
'hexAddress',
'checkSumAddress',
'hex',
'byStrX',
];
mapTest({ ...advanceType }, beTrue, validators.isHex);
try {
validators.isHex(basicType.zero);
} catch (error) {
expect(error.message).toEqual(`${basicType.zero} is not string`);
}
});
});

@ -91,17 +91,12 @@ export const isFunction = (obj: any): boolean => {
return typeof obj === 'function';
};
export const isHex = (obj: string): boolean => {
export const isHex = (obj: any): boolean => {
if (!isString(obj)) {
throw new Error(`${obj} is not string`);
} else {
try {
return (
(obj.startsWith('0x') || obj.startsWith('-0x')) &&
isNumber(Number.parseInt(obj.toLowerCase().replace('0x', ''), 16))
);
} catch (error) {
throw error;
}
}
return (
(obj.startsWith('0x') || obj.startsWith('-0x')) &&
isNumber(Number.parseInt(`${obj}`.toLowerCase().replace('0x', ''), 16))
);
};

@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.test.json",
"include": ["src", "test", "../../typings/**/*.d.ts"],
"references": []
}

@ -1,29 +1,29 @@
const { readdirSync, statSync } = require('fs')
const { join } = require('path')
const baseConfig = require('./jest.src.config')
const { readdirSync, statSync } = require('fs');
const { join } = require('path');
const baseConfig = require('./jest.src.config');
// Find all folders in packages/* with package.json
const packagesRoot = join(__dirname, '..', '..', 'packages')
const packages = readdirSync(packagesRoot).filter(dir => {
const packagesRoot = join(__dirname, '..', '..', 'packages');
const packages = readdirSync(packagesRoot).filter((dir) => {
if (dir.charAt(0) === '.') {
return false
return false;
}
if (dir === 'events') {
// There's an actual Node package called "events"
// that's used by jsdom so we don't want to alias that.
return false
return false;
}
const packagePath = join(packagesRoot, dir, 'package.json')
return statSync(packagePath).isFile()
})
const packagePath = join(packagesRoot, dir, 'package.json');
return statSync(packagePath).isFile();
});
// Create a module map to point packages to the build output
const moduleNameMapper = {}
packages.forEach(name => {
const moduleNameMapper = {};
packages.forEach((name) => {
// Root entry point
moduleNameMapper[`^${name}$`] = `<rootDir>/packages/${name}/lib/index.js`
moduleNameMapper[`^${name}$`] = `<rootDir>/packages/${name}/dist/index.js`;
// Named entry points
// moduleNameMapper[`^${name}/(.*)$`] = `<rootDir>/dist/node_modules/${name}/$1`
})
});
module.exports = Object.assign({}, baseConfig, {
// Redirect imports to the compiled bundles
@ -31,5 +31,5 @@ module.exports = Object.assign({}, baseConfig, {
// Don't run bundle tests on blacklisted -test.internal.* files
testPathIgnorePatterns: ['/node_modules/', '-test.internal.js$'],
// Exclude the build output from transforms
transformIgnorePatterns: ['/node_modules/', '<rootDir>/build/']
})
transformIgnorePatterns: ['/node_modules/', '<rootDir>/build/'],
});

@ -1,9 +1,16 @@
const config = {
transform: {
'^.+\\.(t|j)s$': require.resolve('./transformer.js')
// '^.+\\.(t|j)s$': require.resolve('./transformer.js')
'^.+\\.(t)s$': 'ts-jest',
},
globals: {
'ts-jest': {
babelConfig: true,
tsConfig: './tsconfig.test.json',
},
},
testMatch: [
'<rootDir>/packages/**/__test__/?(*.)+(spec|test).js'
// '<rootDir>/packages/**/__test__/?(*.)+(spec|test).js',
// '<rootDir>/packages/laksa-account/__test__/?(*.)+(spec|test).js',
// '<rootDir>/packages/laksa-blockchain/__test__/?(*.)+(spec|test).js',
// '<rootDir>/packages/laksa-core/__test__/?(*.)+(spec|test).js'
@ -15,14 +22,14 @@ const config = {
// '<rootDir>/packages/laksa-extend-keystore/__test__/?(*.)+(spec|test).js',
// '<rootDir>/packages/laksa-providers-http/__test__/?(*.)+(spec|test).js',
// '<rootDir>/packages/laksa-shared/__test__/?(*.)+(spec|test).js'
// '<rootDir>/packages/laksa-utils/__test__/?(*.)+(spec|test).js',
'<rootDir>/packages/harmony-utils/__test__/?(*.)+(spec|test).ts',
// '<rootDir>/packages/laksa-wallet/__test__/?(*.)+(spec|test).js'
// '<rootDir>/packages/laksa/__test__/?(*.)+(spec|test).js'
],
moduleDirectories: ['src', 'node_modules'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleNameMapper: {
'cross-fetch': 'jest-fetch-mock'
'cross-fetch': 'jest-fetch-mock',
},
testURL: 'http://localhost',
coverageThreshold: {
@ -30,21 +37,23 @@ const config = {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
statements: 80,
},
},
rootDir: process.cwd(),
roots: ['<rootDir>/packages', '<rootDir>/scripts'],
collectCoverageFrom: [
'packages/!(laksa-hd-wallet)/src/**/*.js'
// 'packages/!(harmony-core)/src/**/*.ts',
'packages/harmony-utils/src/**/*.ts',
// 'packages/!(laksa-core-crypto)/src/*.js'
],
timers: 'fake',
setupFiles: ['<rootDir>/scripts/jest/jest.setup.js'],
setupTestFrameworkScriptFile: '<rootDir>/scripts/jest/jest.framework-setup.js',
setupTestFrameworkScriptFile:
'<rootDir>/scripts/jest/jest.framework-setup.js',
testEnvironment: process.env.NODE_ENV === 'development' ? 'node' : 'jsdom',
collectCoverage: true,
automock: false
}
automock: false,
};
module.exports = config
module.exports = config;

@ -2,5 +2,5 @@
"extends": "./tsconfig.base.json",
"files": [],
"include": ["./typings/**/*.d.ts"],
"references": []
"references": [{ "path": "packages/harmony-utils" }]
}

Loading…
Cancel
Save