Commit 38736642 authored by nanahira's avatar nanahira

unit test and remove deprecated things

parent 2e67ff05
Pipeline #7356 failed with stages
in 1 minute and 30 seconds
......@@ -2,4 +2,4 @@ webpack.config.js
dist/*
build/*
*.js
/src/schemastery
\ No newline at end of file
/src/schemastery
stages:
- install
- build
- deploy
variables:
GIT_DEPTH: "1"
build:
stage: build
npm_ci:
stage: install
tags:
- linux
script:
- npm ci
artifacts:
paths:
- node_modules
.build_base:
stage: build
tags:
- linux
dependencies:
- npm_ci
build:
extends:
- .build_base
script:
- npm run build
artifacts:
paths:
- dist/
unit-test:
extends:
- .build_base
script:
- npm run test
deploy_npm:
stage: deploy
dependencies:
......
......@@ -16,7 +16,7 @@ The decorator `@RegisterSchema` for class is used to register schema from a clas
// Don't forget this decorator.
@RegisterSchema({
desc: 'my desc',
description: 'my desc',
})
export class Config {
// add this constructor to make sure the class has one parameter on constructor
......@@ -41,7 +41,7 @@ export class Config {
ant: string[];
// You may also specify schema manually.
@DefineSchema({ schema: Schema.string() })
@DefineSchema({ type: Schema.string() })
dream: string;
// Nested schema.
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
"scripts": {
"lint": "eslint --fix .",
"build": "rm -rf dist && tsc",
"test": "jest --passWithNoTests",
"start": "node dist/index.js"
},
"repository": {
......@@ -21,6 +22,7 @@
},
"homepage": "https://code.mycard.moe/3rdeye/schemastery-gen",
"devDependencies": {
"@types/jest": "^27.0.3",
"@types/lodash": "^4.14.176",
"@types/node": "^16.11.9",
"@typescript-eslint/eslint-plugin": "^4.33.0",
......@@ -28,8 +30,10 @@
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"jest": "^27.4.3",
"prettier": "^2.4.1",
"schemastery": "^2.1.0",
"ts-jest": "^27.0.7",
"typescript": "^4.5.2"
},
"peerDependencies": {
......@@ -39,5 +43,22 @@
"lodash": "^4.17.21",
"reflect-metadata": "^0.1.13",
"typed-reflector": "^1.0.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "tests",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
......@@ -21,7 +21,7 @@ export function SchemaProperty(options: SchemaOptions = {}): PropertyDecorator {
options.type = 'any';
}
}
const typeInSchema = options.schema?.type;
const typeInSchema = (options.type as Schema)?.type;
if (
nativeType === Array &&
options.array !== false &&
......
......@@ -33,21 +33,17 @@ function getBasePropertySchemaFromOptions(options: SchemaOptions) {
}
function applyOptionsToSchema(schema: Schema, options: SchemaClassOptions) {
if (options.desc) {
schema.meta.description = options.desc;
}
Object.assign(schema.meta, options);
}
function getPropertySchemaFromOptions<PT>(options: SchemaOptions): Schema<PT> {
let schema = getBasePropertySchemaFromOptions(options);
if (options.dict) {
const skeySchema = (options.dict === true
? Schema.string()
: ((Schema.from(options.dict) as unknown) as Schema<
any,
string
>)) as Schema<any, string>;
const skeySchema = (
options.dict === true
? Schema.string()
: (Schema.from(options.dict) as unknown as Schema<any, string>)
) as Schema<any, string>;
schema = Schema.dict(schema, skeySchema).default({});
}
if (options.array) {
......@@ -140,11 +136,11 @@ function applySchemaForClass<T>(
export function SchemaClass<T>(originalClass: ClassType<T>) {
const schema = schemaFromClass(originalClass);
const newClass = (function (...args: any[]): T {
const newClass = function (...args: any[]): T {
const instance = new originalClass(...args);
const originalObject = args[0];
return applySchemaForClass(originalClass, instance, originalObject);
} as unknown) as ClassType<T> & Schema<Partial<T>, T>;
} as unknown as ClassType<T> & Schema<Partial<T>, T>;
Object.defineProperty(newClass, 'name', {
value: originalClass.name,
});
......
......@@ -23,10 +23,7 @@ export type SchemaSource =
export type SchemaType = SchemaNativeType | SchemaSource;
export interface SchemaClassOptions extends Schema.Meta<any> {
desc?: string;
allowUnknown?: boolean; // for backward compatibility
}
export type SchemaClassOptions = Schema.Meta<any>;
export interface SchemaOptions extends SchemaClassOptions {
schema?: Schema<any>;
......
import { RegisterSchema, SchemaProperty } from '../src/decorators';
import Schema from 'schemastery';
describe('Circular schema', () => {
@RegisterSchema()
class MyProperty {
@SchemaProperty({ default: 'bar' })
foo: string;
getFoo() {
return this.foo;
}
}
@RegisterSchema()
class MyConfig {
constructor(_: any) {}
@SchemaProperty({ type: MyProperty })
myProperty: MyProperty;
}
it('Should be object type', () => {
const schema = MyConfig as Schema<MyConfig>;
expect(schema.type).toBe('object');
expect(schema.dict.myProperty.type).toBe('object');
});
it('Should be instance', () => {
const config = new MyConfig({ myProperty: {} });
expect(config.myProperty.foo).toBe('bar');
expect(config.myProperty.getFoo()).toBe('bar');
});
it('Should throw if invalid', () => {
expect(() => new MyConfig({ myProperty: 'boo' })).toThrow();
});
});
import { RegisterSchema, SchemaProperty } from '../src/decorators';
describe('schema of class extend', () => {
class MyConfigBase {
@SchemaProperty({ default: 'bar' })
foo: string;
}
@RegisterSchema()
class MyConfig extends MyConfigBase {
constructor(_: any) {
super();
}
@SchemaProperty({ default: 'baz' })
bar: string;
}
it('should have foo and bar', () => {
const config = new MyConfig({});
expect(config.foo).toBe('bar');
expect(config.bar).toBe('baz');
});
});
import { kSchema } from '../src/utility/kschema';
describe('Testing of kSchema', () => {
it('kSchema should be a symbol', () => {
expect(typeof kSchema).toEqual('symbol');
});
});
import { RegisterSchema, SchemaProperty } from '../src/decorators';
import { kSchema } from '../src/utility/kschema';
import Schema from 'schemastery';
describe('Schema registration', () => {
@RegisterSchema()
class Config {
constructor(_config: any) {}
@SchemaProperty({ default: 'bar' })
foo: string;
}
@RegisterSchema()
class ConfigWithRequiredFields {
constructor(_config: any) {}
@SchemaProperty({ required: true })
foo: string;
}
it('should be a schema', () => {
expect(Config[kSchema]).toBeDefined();
});
it('should be schema object type', () => {
const schema = Config as Schema<Config>;
expect(schema.type).toBe('object');
expect(schema.dict.foo.type).toBe('string');
});
it('should put default value', () => {
expect(new Config({}).foo).toBe('bar');
expect(new Config({ foo: 'baz' }).foo).toBe('baz');
});
it('should throw if no default value', () => {
expect(() => new Config({ foo: 111 })).toThrow();
});
it('should throw if required field is missing', () => {
expect(() => new ConfigWithRequiredFields({})).toThrow();
});
});
import { RegisterSchema, SchemaProperty } from '../src/decorators';
import Schema from 'schemastery';
describe('Schema arrays', () => {
@RegisterSchema()
class MyProperty {
@SchemaProperty({ default: 'default' })
name: string;
getName() {
return this.name;
}
}
@RegisterSchema()
class MyConfig {
constructor(_: any) {}
@SchemaProperty({ type: Schema.array(Schema.string()) })
foo: string[];
@SchemaProperty({ type: Number })
bar: number[];
@SchemaProperty({ type: MyProperty })
myProperties: MyProperty[];
@SchemaProperty()
notArray: string;
@SchemaProperty({ type: Schema.tuple([Number, String]) })
myTup: [number, string];
@SchemaProperty({ type: Schema.tuple([Number, String]), array: true })
myTupArr: [number, string][];
}
const schema = MyConfig as Schema<MyConfig>;
it('should be correct type', () => {
expect(schema.dict.foo.type).toEqual('array');
expect(schema.dict.bar.type).toEqual('array');
expect(schema.dict.myProperties.type).toEqual('array');
expect(schema.dict.notArray.type).toEqual('string');
expect(schema.dict.myTup.type).toEqual('tuple');
expect(schema.dict.myTupArr.type).toEqual('array');
});
it('should be instance of property', () => {
const config = new MyConfig({ myProperties: [{ name: 'foo' }] });
expect(config.myProperties[0].getName()).toEqual('foo');
});
});
import { RegisterSchema, SchemaProperty } from '../src/decorators';
import Schema from 'schemastery';
describe('Schema dict', () => {
@RegisterSchema()
class MyProperty {
@SchemaProperty({ default: 'default' })
name: string;
getName() {
return this.name;
}
}
interface FooAndBar {
foo: number;
bar: number;
}
const sym = Symbol();
@RegisterSchema()
class MyConfig {
constructor(_: any) {}
@SchemaProperty({ type: String, dict: true })
foo: Record<string, string>;
@SchemaProperty({ type: Number, dict: Schema.union(['foo', 'bar']) })
fooAndBar: FooAndBar;
@SchemaProperty({ dict: true, type: MyProperty, default: {} })
myProperties: Record<string, MyProperty>;
@SchemaProperty({ dict: true, type: MyProperty, default: {} })
myPropertiesArr: Record<string, MyProperty>[];
}
const schema = MyConfig as Schema<MyConfig>;
it('should be correct type', () => {
expect(schema.dict.foo.type).toEqual('dict');
expect(schema.dict.fooAndBar.type).toEqual('dict');
expect(schema.dict.myProperties.type).toEqual('dict');
expect(schema.dict.myPropertiesArr.type).toEqual('array');
});
it('should check dict', () => {
const config = new MyConfig({
foo: {
bar: 'baz',
},
fooAndBar: {
foo: 1,
bar: 2,
},
});
expect(config.foo).toEqual({ bar: 'baz' });
expect(config.fooAndBar).toEqual({ foo: 1, bar: 2 });
});
it('should throw on invalid', () => {
expect(() => new MyConfig({ foo: 1 })).toThrow();
expect(() => new MyConfig({ foo: { bar: 1 } })).toThrow();
expect(() => new MyConfig({ [sym]: { bar: 'baz' } })).toThrow();
expect(() => new MyConfig({ fooAndBar: { foo: 'not number' } })).toThrow();
expect(() => new MyConfig({ fooAndBar: { somethingElse: 4 } })).toThrow();
});
it('should be instance of MyProperty', () => {
const config = new MyConfig({
myProperties: {
foo: {
name: 'foo',
},
},
myPropertiesArr: [
{
bar: {
name: 'bar',
},
},
],
});
expect(config.myProperties.foo.getName()).toEqual('foo');
expect(config.myPropertiesArr[0].bar.getName()).toEqual('bar');
});
});
......@@ -10,14 +10,11 @@
"sourceMap": true
},
"compileOnSave": true,
"allowJs": true,
"include": [
"./src/**/*.ts",
"./test/**/*.ts",
"./index.ts",
"!*.d.ts"
],
"exclude": [
"node_modules",
"dist"
"*.ts",
"src/**/*.ts",
"test/**/*.ts",
"tests/**/*.ts"
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment