Skip to content

Commit

Permalink
(test) Add unit tests for NumberInputComponent (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
denniskigen committed Jan 11, 2024
1 parent 5b0965a commit 4a9f666
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 300 deletions.
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ testem.log
# System Files
.DS_Store
Thumbs.db
./package-lock.json
./package-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { SelectOption } from '../../form-entry/question-models/interfaces/select

import { DataSource } from '../../form-entry/question-models/interfaces/data-source';
import * as _ from 'lodash';

@Component({
selector: 'ofe-remote-select',
templateUrl: 'remote-select.component.html',
Expand All @@ -40,11 +41,12 @@ export class RemoteSelectComponent implements OnInit, ControlValueAccessor {
value = [];
loading = false;
searchText = '';
notFoundMsg = 'match no found';
notFoundMsg = 'Match not found';
@Input() placeholder = 'Search...';
@Input() componentID: string;
@Input() disabled = false;
@Input() theme = 'dark';
@Input() invalid = 'false';
@Output() done: EventEmitter<any> = new EventEmitter<any>();

private _dataSource: DataSource;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<div>
<ng-select
[ngClass]="{ 'afe-custom': theme === 'light' }"
[disabled]="disabled"
[items]="remoteOptions$ | async"
bindLabel="label"
bindValue="value"
[multiple]="false"
[hideSelected]="true"
[compareWith]="compareItems"
[trackByFn]="trackByFn"
[loading]="loading"
typeToSearchText="{{ 'enterMoreCharacters' | translate }}"
[typeahead]="remoteOptionInput$"
[(ngModel)]="selectedRemoteOptions"
[appendTo]="'form'"
(ngModelChange)="selected($event)"
>
</ng-select>
</div>
<ng-select
[ngClass]="{
'afe-custom': theme === 'light',
'invalid': invalid ? true : null,
}"
[disabled]="disabled"
[items]="remoteOptions$ | async"
bindLabel="label"
bindValue="value"
[multiple]="false"
[hideSelected]="true"
[compareWith]="compareItems"
[trackByFn]="trackByFn"
[loading]="loading"
typeToSearchText="{{ 'enterMoreCharacters' | translate }}"
[typeahead]="remoteOptionInput$"
[(ngModel)]="selectedRemoteOptions"
[appendTo]="'form'"
(ngModelChange)="selected($event)"
>
</ng-select>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
'cds--number--helpertext': helperText,
'cds--skeleton': skeleton,
'cds--number--sm': size === 'sm',
'cds--number--xl': size === 'xl'
'cds--number--md': size === 'md',
'cds--number--lg': size === 'lg'
}"
>
<div
Expand All @@ -18,9 +19,9 @@
}"
>
<input
ofeNumberScroll
type="number"
[id]="id"
ofeNumberScroll
[value]="value"
[attr.min]="min"
[attr.max]="max"
Expand All @@ -29,8 +30,22 @@
[attr.step]="step"
[disabled]="disabled"
[required]="required"
[attr.data-invalid]="invalid ? invalid : null"
[placeholder]="placeholder"
(input)="onNumberInputChange($event)"
/>
<svg
*ngIf="!skeleton && !warn && invalid"
cdsIcon="warning--filled"
size="16"
class="cds--number__invalid"
></svg>
<svg
*ngIf="!skeleton && !invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--number__invalid cds--number__invalid--warning"
></svg>
<div class="cds--number__controls">
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ describe('NumberInputComponent', () => {
let fixture: ComponentFixture<NumberInputComponent>;
let debugEl: DebugElement;
let nativeEl: HTMLElement;
let numberField: HTMLElement;
let containerElement: HTMLElement;
let inputElement: HTMLInputElement;
let incrementButton: HTMLButtonElement;
let decrementButton: HTMLButtonElement;

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -18,151 +21,151 @@ describe('NumberInputComponent', () => {
component = fixture.componentInstance;
debugEl = fixture.debugElement;
nativeEl = debugEl.nativeElement;
numberField = nativeEl.querySelector('div.cds--number');

containerElement = nativeEl.querySelector('div.cds--number');
inputElement = containerElement.querySelector('input[type="number"]');
incrementButton = containerElement.querySelector('button.up-icon');
decrementButton = containerElement.querySelector('button.down-icon');
component.id = 'test-id';
component.theme = 'light';
component.disabled = false;
component.skeleton = false;
component.invalid = false;
component.size = 'md';
component.required = false;
component.value = null;

fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
expect(numberField).toBeTruthy();
expect(component instanceof NumberInputComponent).toBe(true);
expect(inputElement).toBeDefined();
});

it('should render a number input with the correct attributes', () => {
component.label = 'Pill count';
component.value = 10;
component.label = 'Pill count';
component.placeholder = 'Enter pill count';

const input = numberField.querySelector('input[type="number"]');
expect(input.getAttribute('id')).toBe('test-id');
expect(input.getAttribute('type')).toBe('number');
expect(input.getAttribute('min')).toBe(null);
expect(input.getAttribute('max')).toBe(null);
fixture.detectChanges();

expect(inputElement.getAttribute('id')).toBe('test-id');
expect(inputElement.getAttribute('type')).toBe('number');
expect(inputElement.getAttribute('min')).toBe(null);
expect(inputElement.getAttribute('max')).toBe(null);
expect(inputElement.getAttribute('placeholder')).toBe('Enter pill count');
});

it('should decrement and increment the value when the buttons are clicked', () => {
component.value = 10;
const buttons = numberField.querySelectorAll('button');
const decrementBtn = buttons[0];
const incrementBtn = buttons[1];

decrementBtn.click();
decrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(9);

decrementBtn.click();
decrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(8);

incrementBtn.click();
incrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(9);

incrementBtn.click();
incrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(10);
});

it('should not decrement the value below the min value', () => {
component.min = 10;
component.value = 10;
const buttons = numberField.querySelectorAll('button');
const decrementBtn = buttons[0];
component.min = 10;

decrementBtn.click();
decrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(10);

decrementBtn.click();
decrementButton.click();
fixture.detectChanges();

expect(component.value).not.toBe(9);
expect(component.value).toBe(10);
});

it('should not increment the value above the max value', () => {
component.max = 10;
component.value = 10;
const buttons = numberField.querySelectorAll('button');
const incrementBtn = buttons[1];
component.max = 10;

incrementBtn.click();
incrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(10);

incrementBtn.click();
incrementButton.click();
fixture.detectChanges();

expect(component.value).not.toBe(11);
expect(component.value).toBe(10);
});

it('should decrement or increment the value by the step count value', () => {
component.step = 5;
it('should decrement or increment the value by the provided step count', () => {
component.value = 10;
const buttons = numberField.querySelectorAll('button');
const decrementBtn = buttons[0];
const incrementBtn = buttons[1];
component.step = 5;

decrementBtn.click();
decrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(5);

incrementBtn.click();
incrementButton.click();
fixture.detectChanges();

expect(component.value).toBe(10);
});

it('should render helperText below the input when provided', () => {
const helperText = 'Max of 50';
component.value = 49;
component.max = 50;
component.helperText = 'Max of 50';
component.helperText = helperText;

fixture.detectChanges();

const helperText = numberField.querySelector('div.cds--form__helper-text');
expect(helperText.textContent).toBe('Max of 50');
const helperTextElement = containerElement.querySelector(
'div.cds--form__helper-text'
);
expect(containerElement.className.includes('cds--number--helpertext'));
expect(helperTextElement.textContent).toBe(helperText);
});

it('should render the supplied warning text when the warn input is true', () => {
it('should render the supplied warning text when the warn property is truthy', () => {
component.value = 11;
component.max = 10;
component.warn = true;
component.warnText = 'Min value should be 10';

numberField.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' }));
containerElement.dispatchEvent(
new KeyboardEvent('keydown', { key: 'Tab' })
);
fixture.detectChanges();

const warnText = numberField.querySelector('div.cds--form-requirement');
const warnText = containerElement.querySelector(
'div.cds--form-requirement'
);
expect(warnText.textContent).toBe('Min value should be 10');
});

it('should render the supplied invalid text when the invalid input is true', () => {
it('should render the supplied invalid text when the invalid property is truthy', () => {
component.value = 11;
component.max = 10;
component.invalid = true;
component.invalidText = 'Min value should be 10';

numberField.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' }));
containerElement.dispatchEvent(
new KeyboardEvent('keydown', { key: 'Tab' })
);
fixture.detectChanges();

const invalidText = numberField.querySelector('div.cds--form-requirement');
const invalidText = containerElement.querySelector(
'div.cds--form-requirement'
);
expect(invalidText.textContent).toBe('Min value should be 10');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,14 @@ export class NumberInputComponent implements ControlValueAccessor {
* The unique id for the number component.
*/
@Input() id = `number-${NumberInputComponent.numberCount}`;
/**
* Sets the placeholder attribute on the `input` element.
*/
@Input() placeholder = '';
/**
* Number input field render size
*/
@Input() size: 'sm' | 'md' | 'xl' = 'md';
@Input() size: 'sm' | 'md' | 'lg' = 'md';
/**
* Reflects the required attribute of the `input` element.
*/
Expand Down Expand Up @@ -133,11 +137,11 @@ export class NumberInputComponent implements ControlValueAccessor {
/**
* Sets the decrement label text
*/
@Input() decrementLabel = 'Decrease';
@Input() decrementLabel = 'Decrement';
/**
* Sets the increment label text
*/
@Input() incrementLabel = 'Increase';
@Input() incrementLabel = 'Increment';

protected _value = 0;

Expand Down
Loading

0 comments on commit 4a9f666

Please sign in to comment.