Skip to content

Commit

Permalink
test(form): add test unit
Browse files Browse the repository at this point in the history
  • Loading branch information
cipchk committed May 20, 2018
1 parent 7513505 commit beb6171
Show file tree
Hide file tree
Showing 22 changed files with 702 additions and 131 deletions.
12 changes: 11 additions & 1 deletion packages/form/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ type: Documents
- 可自定义小部件满足业务需求
- 无任何第三方依赖,可适用所有 antd 项目

## 如何使用?
## 如何阅读

在开始之前需要知道文档的一些简单编写规则:

- 代码以 `schema.` 开头的表示 JSON Schema 对象属性
- 代码以 `ui.` 开头的表示 UI 对象属性
- 部分小部件数据源分为 **静态****实时** 两类
- **静态** 理解为 `schema.enum` 值,是符合 JSON Schema 标准,且限数组格式 `any[]`
- **实时** 理解为 `ui.asyncData` 值,非 JSON Schema 标准,格式 `(input?: any) => Observable<SFSchemaEnumType[]>`

## 如何使用

安装 `@delon/form` 依赖包:

Expand Down
100 changes: 93 additions & 7 deletions packages/form/spec/base.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { Component, ViewChild, DebugElement } from '@angular/core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import {
TestBed,
ComponentFixture,
tick,
discardPeriodicTasks,
} from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { deepGet } from '@delon/util';
import { deepGet, deepCopy } from '@delon/util';

import { SFSchema } from '../src/schema';
import { SFUISchema } from '../src/schema/ui';
import { SFButton } from '../src/interface';
import { ErrorData } from '../src/errors';
import { DelonFormModule } from '../src/module';
import { SFComponent } from '../src/sf.component';
import { dispatchFakeEvent, typeInElement } from '../../testing';

