Skip to content

Commit

Permalink
Added unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
przemyslaw-zan committed Feb 3, 2023
1 parent 8a51101 commit af616aa
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 15 deletions.
9 changes: 4 additions & 5 deletions src/app/demo-form/demo-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,18 @@ <h3>User profile form</h3>
<p *ngIf="description && description.touched" class="alert">Description has been "touched".</p>

<p>
<button type="button" (click)="toggleDisableTwoWayDataBinding()">{{ shouldDisableTwoWayDataBinding ? 'Enable' : 'Disable' }} two-way data binding</button>
<em>Two-way data binding is {{ shouldDisableTwoWayDataBinding ? 'disabled' : 'enabled' }}.</em>
<button type="button" id="toggleBinding" (click)="toggleDisableTwoWayDataBinding()">{{ shouldDisableTwoWayDataBinding ? 'Enable' : 'Disable' }} two-way data binding</button>
&nbsp;<em>Two-way data binding is {{ shouldDisableTwoWayDataBinding ? 'disabled' : 'enabled' }}.</em>
</p>
<p>
<button type="reset" (click)="reset()">Reset form</button>
</p>
<p>
<button type="submit">Submit this form</button> <em>(Open the console first)</em>
<button type="submit">Submit this form</button>
&nbsp;<em>(Open the console first)</em>
</p>
</form>



<h3>Editor data preview (readable and writable)</h3>
<p>
Note that it's only a prove of concept of using the `ngModel`.
Expand Down
26 changes: 26 additions & 0 deletions src/app/demo-form/demo-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,30 @@ describe( 'DemoFormComponent', () => {
done();
} );
} );

it( 'should assign editor data to the model description if two way binding is disabled', done => {
setTimeout( () => {
const spy = spyOn( console, 'log' );

const toggleButton: HTMLButtonElement = fixture.debugElement.query( By.css( '#toggleBinding' ) ).nativeElement;
const submitButton: HTMLButtonElement = fixture.debugElement.query( By.css( 'button[type=submit]' ) ).nativeElement;
const editorDataPreview: HTMLTextAreaElement = fixture.debugElement.query( By.css( 'textarea' ) ).nativeElement;

toggleButton.click();
component.editorInstance.setData( '<p>Foo bar baz.</p>' );
submitButton.click();

expect( editorDataPreview.value ).toEqual( '<p>A <b>really</b> nice fellow.</p>' );

expect( spy ).toHaveBeenCalledTimes( 1 );
expect( spy.calls.first().args[ 0 ] ).toEqual( 'Form submit, model' );
expect( spy.calls.first().args[ 1 ] ).toEqual( {
name: 'John',
surname: 'Doe',
description: '<p>Foo bar baz.</p>'
} );

done();
} );
} );
} );
3 changes: 2 additions & 1 deletion src/app/demo-form/demo-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ export class DemoFormComponent implements AfterViewInit {
surname: 'Doe',
description: '<p>A <b>really</b> nice fellow.</p>'
};

public formDataPreview?: string;
public shouldDisableTwoWayDataBinding = false;

protected editorInstance: typeof ClassicEditor;
public editorInstance: typeof ClassicEditor;

public get description(): AbstractControl {
return this.demoForm!.controls.description;
Expand Down
15 changes: 13 additions & 2 deletions src/app/demo-reactive-form/demo-reactive-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,27 @@ <h3>User profile form</h3>
<label for="description">Description</label>
<ckeditor
formControlName="description"
[disableTwoWayDataBinding]="shouldDisableTwoWayDataBinding"
[editor]="Editor"
(ready)="onReady($event)"
id="description"
name="description">
</ckeditor>

<p *ngIf="description && description.dirty" class="alert">Description is "dirty".</p>
<p *ngIf="description && description.touched" class="alert">Description has been "touched".</p>

<p><button type="reset" (click)="reset()">Reset form</button></p>
<p><button type="submit">Submit this form</button> <em>(Open the console first)</em></p>
<p>
<button type="button" id="toggleBinding" (click)="toggleDisableTwoWayDataBinding()">{{ shouldDisableTwoWayDataBinding ? 'Enable' : 'Disable' }} two-way data binding</button>
&nbsp;<em>Two-way data binding is {{ shouldDisableTwoWayDataBinding ? 'disabled' : 'enabled' }}.</em>
</p>
<p>
<button type="reset" (click)="reset()">Reset form</button>
</p>
<p>
<button type="submit">Submit this form</button>
&nbsp;<em>(Open the console first)</em>
</p>
</form>

<h3>Editor data preview (readable)</h3>
Expand Down
26 changes: 26 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,30 @@ describe( 'DemoReactiveFormComponent', () => {
done();
} );
} );

