import {HarnessLoader} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; import {Component} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ReactiveFormsModule} from '@angular/forms'; import {MatRadioModule} from '@angular/material/radio'; import {MatRadioButtonHarness, MatRadioGroupHarness} from './radio-harness'; describe('radio harness', () => { let fixture: ComponentFixture; let loader: HarnessLoader; beforeEach(() => { TestBed.configureTestingModule({ imports: [MatRadioModule, ReactiveFormsModule, MultipleRadioButtonsHarnessTest], }); fixture = TestBed.createComponent(MultipleRadioButtonsHarnessTest); fixture.detectChanges(); loader = TestbedHarnessEnvironment.loader(fixture); }); describe('MatRadioGroupHarness', () => { it('should load all radio-group harnesses', async () => { const groups = await loader.getAllHarnesses(MatRadioGroupHarness); expect(groups.length).toBe(3); }); it('should load radio-group with exact id', async () => { const groups = await loader.getAllHarnesses( MatRadioGroupHarness.with({selector: '#my-group-2'}), ); expect(groups.length).toBe(1); }); it('should load radio-group by name', async () => { let groups = await loader.getAllHarnesses( MatRadioGroupHarness.with({name: 'my-group-2-name'}), ); expect(groups.length).toBe(1); expect(await groups[0].getId()).toBe('my-group-2'); groups = await loader.getAllHarnesses(MatRadioGroupHarness.with({name: 'my-group-1-name'})); expect(groups.length).toBe(1); expect(await groups[0].getId()).toBe('my-group-1'); }); it('should throw when finding radio-group with specific name that has mismatched radio-button names', async () => { fixture.componentInstance.thirdGroupButtonName = 'other-name'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); await expectAsync( loader.getAllHarnesses(MatRadioGroupHarness.with({name: 'third-group-name'})), ).toBeRejectedWithError( /locator found a radio-group with name "third-group-name".*have mismatching names/, ); }); it('should get name of radio-group', async () => { const groups = await loader.getAllHarnesses(MatRadioGroupHarness); expect(groups.length).toBe(3); expect(await groups[0].getName()).toBe('my-group-1-name'); expect(await groups[1].getName()).toBe('my-group-2-name'); expect(await groups[2].getName()).toBe('third-group-name'); fixture.componentInstance.secondGroupId = 'new-group'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(await groups[1].getName()).toBe('new-group-name'); fixture.componentInstance.thirdGroupButtonName = 'other-button-name'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); await expectAsync(groups[2].getName()).toBeRejectedWithError( /Radio buttons in radio-group have mismatching names./, ); }); it('should get id of radio-group', async () => { const groups = await loader.getAllHarnesses(MatRadioGroupHarness); expect(groups.length).toBe(3); expect(await groups[0].getId()).toBe('my-group-1'); expect(await groups[1].getId()).toBe('my-group-2'); expect(await groups[2].getId()).toBe(''); fixture.componentInstance.secondGroupId = 'new-group-name'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(await groups[1].getId()).toBe('new-group-name'); }); it('should get checked value of radio-group', async () => { const [firstGroup, secondGroup] = await loader.getAllHarnesses(MatRadioGroupHarness); expect(await firstGroup.getCheckedValue()).toBe('opt2'); expect(await secondGroup.getCheckedValue()).toBe(null); }); it('should get radio-button harnesses of radio-group', async () => { const groups = await loader.getAllHarnesses(MatRadioGroupHarness); expect(groups.length).toBe(3); expect((await groups[0].getRadioButtons()).length).toBe(3); expect((await groups[1].getRadioButtons()).length).toBe(1); expect((await groups[2].getRadioButtons()).length).toBe(2); }); it('should get radio buttons from group with filter', async () => { const group = await loader.getHarness(MatRadioGroupHarness.with({name: 'my-group-1-name'})); expect((await group.getRadioButtons({label: 'opt2'})).length).toBe(1); }); it('should get checked radio-button harnesses of radio-group', async () => { const groups = await loader.getAllHarnesses(MatRadioGroupHarness); expect(groups.length).toBe(3); const groupOneChecked = await groups[0].getCheckedRadioButton(); const groupTwoChecked = await groups[1].getCheckedRadioButton(); const groupThreeChecked = await groups[2].getCheckedRadioButton(); expect(groupOneChecked).not.toBeNull(); expect(groupTwoChecked).toBeNull(); expect(groupThreeChecked).toBeNull(); expect(await groupOneChecked!.getId()).toBe('opt2-group-one'); }); it('should check radio button in group', async () => { const group = await loader.getHarness(MatRadioGroupHarness.with({name: 'my-group-1-name'})); expect(await group.getCheckedValue()).toBe('opt2'); await group.checkRadioButton({label: 'opt3'}); expect(await group.getCheckedValue()).toBe('opt3'); }); it('should throw error when checking invalid radio button', async () => { const group = await loader.getHarness(MatRadioGroupHarness.with({name: 'my-group-1-name'})); await expectAsync(group.checkRadioButton({label: 'opt4'})).toBeRejectedWithError( /Could not find radio button matching {"label":"opt4"}/, ); }); }); describe('MatRadioButtonHarness', () => { it('should load all radio-button harnesses', async () => { const radios = await loader.getAllHarnesses(MatRadioButtonHarness); expect(radios.length).toBe(9); }); it('should load radio-button with exact label', async () => { const radios = await loader.getAllHarnesses(MatRadioButtonHarness.with({label: 'Option #2'})); expect(radios.length).toBe(1); expect(await radios[0].getId()).toBe('opt2'); expect(await radios[0].getLabelText()).toBe('Option #2'); }); it('should load radio-button with regex label match', async () => { const radios = await loader.getAllHarnesses(MatRadioButtonHarness.with({label: /#3$/i})); expect(radios.length).toBe(1); expect(await radios[0].getId()).toBe('opt3'); expect(await radios[0].getLabelText()).toBe('Option #3'); }); it('should load radio-button with id', async () => { const radios = await loader.getAllHarnesses(MatRadioButtonHarness.with({selector: '#opt3'})); expect(radios.length).toBe(1); expect(await radios[0].getId()).toBe('opt3'); expect(await radios[0].getLabelText()).toBe('Option #3'); }); it('should load radio-buttons with same name', async () => { const radios = await loader.getAllHarnesses(MatRadioButtonHarness.with({name: 'group1'})); expect(radios.length).toBe(2); expect(await radios[0].getId()).toBe('opt1'); expect(await radios[1].getId()).toBe('opt2'); }); it('should get checked state', async () => { const [uncheckedRadio, checkedRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); expect(await uncheckedRadio.isChecked()).toBe(false); expect(await checkedRadio.isChecked()).toBe(true); }); it('should get label text', async () => { const [firstRadio, secondRadio, thirdRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); expect(await firstRadio.getLabelText()).toBe('Option #1'); expect(await secondRadio.getLabelText()).toBe('Option #2'); expect(await thirdRadio.getLabelText()).toBe('Option #3'); }); it('should get value', async () => { const [firstRadio, secondRadio, thirdRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); expect(await firstRadio.getValue()).toBe('opt1'); expect(await secondRadio.getValue()).toBe('opt2'); expect(await thirdRadio.getValue()).toBe('opt3'); }); it('should get disabled state', async () => { const [firstRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); expect(await firstRadio.isDisabled()).toBe(false); fixture.componentInstance.disableAll = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(await firstRadio.isDisabled()).toBe(true); }); it('should get the disabled state with disabledInteractive is enabled', async () => { fixture.componentInstance.disabledInteractive = true; fixture.changeDetectorRef.markForCheck(); const [firstRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); expect(await firstRadio.isDisabled()).toBe(false); fixture.componentInstance.disableAll = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(await firstRadio.isDisabled()).toBe(true); }); it('should focus radio-button', async () => { const radioButton = await loader.getHarness(MatRadioButtonHarness.with({selector: '#opt2'})); expect(await radioButton.isFocused()).toBe(false); await radioButton.focus(); expect(await radioButton.isFocused()).toBe(true); }); it('should blur radio-button', async () => { const radioButton = await loader.getHarness(MatRadioButtonHarness.with({selector: '#opt2'})); await radioButton.focus(); expect(await radioButton.isFocused()).toBe(true); await radioButton.blur(); expect(await radioButton.isFocused()).toBe(false); }); it('should check radio-button', async () => { const [uncheckedRadio, checkedRadio] = await loader.getAllHarnesses(MatRadioButtonHarness); await uncheckedRadio.check(); expect(await uncheckedRadio.isChecked()).toBe(true); // Checked radio state should change since the two radio's // have the same name and only one can be checked. expect(await checkedRadio.isChecked()).toBe(false); }); it('should not be able to check disabled radio-button', async () => { fixture.componentInstance.disableAll = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const radioButton = await loader.getHarness(MatRadioButtonHarness.with({selector: '#opt3'})); expect(await radioButton.isChecked()).toBe(false); await radioButton.check(); expect(await radioButton.isChecked()).toBe(false); fixture.componentInstance.disableAll = false; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(await radioButton.isChecked()).toBe(false); await radioButton.check(); expect(await radioButton.isChecked()).toBe(true); }); it('should get required state', async () => { const radioButton = await loader.getHarness( MatRadioButtonHarness.with({selector: '#required-radio'}), ); expect(await radioButton.isRequired()).toBe(true); }); }); }); @Component({ template: ` @for (value of values; track value) { Option #{{$index + 1}} } @for (value of values; track value) { {{value}} } Accept terms of conditions First `, standalone: true, imports: [MatRadioModule, ReactiveFormsModule], }) class MultipleRadioButtonsHarnessTest { values = ['opt1', 'opt2', 'opt3']; disableAll = false; disabledInteractive = false; secondGroupId = 'my-group-2'; thirdGroupName: string = 'third-group-name'; thirdGroupButtonName: string | undefined = undefined; }