UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

399 lines (321 loc) 15.4 kB
import { Component, ViewChild } from '@angular/core'; import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { UntypedFormBuilder, FormsModule, ReactiveFormsModule, Validators, NgForm } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { IgxSwitchComponent } from './switch.component'; import { configureTestSuite } from '../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('IgxSwitch', () => { configureTestSuite(); beforeAll(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, InitSwitchComponent, SwitchSimpleComponent, SwitchRequiredComponent, SwitchExternalLabelComponent, SwitchInvisibleLabelComponent, SwitchFormComponent, SwitchFormGroupComponent, IgxSwitchComponent ] }).compileComponents(); })); it('Initializes', () => { const fixture = TestBed.createComponent(InitSwitchComponent); fixture.detectChanges(); const switchComp = fixture.componentInstance.switch; const domSwitch = fixture.debugElement.query(By.css('igx-switch')).nativeElement; const nativeCheckbox = switchComp.nativeCheckbox.nativeElement; const nativeLabel = switchComp.nativeLabel.nativeElement; const placeholderLabel = fixture.debugElement.query(By.css('.igx-switch__label')).nativeElement; expect(domSwitch.id).toContain('igx-switch-'); expect(nativeCheckbox).toBeTruthy(); expect(nativeCheckbox.id).toContain('igx-switch-'); expect(nativeCheckbox.getAttribute('aria-label')).toEqual(null); expect(nativeCheckbox.getAttribute('aria-labelledby')).toContain('igx-switch-'); expect(nativeLabel).toBeTruthy(); // No longer have a for attribute to not propagate clicks to the native checkbox // expect(nativeLabel.getAttribute('for')).toEqual('igx-switch-0-input'); expect(placeholderLabel.textContent.trim()).toEqual('Init'); expect(placeholderLabel.classList).toContain('igx-switch__label'); expect(placeholderLabel.getAttribute('id')).toContain('igx-switch-'); switchComp.id = 'customSwitch'; fixture.detectChanges(); expect(switchComp.id).toBe('customSwitch'); expect(domSwitch.id).toBe('customSwitch'); // When aria-label is present, aria-labeledby shouldn't be switchComp.ariaLabel = 'New Label'; fixture.detectChanges(); expect(nativeCheckbox.getAttribute('aria-labelledby')).toEqual(null); expect(nativeCheckbox.getAttribute('aria-label')).toMatch('New Label'); }); it('Initializes with ngModel', () => { const fixture = TestBed.createComponent(SwitchSimpleComponent); fixture.detectChanges(); const testInstance = fixture.componentInstance; const switchInstance = testInstance.switch; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement; fixture.detectChanges(); expect(nativeCheckbox.checked).toBe(false); expect(switchInstance.checked).toBe(null); testInstance.subscribed = true; switchInstance.name = 'my-switch'; fixture.detectChanges(); expect(nativeCheckbox.checked).toBe(true); expect(switchInstance.checked).toBe(true); expect(switchInstance.name).toEqual('my-switch'); }); it('Initializes with form group', () => { const fixture = TestBed.createComponent(SwitchFormGroupComponent); fixture.detectChanges(); const testInstance = fixture.componentInstance; const switchInstance = testInstance.switch; const form = testInstance.myForm; form.setValue({ switch: true }); expect(switchInstance.checked).toBe(true); form.reset(); expect(switchInstance.checked).toBe(null); }); it('Initializes with external label', () => { const fixture = TestBed.createComponent(SwitchExternalLabelComponent); const switchInstance = fixture.componentInstance.switch; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement; const externalLabel = fixture.debugElement.query(By.css('#my-label')).nativeElement; fixture.detectChanges(); expect(nativeCheckbox.getAttribute('aria-labelledby')).toMatch(externalLabel.getAttribute('id')); expect(externalLabel.textContent).toMatch(fixture.componentInstance.label); }); it('Initializes with invisible label', () => { const fixture = TestBed.createComponent(SwitchInvisibleLabelComponent); const switchInstance = fixture.componentInstance.switch; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement; fixture.detectChanges(); expect(nativeCheckbox.getAttribute('aria-label')).toMatch(fixture.componentInstance.label); }); it('Positions label before and after switch', () => { const fixture = TestBed.createComponent(SwitchSimpleComponent); const switchInstance = fixture.componentInstance.switch; const placeholderLabel = switchInstance.placeholderLabel.nativeElement; const labelStyles = window.getComputedStyle(placeholderLabel); fixture.detectChanges(); expect(labelStyles.order).toEqual('0'); switchInstance.labelPosition = 'before'; fixture.detectChanges(); expect(labelStyles.order).toEqual('-1'); }); it('Required state', () => { const fixture = TestBed.createComponent(SwitchRequiredComponent); const testInstance = fixture.componentInstance; const switchInstance = testInstance.switch; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement; fixture.detectChanges(); expect(switchInstance.required).toBe(true); expect(nativeCheckbox.required).toBeTruthy(); switchInstance.required = false; nativeCheckbox.required = false; fixture.detectChanges(); expect(switchInstance.required).toBe(false); expect(nativeCheckbox.required).toBe(false); }); it('Disabled state', () => { const fixture = TestBed.createComponent(IgxSwitchComponent); const switchInstance = fixture.componentInstance; switchInstance.disabled = true; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement as HTMLInputElement; const nativeLabel = switchInstance.nativeLabel.nativeElement; const placeholderLabel = switchInstance.placeholderLabel.nativeElement; fixture.detectChanges(); expect(switchInstance.disabled).toBe(true); expect(nativeCheckbox.disabled).toBe(true); nativeCheckbox.click(); nativeLabel.click(); placeholderLabel.click(); fixture.detectChanges(); // Should not update expect(switchInstance.checked).toBe(false); }); it('Event handling', () => { const fixture = TestBed.createComponent(SwitchSimpleComponent); const testInstance = fixture.componentInstance; const switchInstance = testInstance.switch; const nativeCheckbox = switchInstance.nativeCheckbox.nativeElement; const nativeLabel = switchInstance.nativeLabel.nativeElement; const placeholderLabel = switchInstance.placeholderLabel.nativeElement; const switchEl = fixture.debugElement.query(By.directive(IgxSwitchComponent)).nativeElement; fixture.detectChanges(); expect(switchInstance.focused).toBe(false); switchEl.dispatchEvent(new KeyboardEvent('keyup')); fixture.detectChanges(); expect(switchInstance.focused).toBe(true); nativeCheckbox.dispatchEvent(new Event('blur')); fixture.detectChanges(); expect(switchInstance.focused).toBe(false); nativeLabel.click(); fixture.detectChanges(); expect(testInstance.changeEventCalled).toBe(true); expect(testInstance.subscribed).toBe(true); expect(testInstance.clickCounter).toEqual(1); placeholderLabel.click(); fixture.detectChanges(); expect(testInstance.changeEventCalled).toBe(true); expect(testInstance.subscribed).toBe(false); expect(testInstance.clickCounter).toEqual(2); }); it('Should update style when required switch\'s value is set.', () => { const fixture = TestBed.createComponent(SwitchRequiredComponent); fixture.detectChanges(); const switchInstance = fixture.componentInstance.switch; const domSwitch = fixture.debugElement.query(By.css('igx-switch')).nativeElement; expect(domSwitch.classList.contains('igx-switch--invalid')).toBe(false); expect(switchInstance.invalid).toBe(false); expect(switchInstance.checked).toBe(false); expect(switchInstance.required).toBe(true); dispatchCbEvent('keyup', domSwitch, fixture); expect(domSwitch.classList.contains('igx-switch--focused')).toBe(true); dispatchCbEvent('blur', domSwitch, fixture); expect(switchInstance.invalid).toBe(true); expect(domSwitch.classList.contains('igx-switch--invalid')).toBe(true); dispatchCbEvent('keyup', domSwitch, fixture); expect(domSwitch.classList.contains('igx-switch--focused')).toBe(true); dispatchCbEvent('click', domSwitch, fixture); expect(domSwitch.classList.contains('igx-switch--checked')).toBe(true); expect(switchInstance.checked).toBe(true); expect(switchInstance.invalid).toBe(false); expect(domSwitch.classList.contains('igx-switch--invalid')).toBe(false); dispatchCbEvent('click', domSwitch, fixture); dispatchCbEvent('keyup', domSwitch, fixture); expect(domSwitch.classList.contains('igx-switch--focused')).toBe(true); dispatchCbEvent('blur', domSwitch, fixture); expect(switchInstance.checked).toBe(false); expect(switchInstance.invalid).toBe(true); expect(domSwitch.classList.contains('igx-switch--invalid')).toBe(true); }); it('Should work properly with ngModel', fakeAsync(() => { const fixture = TestBed.createComponent(SwitchFormComponent); fixture.detectChanges(); tick(); const switchEl = fixture.componentInstance.switch; expect(switchEl.invalid).toEqual(false); switchEl.onBlur(); expect(switchEl.invalid).toEqual(true); fixture.componentInstance.ngForm.resetForm(); tick(); expect(switchEl.invalid).toEqual(false); })); it('Should work properly with reactive forms validation.', () => { const fixture = TestBed.createComponent(SwitchFormGroupComponent); fixture.detectChanges(); const switchEl = fixture.componentInstance.switch; const switchNative = fixture.debugElement.query(By.directive(IgxSwitchComponent)).nativeElement; expect(switchEl.required).toBe(true); expect(switchEl.invalid).toBe(false); expect(switchNative.classList.contains('igx-switch--invalid')).toBe(false); expect(switchEl.nativeElement.getAttribute('aria-required')).toEqual('true'); expect(switchEl.nativeElement.getAttribute('aria-invalid')).toEqual('false'); dispatchCbEvent('keyup', switchNative, fixture); expect(switchEl.focused).toBe(true); dispatchCbEvent('blur', switchNative, fixture); expect(switchNative.classList.contains('igx-switch--invalid')).toBe(true); expect(switchEl.invalid).toBe(true); expect(switchEl.nativeElement.getAttribute('aria-invalid')).toEqual('true'); switchEl.checked = true; fixture.detectChanges(); expect(switchNative.classList.contains('igx-switch--invalid')).toBe(false); expect(switchEl.invalid).toBe(false); expect(switchEl.nativeElement.getAttribute('aria-invalid')).toEqual('false'); }); describe('EditorProvider', () => { it('Should return correct edit element', () => { const fixture = TestBed.createComponent(SwitchSimpleComponent); fixture.detectChanges(); const instance = fixture.componentInstance.switch; const editElement = fixture.debugElement.query(By.css('.igx-switch__input')).nativeElement; expect(instance.getEditElement()).toBe(editElement); }); }); }); @Component({ template: `<igx-switch #switch>Init</igx-switch>`, standalone: true, imports: [IgxSwitchComponent] }) class InitSwitchComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; } @Component({ template: `<igx-switch #switch (change)="onChange()" (click)="onClick()" [(ngModel)]="subscribed" [checked]="subscribed">Simple</igx-switch>`, standalone: true, imports: [FormsModule, IgxSwitchComponent] }) class SwitchSimpleComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; public changeEventCalled = false; public subscribed = false; public clickCounter = 0; public onChange() { this.changeEventCalled = true; } public onClick() { this.clickCounter++; } } @Component({ template: `<igx-switch #switch required>Required</igx-switch>`, standalone: true, imports: [IgxSwitchComponent] }) class SwitchRequiredComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; } @Component({ template: `<p id="my-label">{{label}}</p> <igx-switch #switch aria-labelledby="my-label"></igx-switch>`, standalone: true, imports: [IgxSwitchComponent] }) class SwitchExternalLabelComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; public label = 'My Label'; } @Component({ template: `<igx-switch #switch [aria-label]="label"></igx-switch>`, standalone: true, imports: [IgxSwitchComponent] }) class SwitchInvisibleLabelComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; public label = 'Invisible Label'; } @Component({ template: `<form [formGroup]="myForm"><igx-switch #switch formControlName="switch">Form Group</igx-switch></form>`, standalone: true, imports: [ReactiveFormsModule, IgxSwitchComponent] }) class SwitchFormGroupComponent { @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; public myForm = this.fb.group({ switch: ['', Validators.required] }); constructor(private fb: UntypedFormBuilder) {} } @Component({ template: ` <form #form="ngForm"> <igx-switch #switch [(ngModel)]="subscribed" name="switch" required>Switch</igx-switch> </form> `, standalone: true, imports: [FormsModule, IgxSwitchComponent] }) class SwitchFormComponent { @ViewChild('switch', { read: IgxSwitchComponent, static: true }) public switch: IgxSwitchComponent; @ViewChild(NgForm, { static: true }) public ngForm: NgForm; public subscribed: string; } const dispatchCbEvent = (eventName, switchNativeElement, fixture) => { switchNativeElement.dispatchEvent(new Event(eventName)); fixture.detectChanges(); };