export const SCHEMA = {
user: <SFSchema>{
Expand All @@ -28,19 +34,29 @@ export const SCHEMA = {
let fixture: ComponentFixture<TestFormComponent>;
let dl: DebugElement;
let context: TestFormComponent;
export function builder() {
export function builder(options?: {
detectChanges?: boolean;
template?: string;
ingoreAntd?: boolean;
}) {
options = Object.assign({ detectChanges: true }, options);
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, DelonFormModule.forRoot()],
declarations: [TestFormComponent],
});
if (options.template) {
TestBed.overrideTemplate(TestFormComponent, options.template);
}
fixture = TestBed.createComponent(TestFormComponent);
dl = fixture.debugElement;
context = fixture.componentInstance;
spyOn(context, 'formChange');
spyOn(context, 'formSubmit');
spyOn(context, 'formReset');
spyOn(context, 'formError');
fixture.detectChanges();
if (options.detectChanges !== false) {
fixture.detectChanges();
}
const page = new SFPage(context.comp);
return {
fixture,
Expand All @@ -63,8 +79,19 @@ export class SFPage {
return el.nativeElement as HTMLElement;
}

getWidget<T>(cls: string): T {
return this.getDl(cls).componentInstance as T;
}

private fixPath(path: string) {
return path.startsWith('/') ? path : '/' + path;
}

setValue(path: string, value: any): this {
this.comp.rootProperty.searchProperty(path).widget.setValue(value);
path = this.fixPath(path);
const property = this.comp.rootProperty.searchProperty(path);
expect(property).not.toBeNull(`can't found ${path}`);
property.widget.setValue(value);
return this;
}

Expand Down Expand Up @@ -92,15 +119,33 @@ export class SFPage {
this.getEl('.add button').click();
return this;
}
/** 下标从 `1` 开始 */
remove(index = 1): this {
this.getEl(
`.sf-array-container [data-index="${index - 1}"] .remove`,
).click();
return this;
}

newSchema(schema: SFSchema, ui?: SFUISchema): this {
newSchema(schema: SFSchema, ui?: SFUISchema, formData?: any): this {
context.schema = schema;
if (typeof ui !== 'undefined') context.ui = ui;
if (typeof formData !== 'undefined') context.formData = formData;
fixture.detectChanges();
return this;
}

/** 强制指定 `a` 节点 */
chainSchema(schema: SFSchema, overObject: SFSchema): this {
context.schema = Object.assign({}, deepCopy(schema), {
properties: { a: overObject },
});
fixture.detectChanges();
return this;
}

checkSchema(path: string, propertyName: string, value: any): this {
path = this.fixPath(path);
const property = this.comp.rootProperty.searchProperty(path);
expect(property != null).toBe(true);
const item = property.schema;
Expand All @@ -110,6 +155,7 @@ export class SFPage {
}

checkUI(path: string, propertyName: string, value: any): this {
path = this.fixPath(path);
const property = this.comp.rootProperty.searchProperty(path);
expect(property != null).toBe(true);
const item = property.ui;
Expand All @@ -119,6 +165,7 @@ export class SFPage {
}

checkValue(path: string, value: any, propertyName?: string): this {
path = this.fixPath(path);
const property = this.comp.rootProperty.searchProperty(path);
expect(property != null).toBe(true);
if (typeof propertyName !== 'undefined') {
Expand All @@ -130,6 +177,16 @@ export class SFPage {
return this;
}

checkElText(cls: string, value: any): this {
const node = this.getEl(cls);
if (value == null) {
expect(node).toBeNull();
} else {
expect(node.textContent.trim()).toBe(value);
}
return this;
}

checkCls(cls: string, value: string): this {
const el = this.getEl(cls);
expect(el).not.toBe(null);
Expand Down Expand Up @@ -157,6 +214,36 @@ export class SFPage {
expect(dl.queryAll(By.css(cls)).length).toBe(count);
return this;
}

click(cls: string): this {
const el = this.getEl(cls);
expect(el).not.toBeNull();
el.click();
fixture.detectChanges();
return this;
}

typeChar(value: any, cls = 'input'): this {
const node = this.getEl(cls) as HTMLInputElement;
typeInElement(value, node);
tick();
fixture.detectChanges();
return this;
}

typeEvent(eventName: string, cls = 'input'): this {
const node = this.getEl(cls) as HTMLInputElement;
dispatchFakeEvent(node, eventName);
tick();
fixture.detectChanges();
return this;
}

asyncEnd(time = 0) {
tick(time);
discardPeriodicTasks();
return this;
}
}

@Component({
Expand All @@ -165,7 +252,6 @@ export class SFPage {
[schema]="schema"
[ui]="ui"
[formData]="formData"
[mode]="mode"
[button]="button"
[liveValidate]="liveValidate"
[autocomplete]="autocomplete"
Expand Down
123 changes: 80 additions & 43 deletions packages/form/spec/form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ describe('form: component', () => {
let context: TestFormComponent;
let page: SFPage;

beforeEach(() => ({ fixture, dl, context, page } = builder()));

describe('[default]', () => {
beforeEach(() => ({ fixture, dl, context, page } = builder()));

it('should be create a form', () => {
expect(context).not.toBeUndefined();
});
Expand Down Expand Up @@ -69,27 +69,10 @@ describe('form: component', () => {
});

describe('[button]', () => {
beforeEach(() => ({ fixture, dl, context, page } = builder({})));
it('should be has a primary button when default value', () => {
page.checkCount('.sf-btns', 1).checkCount('.ant-btn-primary', 1);
});
it('should be has a fix 100px width', () => {
page
.newSchema({
properties: {
name: {
type: 'string',
ui: {
spanLabelFixed: 100,
},
},
},
})
.checkStyle(
'.sf-btns .ant-form-item-control-wrapper',
'margin-left',
'100px',
);
});
it('should be null', () => {
context.button = null;
fixture.detectChanges();
Expand All @@ -105,9 +88,57 @@ describe('form: component', () => {
fixture.detectChanges();
page.checkCount('.sf-btns', 0);
});
describe('when layout is horizontal', () => {
it('should be has a fix 100px width', () => {
page
.newSchema({
properties: {
name: {
type: 'string',
ui: {
spanLabelFixed: 100,
},
},
},
})
.checkStyle(
'.sf-btns .ant-form-item-control-wrapper',
'margin-left',
'100px',
);
});
it('should be specified grid', () => {
const span = 11;
context.button = {
render: {
grid: { span },
},
};
fixture.detectChanges();
page.checkCls(
'.sf-btns .ant-form-item-control-wrapper',
`ant-col-${span}`,
);
});
it('should be fixed label', () => {
const spanLabelFixed = 56;
context.button = {
render: {
spanLabelFixed,
},
};
fixture.detectChanges();
page.checkStyle(
'.sf-btns .ant-form-item-control-wrapper',
'margin-left',
`${spanLabelFixed}px`,
);
});
});
});

describe('properites', () => {
beforeEach(() => ({ fixture, dl, context, page } = builder({})));
describe('#validate', () => {
it('should be validate when submitted and not liveValidate', () => {
page.submit(false);
Expand Down Expand Up @@ -170,17 +201,20 @@ describe('form: component', () => {
})
.checkStyle('.ant-form-item-label', 'width', '100px');
});
it('shoule be fixed label width if parent node had setting', () => {
it('should inherit parent node', () => {
page
.newSchema({
properties: {
name: { type: 'string' },
},
ui: {
spanLabelFixed: 99,
address: {
type: 'object',
ui: { spanLabelFixed: 98 },
properties: {
city: { type: 'string' },
},
},
},
})
.checkStyle('.ant-form-item-label', 'width', '99px');
.checkStyle('.ant-form-item-label', 'width', '98px');
});
});
});
Expand Down Expand Up @@ -208,23 +242,6 @@ describe('form: component', () => {
});
});

describe('#mode', () => {
it('with search', () => {
context.mode = 'search';
fixture.detectChanges();
expect(context.comp.layout).toBe('inline');
expect(context.comp.firstVisual).toBe(false);
expect(context.comp.liveValidate).toBe(false);
});
it('with edit', () => {
context.mode = 'edit';
fixture.detectChanges();
expect(context.comp.layout).toBe('horizontal');
expect(context.comp.firstVisual).toBe(false);
expect(context.comp.liveValidate).toBe(true);
});
});

it('#formChange', () => {
page.setValue('/name', 'cipchk');
expect(context.formChange).toHaveBeenCalled();
Expand Down Expand Up @@ -253,6 +270,7 @@ describe('form: component', () => {
});

describe('[widgets]', () => {
beforeEach(() => ({ fixture, dl, context, page } = builder({})));
it('#size', () => {
page
.newSchema({
Expand All @@ -273,4 +291,23 @@ describe('form: component', () => {
.checkCls('sf-string', 'test-cls');
});
});

describe('#mode', () => {
beforeEach(() => {
({ fixture, dl, context, page } = builder({
detectChanges: false,
template: `<sf [layout]="layout" #comp [schema]="schema" [ui]="ui" [button]="button" [mode]="mode"></sf>`,
}));
});
it('should be auto 搜索 in submit', () => {
context.mode = 'search';
fixture.detectChanges();
expect(page.getEl('.ant-btn-primary').textContent).toBe('搜索');
});
it('should be auto 保存 in submit', () => {
context.mode = 'edit';
fixture.detectChanges();
expect(page.getEl('.ant-btn-primary').textContent).toBe('保存');
});
});
});
2 changes: 1 addition & 1 deletion packages/form/spec/schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ describe('form: schema', () => {
b: { type: 'string' }
},
ui: {
order: ['a', '*', '*'],
order: ['a', '*', '*', '*', '*'],
},
});
}).toThrow();
Expand Down
Loading

0 comments on commit beb6171

Please sign in to comment.