Rename assert sub-package and removed duplicate methods from 0x.js's assert module

This commit is contained in:
Fabio Berger
2017-11-13 17:42:42 -05:00
parent cf29530dd0
commit 3e8e3478a3
9 changed files with 15 additions and 78 deletions

View File

@@ -1,5 +0,0 @@
<img src="https://github.com/0xProject/branding/blob/master/0x_Black_CMYK.png" width="200px" >
---
Standard type and schema assertions to be used across all 0x projects and packages

View File

@@ -1,14 +0,0 @@
machine:
node:
version: 6.5.0
dependencies:
override:
- yarn
cache_directories:
- ~/.cache/yarn
test:
override:
- yarn test
- yarn lint

View File

@@ -1,45 +0,0 @@
{
"name": "0x-assert",
"version": "0.0.3",
"description": "Provides a standard way of performing type and schema validation across 0x projects",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc",
"clean": "shx rm -rf _bundles lib test_temp",
"lint": "tslint src/**/*.ts test/**/*.ts",
"run_mocha": "mocha lib/test/**/*_test.js",
"prepublishOnly": "run-p build",
"test": "run-s clean build run_mocha"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/0xProject/assert.git"
},
"bugs": {
"url": "https://github.com/0xProject/assert/issues"
},
"homepage": "https://github.com/0xProject/assert#readme",
"devDependencies": {
"@types/lodash": "^4.14.78",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
"chai": "^4.0.1",
"chai-typescript-typings": "^0.0.1",
"dirty-chai": "^2.0.1",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.1",
"shx": "^0.2.2",
"tslint": "~5.5.0",
"tslint-config-0xproject": "^0.0.2",
"typescript": "^2.4.2"
},
"dependencies": {
"0x-json-schemas": "^0.6.5",
"bignumber.js": "~4.1.0",
"ethereum-address": "^0.0.4",
"lodash": "^4.17.4",
"valid-url": "^1.0.9"
}
}

View File

@@ -1,5 +0,0 @@
declare module 'dirty-chai';
declare module 'ethereum-address' {
const isAddress: (arg: any) => boolean;
}

View File

@@ -1,84 +0,0 @@
import BigNumber from 'bignumber.js';
import * as ethereum_address from 'ethereum-address';
import * as _ from 'lodash';
import * as validUrl from 'valid-url';
import {SchemaValidator, Schema} from '0x-json-schemas';
const HEX_REGEX = /^0x[0-9A-F]*$/i;
export const assert = {
isBigNumber(variableName: string, value: BigNumber): void {
const isBigNumber = _.isObject(value) && (value as any).isBigNumber;
this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value));
},
isUndefined(value: any, variableName?: string): void {
this.assert(_.isUndefined(value), this.typeAssertionMessage(variableName, 'undefined', value));
},
isString(variableName: string, value: string): void {
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
},
isFunction(variableName: string, value: any): void {
this.assert(_.isFunction(value), this.typeAssertionMessage(variableName, 'function', value));
},
isHexString(variableName: string, value: string): void {
this.assert(_.isString(value) && HEX_REGEX.test(value),
this.typeAssertionMessage(variableName, 'HexString', value));
},
isETHAddressHex(variableName: string, value: string): void {
this.assert(ethereum_address.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
this.assert(
ethereum_address.isAddress(value) && value.toLowerCase() === value,
`Checksummed addresses are not supported. Convert ${variableName} to lower case before passing`,
);
},
doesBelongToStringEnum(variableName: string, value: string,
stringEnum: any /* There is no base type for every string enum */): void {
const doesBelongToStringEnum = !_.isUndefined(stringEnum[value]);
const enumValues = _.keys(stringEnum);
const enumValuesAsStrings = _.map(enumValues, enumValue => `'${enumValue}'`);
const enumValuesAsString = enumValuesAsStrings.join(', ');
assert.assert(
doesBelongToStringEnum,
`Expected ${variableName} to be one of: ${enumValuesAsString}, encountered: ${value}`,
);
},
hasAtMostOneUniqueValue(value: any[], errMsg: string): void {
this.assert(_.uniq(value).length <= 1, errMsg);
},
isNumber(variableName: string, value: number): void {
this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value));
},
isBoolean(variableName: string, value: boolean): void {
this.assert(_.isBoolean(value), this.typeAssertionMessage(variableName, 'boolean', value));
},
isWeb3Provider(variableName: string, value: any): void {
const isWeb3Provider = _.isFunction((value as any).send) || _.isFunction((value as any).sendAsync);
this.assert(isWeb3Provider, this.typeAssertionMessage(variableName, 'Web3.Provider', value));
},
doesConformToSchema(variableName: string, value: any, schema: Schema): void {
const schemaValidator = new SchemaValidator();
const validationResult = schemaValidator.validate(value, schema);
const hasValidationErrors = validationResult.errors.length > 0;
const msg = `Expected ${variableName} to conform to schema ${schema.id}
Encountered: ${JSON.stringify(value, null, '\t')}
Validation errors: ${validationResult.errors.join(', ')}`;
this.assert(!hasValidationErrors, msg);
},
isHttpUrl(variableName: string, value: any): void {
const isValidUrl = validUrl.isWebUri(value);
this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'http url', value));
},
isUri(variableName: string, value: any): void {
const isValidUri = validUrl.isUri(value);
this.assert(isValidUri, this.typeAssertionMessage(variableName, 'uri', value));
},
assert(condition: boolean, message: string): void {
if (!condition) {
throw new Error(message);
}
},
typeAssertionMessage(variableName: string, type: string, value: any): string {
return `Expected ${variableName} to be of type ${type}, encountered: ${value}`;
},
};

