Skip to content

Commit

Permalink
Merge pull request #215 from funidata/DS-100-checkbox-tests
Browse files Browse the repository at this point in the history
[Checkbox Group]: Tests
  • Loading branch information
videoeero authored Oct 30, 2023
2 parents 2dd32be + c47ca7c commit 7a9755d
Show file tree
Hide file tree
Showing 8 changed files with 420 additions and 61 deletions.
2 changes: 2 additions & 0 deletions ngx-fudis/projects/ngx-fudis/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ module.exports = function (config) {
"/info-circle.svg": "/base/src/lib/assets/icons/info-circle.svg",
"/calendar.svg": "/base/src/lib/assets/icons/calendar.svg",
"/alert.svg": "/base/src/lib/assets/icons/alert.svg",
"/check-small.svg": "/base/src/lib/assets/icons/check-small.svg",
"/alert-fill.svg": "/base/src/lib/assets/icons/alert-fill.svg",
},
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogModule } from '@angular/material/dialog';
import { RouterTestingModule } from '@angular/router/testing';
import { MockComponent } from 'ng-mocks';
import { getElement, sortClasses } from 'projects/ngx-fudis/utilities/tests/utilities';
import { Component } from '@angular/core';
import { getElement, sortClasses } from '../../../../../utilities/tests/utilities';
import { AlertComponent } from './alert.component';
import { FudisDialogService } from '../../../services/dialog/dialog.service';
import { BodyTextComponent } from '../../typography/body-text/body-text.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@
width: spacing.$spacing-sm;
height: spacing.$spacing-sm;

:focus {
@include focus.focus-checkbox;
}

svg {
@include colorMixins.bg-color('white');
}
Expand Down Expand Up @@ -103,7 +99,7 @@
place-content: center;

&:focus {
@include focus.focus-generic;
@include focus.focus-checkbox;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
// eslint-disable-next-line max-classes-per-file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';

import { MockComponent } from 'ng-mocks';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { BehaviorSubject } from 'rxjs';

import { CheckboxGroupComponent } from './checkbox-group.component';
import { FieldSetComponent } from '../fieldset/fieldset.component';
import { CheckboxComponent } from './checkbox/checkbox.component';
import { FudisCheckboxGroupFormGroup } from '../../../types/forms';
import { FudisGroupValidator } from '../../../utilities/form/validators';
import { FudisBreakpointService } from '../../../services/breakpoint/breakpoint.service';
import { FudisGridService } from '../../../services/grid/grid.service';
import { GridComponent } from '../../grid/grid/grid.component';
import { GridApiDirective } from '../../../directives/grid/grid-api/grid-api.directive';
import { GridDirective } from '../../../directives/grid/grid/grid.directive';
import { IconComponent } from '../../icon/icon.component';
import { ContentDirective } from '../../../directives/content-projection/content/content.directive';
import { GuidanceComponent } from '../guidance/guidance.component';
import { ErrorMessageComponent } from '../error-message/error-message.component';
import { FudisDropdownMenuItemService } from '../../dropdown-menu/dropdown-menu-item/dropdown-menu-item.service';

const testFormGroup = new FormGroup<FudisCheckboxGroupFormGroup>(
{
Expand All @@ -20,22 +32,193 @@ const testFormGroup = new FormGroup<FudisCheckboxGroupFormGroup>(
[FudisGroupValidator.atLeastOneRequired(new BehaviorSubject('No fruit picked! :('))]
);

@Component({
selector: 'fudis-mock-component',
template: `<fudis-checkbox-group
[formGroup]="testFromGroup"
[title]="'Choose minimum of one fruit'"
[required]="true">
<p class="do-not-find-me">This should not be shown</p>
<fudis-checkbox *ngFor="let option of options" [controlName]="option.controlName" [label]="option.label" />
</fudis-checkbox-group>`,
})
class MockContainerComponent {
public testFromGroup = new FormGroup<FudisCheckboxGroupFormGroup>(
{
apple: new FormControl<boolean | null | undefined>(null),
fairTradeBanana: new FormControl<boolean | null | undefined>(false),
orange: new FormControl<boolean | null | undefined>(undefined),
pear: new FormControl<boolean | null | undefined>(true),
pineapple: new FormControl<boolean | null | undefined>({ value: false, disabled: true }),
},
[
FudisGroupValidator.min({ value: 2, message: new BehaviorSubject('Too few selected') }),
FudisGroupValidator.max({ value: 3, message: new BehaviorSubject('Too many selected') }),
]
);

public options = [
{ controlName: 'apple', label: 'Apple' },
{ controlName: 'fairTradeBanana', label: 'Fair trade banana' },
{ controlName: 'pear', label: 'Pear' },
{ controlName: 'pineapple', label: 'Pineapple' },
{ controlName: 'orange', label: 'Orange' },
];
}

describe('CheckboxGroupComponent', () => {
let component: CheckboxGroupComponent;
let fixture: ComponentFixture<CheckboxGroupComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [CheckboxComponent, CheckboxGroupComponent, MockComponent(FieldSetComponent)],
let fixture: ComponentFixture<CheckboxGroupComponent> | ComponentFixture<MockContainerComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
CheckboxComponent,
MockContainerComponent,
CheckboxGroupComponent,
FieldSetComponent,
GridComponent,
GridApiDirective,
GridDirective,
ContentDirective,
GuidanceComponent,
IconComponent,
ErrorMessageComponent,
],
providers: [FudisBreakpointService, FudisGridService, FudisDropdownMenuItemService],
imports: [ReactiveFormsModule],
}).compileComponents();
});