it( 'should assign editor data to the model description if two way binding is disabled', done => {
setTimeout( () => {
const spy = spyOn( console, 'log' );

const toggleButton: HTMLButtonElement = fixture.debugElement.query( By.css( '#toggleBinding' ) ).nativeElement;
const submitButton: HTMLButtonElement = fixture.debugElement.query( By.css( 'button[type=submit]' ) ).nativeElement;
const editorDataPreview: HTMLTextAreaElement = fixture.debugElement.query( By.css( 'textarea' ) ).nativeElement;

toggleButton.click();
component.editorInstance.setData( '<p>Foo bar baz.</p>' );
submitButton.click();

expect( editorDataPreview.value ).toEqual( '<p>A <b>really</b> nice fellow.</p>' );

expect( spy ).toHaveBeenCalledTimes( 1 );
expect( spy.calls.first().args[ 0 ] ).toEqual( 'Form submit, model' );
expect( spy.calls.first().args[ 1 ] ).toEqual( {
name: 'John',
surname: 'Doe',
description: '<p>Foo bar baz.</p>'
} );

done();
} );
} );
} );
16 changes: 16 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ export class DemoReactiveFormComponent implements AfterViewInit {
} );

public formDataPreview?: string;
public shouldDisableTwoWayDataBinding = false;

public editorInstance: typeof ClassicEditor;

public toggleDisableTwoWayDataBinding(): void {
this.shouldDisableTwoWayDataBinding = !this.shouldDisableTwoWayDataBinding;
}

public ngAfterViewInit(): void {
this.demoReactiveForm!.valueChanges
Expand All @@ -34,7 +41,16 @@ export class DemoReactiveFormComponent implements AfterViewInit {
} );
}

public onReady( editor: typeof ClassicEditor ): void {
this.editorInstance = editor;
}

public onSubmit(): void {
// Read editor's data only when two-way data binding is disabled
if ( this.shouldDisableTwoWayDataBinding ) {
this.demoReactiveForm.value.description = this.editorInstance.getData();
}

console.log( 'Form submit, model', this.demoReactiveForm.value );
}

Expand Down
25 changes: 20 additions & 5 deletions src/ckeditor/ckeditor.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe( 'CKEditorComponent', () => {
expect( console.warn ).toHaveBeenCalledWith( 'The <CKEditor> component requires using CKEditor 5 in version 34 or higher.' );
} );

it( 'should not print any warninig if using CKEditor 5 in version 34 or higher', () => {
it( 'should not print any warning if using CKEditor 5 in version 34 or higher', () => {
window.CKEDITOR_VERSION = '34.0.0';

fixture = TestBed.createComponent( CKEditorComponent );
Expand Down Expand Up @@ -220,9 +220,8 @@ describe( 'CKEditorComponent', () => {

it( 'change - should not calculate editor data when the control value ancestor is not specified', () => {
fixture.detectChanges();

const changeSpy = jasmine.createSpy();
component.change.subscribe( changeSpy );
const spy = jasmine.createSpy();
component.change.subscribe( spy );

return waitCycle().then( () => {
spyOn( component.editorInstance!, 'getData' ).and.callThrough();
Expand All @@ -232,7 +231,23 @@ describe( 'CKEditorComponent', () => {
component.editorInstance!.execute( 'input', { text: 'foo' } );

expect( component.editorInstance!.getData ).toHaveBeenCalledTimes( 0 );
expect( changeSpy ).toHaveBeenCalledTimes( 3 );
expect( spy ).toHaveBeenCalledTimes( 3 );
} );
} );

it( 'change - should not calculate editor data when the two way data binding is disabled', () => {
component.disableTwoWayDataBinding = true;

fixture.detectChanges();
const spy = jasmine.createSpy();
component.change.subscribe( spy );

return waitCycle().then( () => {
spyOn( component.editorInstance!, 'getData' ).and.callThrough();

component.editorInstance!.execute( 'input', { text: 'foo' } );

expect( spy ).toHaveBeenCalledTimes( 0 );
} );
} );

Expand Down
5 changes: 3 additions & 2 deletions src/ckeditor/ckeditor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ export class CKEditorComponent implements AfterViewInit, OnDestroy, ControlValue
@Input() public watchdog?: CKEditor5.ContextWatchdog;

/**
* Allows disabling the two-way data binding mechanism. It can boosts performance for large documents if set to `true`.
* Allows disabling the two-way data binding mechanism. Disabling it can boost performance for large documents.
*
* When a component is connected using the [(ngModel)] or [formControl] directives then all data will be never synchronized.
* When a component is connected using the [(ngModel)] or [formControl] directives and this value is set to true then none of the data
* will ever be synchronized.
*
* An integrator must call `editor.getData()` manually once the application needs the editor's data.
* An editor instance can be received in the `ready()` callback.
Expand Down

0 comments on commit af616aa

Please sign in to comment.