View File

@@ -1,338 +0,0 @@
import 'mocha';
import * as dirtyChai from 'dirty-chai';
import * as chai from 'chai';
import {BigNumber} from 'bignumber.js';
import {schemas} from '0x-json-schemas';
import {assert} from '../src/index';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
describe('Assertions', () => {
const variableName = 'variable';
describe('#isBigNumber', () => {
it('should not throw for valid input', () => {
const validInputs = [
new BigNumber(23),
new BigNumber('45'),
];
validInputs.forEach(input => expect(assert.isBigNumber.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
'test',
42,
false,
{ random: 'test' },
undefined,
];
invalidInputs.forEach(input => expect(assert.isBigNumber.bind(assert, variableName, input)).to.throw());
});
});
describe('#isUndefined', () => {
it('should not throw for valid input', () => {
const validInputs = [
undefined,
];
validInputs.forEach(input => expect(assert.isUndefined.bind(assert, input, variableName)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
'test',
42,
false,
{ random: 'test' },
];
invalidInputs.forEach(input => expect(assert.isUndefined.bind(assert, input, variableName)).to.throw());
});
});
describe('#isString', () => {
it('should not throw for valid input', () => {
const validInputs = [
'hello',
'goodbye',
];
validInputs.forEach(input => expect(assert.isString.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
false,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input => expect(assert.isString.bind(assert, variableName, input)).to.throw());
});
});
describe('#isFunction', () => {
it('should not throw for valid input', () => {
const validInputs = [
BigNumber,
assert.isString.bind(this),
];
validInputs.forEach(input => expect(assert.isFunction.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
false,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input => expect(assert.isFunction.bind(assert, variableName, input)).to.throw());
});
});
describe('#isHexString', () => {
it('should not throw for valid input', () => {
const validInputs = [
'0x61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33',
'0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
];
validInputs.forEach(input => expect(assert.isHexString.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
false,
{ random: 'test' },
undefined,
new BigNumber(45),
'0x61a3ed31B43c8780e905a260a35faYfEc527be7516aa11c0256729b5b351bc33',
];
invalidInputs.forEach(input => expect(assert.isHexString.bind(assert, variableName, input)).to.throw());
});
});
describe('#isETHAddressHex', () => {
it('should not throw for valid input', () => {
const validInputs = [
'0x0000000000000000000000000000000000000000',
'0x6fffd0ae3f7d88c9b4925323f54c6e4b2918c5fd',
'0x12459c951127e0c374ff9105dda097662a027093',
];
validInputs.forEach(input =>
expect(assert.isETHAddressHex.bind(assert, variableName, input)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
false,
{ random: 'test' },
undefined,
new BigNumber(45),
'0x6FFFd0ae3f7d88c9b4925323f54c6e4b2918c5fd',
'0x6FFFd0ae3f7d88c9b4925323f54c6e4',
];
invalidInputs.forEach(input =>
expect(assert.isETHAddressHex.bind(assert, variableName, input)).to.throw(),
);
});
});
describe('#doesBelongToStringEnum', () => {
enum TestEnums {
Test1 = 'Test1',
Test2 = 'Test2',
}
it('should not throw for valid input', () => {
const validInputs = [
TestEnums.Test1,
TestEnums.Test2,
];
validInputs.forEach(input =>
expect(assert.doesBelongToStringEnum.bind(assert, variableName, input, TestEnums)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
false,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input =>
expect(assert.doesBelongToStringEnum.bind(assert, variableName, input, TestEnums)).to.throw(),
);
});
});
describe('#hasAtMostOneUniqueValue', () => {
const errorMsg = 'more than one unique value';
it('should not throw for valid input', () => {
const validInputs = [
['hello'],
['goodbye', 'goodbye', 'goodbye'],
];
validInputs.forEach(input =>
expect(assert.hasAtMostOneUniqueValue.bind(assert, input, errorMsg)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
['hello', 'goodbye'],
['goodbye', 42, false, false],
];
invalidInputs.forEach(input =>
expect(assert.hasAtMostOneUniqueValue.bind(assert, input, errorMsg)).to.throw(),
);
});
});
describe('#isNumber', () => {
it('should not throw for valid input', () => {
const validInputs = [
42,
0.00,
21e+42,
];
validInputs.forEach(input => expect(assert.isNumber.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
false,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input => expect(assert.isNumber.bind(assert, variableName, input)).to.throw());
});
});
describe('#isBoolean', () => {
it('should not throw for valid input', () => {
const validInputs = [
true,
false,
];
validInputs.forEach(input => expect(assert.isBoolean.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input => expect(assert.isBoolean.bind(assert, variableName, input)).to.throw());
});
});
describe('#isWeb3Provider', () => {
it('should not throw for valid input', () => {
const validInputs = [
{ send: () => 45 },
{ sendAsync: () => 45 },
];
validInputs.forEach(input =>
expect(assert.isWeb3Provider.bind(assert, variableName, input)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input =>
expect(assert.isWeb3Provider.bind(assert, variableName, input)).to.throw(),
);
});
});
describe('#doesConformToSchema', () => {
const schema = schemas.addressSchema;
it('should not throw for valid input', () => {
const validInputs = [
'0x6fffd0ae3f7d88c9b4925323f54c6e4b2918c5fd',
'0x12459c951127e0c374ff9105dda097662a027093',
];
validInputs.forEach(input =>
expect(assert.doesConformToSchema.bind(assert, variableName, input, schema)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
{ random: 'test' },
undefined,
new BigNumber(45),
];
invalidInputs.forEach(input =>
expect(assert.doesConformToSchema.bind(assert, variableName, input, schema)).to.throw(),
);
});
});
describe('#isHttpUrl', () => {
it('should not throw for valid input', () => {
const validInputs = [
'http://www.google.com',
'https://api.example-relayer.net',
'https://api.radarrelay.com/0x/v0/',
'https://zeroex.beta.radarrelay.com:8000/0x/v0/',
];
validInputs.forEach(input =>
expect(assert.isHttpUrl.bind(assert, variableName, input)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
{ random: 'test' },
undefined,
new BigNumber(45),
'ws://www.api.example-relayer.net',
'www.google.com',
'api.example-relayer.net',
'user:password@api.example-relayer.net',
'//api.example-relayer.net',
];
invalidInputs.forEach(input =>
expect(assert.isHttpUrl.bind(assert, variableName, input)).to.throw(),
);
});
});
describe('#isUri', () => {
it('should not throw for valid input', () => {
const validInputs = [
'http://www.google.com',
'https://api.example-relayer.net',
'https://api.radarrelay.com/0x/v0/',
'https://zeroex.beta.radarrelay.com:8000/0x/v0/',
'ws://www.api.example-relayer.net',
'wss://www.api.example-relayer.net',
'user:password@api.example-relayer.net',
];
validInputs.forEach(input =>
expect(assert.isUri.bind(assert, variableName, input)).to.not.throw(),
);
});
it('should throw for invalid input', () => {
const invalidInputs = [
42,
{ random: 'test' },
undefined,
new BigNumber(45),
'www.google.com',
'api.example-relayer.net',
'//api.example-relayer.net',
];
invalidInputs.forEach(input =>
expect(assert.isUri.bind(assert, variableName, input)).to.throw(),
);
});
});
describe('#assert', () => {
const assertMessage = 'assert not satisfied';
it('should not throw for valid input', () => {
expect(assert.assert.bind(assert, true, assertMessage)).to.not.throw();
});
it('should throw for invalid input', () => {
expect(assert.assert.bind(assert, false, assertMessage)).to.throw();
});
});
describe('#typeAssertionMessage', () => {
it('should render correct message', () => {
expect(assert.typeAssertionMessage('variable', 'string', 'number'))
.to.equal(`Expected variable to be of type string, encountered: number`);
});
});
});

View File

@@ -1,18 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [ "es2017", "dom"],
"outDir": "lib",
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
"strictNullChecks": true
},
"include": [
"./src/**/*",
"./test/**/*",
"../../node_modules/chai-typescript-typings/index.d.ts",
"../../node_modules/web3-typescript-typings/index.d.ts"
]
}

View File

@@ -1,5 +0,0 @@
{
"extends": [
"tslint-config-0xproject"
]
}