Skip to content

Commit

Permalink
fix: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
danielleroux committed Feb 13, 2025
1 parent 94cd3f3 commit f60cbde
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 12 deletions.
33 changes: 33 additions & 0 deletions packages/angular-test-app/src/test/input/form-ix-input-required.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2025 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import { FormControl, FormGroup, Validators } from '@angular/forms';

import { Component } from '@angular/core';

@Component({
selector: 'test-input-form-required',
template: `
<form class="form-validation-example" [formGroup]="form">
<ix-input
label="Name:"
helperText="Write down your name"
invalidText="Value is required"
formControlName="name"
required
>
</ix-input>
</form>
`,
})
export class TestInputFormRequired {
public form = new FormGroup({
name: new FormControl('', Validators.compose([Validators.required])),
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2025 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import { FormControl, FormGroup, Validators } from '@angular/forms';

import { Component } from '@angular/core';

@Component({
selector: 'test-input-form-with-validators',
template: `
<form [formGroup]="form">
<ix-input formControlName="name" [required]="true"> </ix-input>
</form>
`,
})
export class TestInputFormWithValidators {
public form = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(4)]),
});
}
130 changes: 130 additions & 0 deletions packages/angular-test-app/src/test/input/input-required-check.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { ApplicationInitStatus, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import {
ComponentFixture,
fakeAsync,
TestBed,
tick,
flush,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { IxModule } from '@siemens/ix-angular';
import { waitForHydration } from '../utils/wait-for-hydration';
import { TestInputFormRequired } from './form-ix-input-required';
import { TestInputFormWithValidators } from './form-ix-input-with-validators';

describe('ix-input required', () => {
let component: TestInputFormRequired;
let fixture: ComponentFixture<TestInputFormRequired>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [TestInputFormRequired, TestInputFormWithValidators],
schemas: [],
imports: [FormsModule, ReactiveFormsModule, IxModule.forRoot()],
}).compileComponents();

fixture = TestBed.createComponent(TestInputFormRequired);
component = fixture.componentInstance;
fixture.detectChanges();
});

beforeEach(async () => {
// until https://github.com/angular/angular/issues/24218 is fixed
await TestBed.inject(ApplicationInitStatus).donePromise;
});

it('show no invalid state after first validation', fakeAsync(() => {
const input = fixture.debugElement.query(
By.css('ix-input[formControlName="name"]')
);

fixture.detectChanges();
tick(100);
flush();

fixture.detectChanges();

expect(component).toBeDefined();
expect(input.nativeElement.classList).not.toContain('ix-invalid');

input.nativeElement.dispatchEvent(new Event('ixBlur'));
fixture.detectChanges();

tick(100);
flush();
expect(input.nativeElement.classList).toContain('ix-invalid');

component.form.get('name')!.setValue('test');
input.nativeElement.dispatchEvent(new Event('ixBlur'));
fixture.detectChanges();

tick(100);
flush();
expect(input.nativeElement.classList).not.toContain('ix-invalid');
}));
});

describe('ix-input required + additional validators', () => {
let component: TestInputFormWithValidators;
let fixture: ComponentFixture<TestInputFormRequired>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [TestInputFormRequired, TestInputFormWithValidators],
schemas: [],
imports: [FormsModule, ReactiveFormsModule, IxModule.forRoot()],
}).compileComponents();

fixture = TestBed.createComponent(TestInputFormWithValidators);
component = fixture.componentInstance;
fixture.detectChanges();
});

beforeEach(async () => {
// until https://github.com/angular/angular/issues/24218 is fixed
await TestBed.inject(ApplicationInitStatus).donePromise;
});

it('should show invalid state if another validator is added', fakeAsync(() => {
const input = fixture.debugElement.query(
By.css('ix-input[formControlName="name"]')
);

fixture.detectChanges();
tick(100);
flush();

fixture.detectChanges();

expect(component).toBeDefined();
// Validators.required = true, but not showing invalid state, because the input is not touched
expect(input.nativeElement.classList).not.toContain('ix-invalid');

input.nativeElement.dispatchEvent(new Event('ixBlur'));
fixture.detectChanges();

tick(100);
flush();
// Validators.required = true
expect(input.nativeElement.classList).toContain('ix-invalid');

component.form.get('name')!.setValue('1');
input.nativeElement.dispatchEvent(new Event('ixBlur'));
fixture.detectChanges();

tick(100);
flush();
// Validators.minLength = true
expect(input.nativeElement.classList).toContain('ix-invalid');

component.form.get('name')!.setValue('1234');
input.nativeElement.dispatchEvent(new Event('ixBlur'));
fixture.detectChanges();

tick(100);
flush();
expect(input.nativeElement.classList).not.toContain('ix-invalid');
}));
});
21 changes: 9 additions & 12 deletions packages/angular-test-app/src/test/utils/wait-for-hydration.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
export function waitForHydration(
element: HTMLElement,
timeout = 5000
timeout = 1000
): Promise<void> {
return new Promise((resolve, reject) => {
const interval = 50;
let elapsedTime = 0;

const checkClass = () => {
const interval = setInterval(() => {
if (element.classList.contains('hydrated')) {
clearInterval(interval);
clearTimeout(timeoutId);
resolve();
} else if (elapsedTime >= timeout) {
reject(new Error(`Timeout waiting for hydration`));
} else {
elapsedTime += interval;
setTimeout(checkClass, interval);
}
};
}, 50);

checkClass();
const timeoutId = setTimeout(() => {
clearInterval(interval);
reject(new Error('Timeout waiting for hydration'));
}, timeout);
});
}

0 comments on commit f60cbde

Please sign in to comment.