describe('Basic inputs', () => {
beforeEach(() => {
fixture = TestBed.createComponent(CheckboxGroupComponent);
component = fixture.componentInstance;
component.formGroup = testFormGroup;
component.title = 'Checkbox Group test title';
component.helpText = 'Some help text';

fixture.detectChanges();
});

it('should have correct title as legend', () => {
const legendTitle: string = fixture.nativeElement.querySelector('.fudis-fieldset__legend__title__text').innerText;

expect(legendTitle).toEqual('CHECKBOX GROUP TEST TITLE');
});

it('should have correct helptext in the guidance', () => {
const helpText: string = fixture.nativeElement.querySelector('.fudis-guidance__help-text').innerText;

expect(helpText).toEqual('Some help text');
});

it('should display required text', () => {
component.required = true;
fixture.detectChanges();

const requiredText: string = fixture.nativeElement.querySelector(
'.fudis-fieldset__legend__title__text__required'
).innerText;

expect(requiredText).toEqual('(Required)');
});
fixture = TestBed.createComponent(CheckboxGroupComponent);
component = fixture.componentInstance;
component.formGroup = testFormGroup;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
describe('Child checkboxes', () => {
let mockComponent: MockContainerComponent;

beforeEach(() => {
fixture = TestBed.createComponent(MockContainerComponent);
mockComponent = fixture.componentInstance;
fixture.detectChanges();
});

it('should not render p-tag', () => {
const element = fixture.nativeElement.querySelector('.do-not-find-me');

expect(element).toBeNull();
});

it('should have correct amount of child components', () => {
const element: NodeList = fixture.nativeElement.querySelectorAll('fudis-checkbox');

expect(element.length).toEqual(5);
});

it('should have invalid styled child elements with invalid state, when form group is touched and should display errors', () => {
mockComponent.testFromGroup.markAllAsTouched();

fixture.detectChanges();

const invalidStyledCheckboxes: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox .fudis-checkbox__content__box--invalid'
);

const invalidInputs: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox input[aria-invalid="true"]'
);

const errorMessage: string = fixture.nativeElement.querySelector('fudis-guidance .fudis-error-message').innerText;

expect(invalidInputs.length).toEqual(5);
expect(invalidStyledCheckboxes.length).toEqual(5);
expect(errorMessage).toEqual('Too few selected');
});

it('should remove invalid state when checking one checkbox more', () => {
mockComponent.testFromGroup.markAllAsTouched();

fixture.detectChanges();

const checkbox = fixture.nativeElement.querySelector('fudis-checkbox');

checkbox.querySelector('input').click();

fixture.detectChanges();

const invalidStyledCheckboxes: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox .fudis-checkbox__content__box--invalid'
);

const invalidInputs: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox input[aria-invalid="true"]'
);

const errorMessage = fixture.nativeElement.querySelector('fudis-guidance .fudis-error-message');

expect(invalidInputs.length).toEqual(0);
expect(invalidStyledCheckboxes.length).toEqual(0);
expect(errorMessage).toBeNull();
});

it('should display error, when too many selected', () => {
mockComponent.testFromGroup.markAllAsTouched();
const appleInput = fixture.nativeElement.querySelector('fudis-checkbox[ng-reflect-control-name="apple"] input');
const bananaInput = fixture.nativeElement.querySelector(
'fudis-checkbox[ng-reflect-control-name="fairTradeBanana"] input'
);
const orangeInput = fixture.nativeElement.querySelector('fudis-checkbox[ng-reflect-control-name="orange"] input');

appleInput.click();
bananaInput.click();
orangeInput.click();
fixture.detectChanges();

const invalidStyledCheckboxes: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox .fudis-checkbox__content__box--invalid'
);

const invalidInputs: NodeList = fixture.nativeElement.querySelectorAll(
'fudis-checkbox input[aria-invalid="true"]'
);

const errorMessage = fixture.nativeElement.querySelector('fudis-guidance .fudis-error-message').innerText;

expect(invalidInputs.length).toEqual(5);
expect(invalidStyledCheckboxes.length).toEqual(5);
expect(errorMessage).toEqual('Too many selected');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ export class CheckboxGroupComponent extends FieldSetBaseDirective implements OnI
*/
@Input() required: boolean | undefined = undefined;

/**
* Set Checkbox Group's visual style and ARIA attribute as invalid. Does not override if control.invalid is true.
*/
@Input() invalidState: boolean = false;

/**
* Width size of the group - defaults to large.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@
[value]="_checkboxGroup.formGroup.controls[controlName].value"
[name]="this._checkboxGroup.id"
[attr.aria-describedBy]="_checkboxGroup.id + '_guidance'"
[attr.aria-disabled]="_checkboxGroup.formGroup.controls[controlName].disabled"
[attr.aria-disabled]="_checkboxGroup.formGroup.controls[controlName].disabled ? true : null"
[attr.checked]="_checkboxGroup.formGroup.controls[controlName].value ? true : null"
[attr.aria-invalid]="
_checkboxGroup.formGroup.touched && (_checkboxGroup.formGroup.invalid || _checkboxGroup.invalidState)
? true
: null
"
[attr.aria-invalid]="_checkboxGroup.formGroup.touched && _checkboxGroup.formGroup.invalid ? true : null"
(change)="_onChange()"
(blur)="_onBlur($event)"
(focus)="_onFocus()" />
Expand Down
Loading

0 comments on commit 7a9755d

Please sign in to comment.