From 88de34e9383e08d78716d839d7c56382fcf6f005 Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Tue, 26 Sep 2023 15:23:32 -0400 Subject: [PATCH 1/3] test(Multiple Choice): Add tests to Multiple Choice authoring --- .../mulitiple-choice-authoring.spec.ts | 139 ++++++++++++++++++ .../multiple-choice-authoring.harness.ts | 54 +++++++ 2 files changed, 193 insertions(+) create mode 100644 src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts create mode 100644 src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts diff --git a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts new file mode 100644 index 00000000000..fc62789453c --- /dev/null +++ b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts @@ -0,0 +1,139 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { MultipleChoiceAuthoring } from './multiple-choice-authoring.component'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { MatDialogModule } from '@angular/material/dialog'; +import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module'; +import { ProjectAssetService } from '../../../../../app/services/projectAssetService'; +import { TeacherProjectService } from '../../../services/teacherProjectService'; +import { EditComponentPrompt } from '../../../../../app/authoring-tool/edit-component-prompt/edit-component-prompt.component'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatIconModule } from '@angular/material/icon'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { FormsModule } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MultipleChoiceAuthoringHarness } from './multiple-choice-authoring.harness'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +let component: MultipleChoiceAuthoring; +let fixture: ComponentFixture; +let multipleChoiceAuthoringHarness: MultipleChoiceAuthoringHarness; + +describe('MultipleChoiceAuthoringComponent', () => { + beforeEach( + waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [EditComponentPrompt, MultipleChoiceAuthoring], + imports: [ + BrowserAnimationsModule, + FormsModule, + HttpClientTestingModule, + MatDialogModule, + MatCheckboxModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatRadioModule, + StudentTeacherCommonServicesModule + ], + providers: [ProjectAssetService, TeacherProjectService] + }); + }) + ); + + beforeEach(async () => { + fixture = TestBed.createComponent(MultipleChoiceAuthoring); + component = fixture.componentInstance; + component.componentContent = { + choices: [], + choiceType: 'radio', + prompt: '', + showFeedback: true, + type: 'MultipleChoice' + }; + fixture.detectChanges(); + multipleChoiceAuthoringHarness = await TestbedHarnessEnvironment.harnessForFixture( + fixture, + MultipleChoiceAuthoringHarness + ); + }); + + addChoice(); + deleteChoice(); + changeChoiceType(); + moveChoice(); +}); + +function addChoice() { + describe('add choice button is clicked', () => { + it('adds a new choice', async () => { + await multipleChoiceAuthoringHarness.clickAddChoiceButton(); + expect(await multipleChoiceAuthoringHarness.getNumChoices()).toBe(1); + }); + }); +} + +function deleteChoice() { + describe('delete choice button is clicked', () => { + beforeEach(() => { + component.componentContent.choices = [{ id: 'choice1', text: 'Choice A' }]; + }); + it('deletes a choice', async () => { + spyOn(window, 'confirm').and.returnValue(true); + await multipleChoiceAuthoringHarness.clickDeleteChoiceButton(0); + expect(await multipleChoiceAuthoringHarness.getNumChoices()).toBe(0); + }); + }); +} + +function changeChoiceType() { + describe('single answer is currently selected', () => { + describe('multiple answer is clicked', () => { + it('sets the choice type to checkbox', async () => { + await multipleChoiceAuthoringHarness.clickMultipleAnswerRadioChoice(); + expect(component.componentContent.choiceType).toBe('checkbox'); + }); + }); + }); + describe('multiple answer is currently selected', () => { + describe('single answer is clicked', () => { + beforeEach(() => { + component.componentContent.choiceType = 'checkbox'; + }); + it('sets the choice type to radio', async () => { + await multipleChoiceAuthoringHarness.clickSingleAnswerRadioChoice(); + expect(component.componentContent.choiceType).toBe('radio'); + }); + }); + }); +} + +function moveChoice() { + describe('move choice', () => { + beforeEach(() => { + component.componentContent.choices = [ + { id: 'choice1', text: 'Choice A' }, + { id: 'choice2', text: 'Choice B' } + ]; + }); + describe('move choice down is clicked on the first choice', () => { + it('moves the choice down', async () => { + await multipleChoiceAuthoringHarness.clickMoveChoiceDownButton(0); + expectChoiceOrder(['choice2', 'choice1']); + }); + }); + describe('move choice up is clicked on the second choice', () => { + it('moves the choice up', async () => { + await multipleChoiceAuthoringHarness.clickMoveChoiceUpButton(1); + expectChoiceOrder(['choice2', 'choice1']); + }); + }); + }); +} + +function expectChoiceOrder(choiceIds: string[]): void { + choiceIds.forEach((choiceId, index) => { + expect(component.componentContent.choices[index].id).toBe(choiceId); + }); +} diff --git a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts new file mode 100644 index 00000000000..43289515da5 --- /dev/null +++ b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts @@ -0,0 +1,54 @@ +import { ComponentHarness } from '@angular/cdk/testing'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { MatRadioButtonHarness } from '@angular/material/radio/testing'; + +export class MultipleChoiceAuthoringHarness extends ComponentHarness { + static hostSelector = 'multiple-choice-authoring'; + protected getAddChoiceButton = this.locatorFor( + MatButtonHarness.with({ selector: '.add-choice-button' }) + ); + protected getChoices = this.locatorForAll('.choice-container'); + protected getDeleteChoiceButtons = this.locatorForAll( + MatButtonHarness.with({ selector: '[aria-label="Delete"]' }) + ); + protected getMoveDownButtons = this.locatorForAll( + MatButtonHarness.with({ selector: '[aria-label="Down"]' }) + ); + protected getMoveUpButtons = this.locatorForAll( + MatButtonHarness.with({ selector: '[aria-label="Up"]' }) + ); + protected getMultipleAnswerRadioChoice = this.locatorFor( + MatRadioButtonHarness.with({ label: 'Multiple Answer' }) + ); + protected getSingleAnswerRadioChoice = this.locatorFor( + MatRadioButtonHarness.with({ label: 'Single Answer' }) + ); + + async clickAddChoiceButton(): Promise { + return (await this.getAddChoiceButton()).click(); + } + + async clickDeleteChoiceButton(index: number): Promise { + await (await this.getDeleteChoiceButtons())[index].click(); + } + + async clickMoveChoiceDownButton(index: number): Promise { + await (await this.getMoveDownButtons())[index].click(); + } + + async clickMoveChoiceUpButton(index: number): Promise { + await (await this.getMoveUpButtons())[index].click(); + } + + async clickMultipleAnswerRadioChoice(): Promise { + return (await this.getMultipleAnswerRadioChoice()).check(); + } + + async clickSingleAnswerRadioChoice(): Promise { + return (await this.getSingleAnswerRadioChoice()).check(); + } + + async getNumChoices(): Promise { + return (await this.getChoices()).length; + } +} From 58cfe1f7c011d809a101ac21daf1cfb5c934d643 Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Fri, 13 Oct 2023 13:18:52 -0400 Subject: [PATCH 2/3] test(Multiple Choice): Remove unnecessary functions --- .../multiple-choice-authoring.harness.ts | 42 ++++++------------- ...c.ts => multiple-choice-authoring.spec.ts} | 12 +++--- 2 files changed, 19 insertions(+), 35 deletions(-) rename src/assets/wise5/components/multipleChoice/multiple-choice-authoring/{mulitiple-choice-authoring.spec.ts => multiple-choice-authoring.spec.ts} (89%) diff --git a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts index 43289515da5..0bd854fa246 100644 --- a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts +++ b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts @@ -4,48 +4,32 @@ import { MatRadioButtonHarness } from '@angular/material/radio/testing'; export class MultipleChoiceAuthoringHarness extends ComponentHarness { static hostSelector = 'multiple-choice-authoring'; - protected getAddChoiceButton = this.locatorFor( - MatButtonHarness.with({ selector: '.add-choice-button' }) - ); - protected getChoices = this.locatorForAll('.choice-container'); - protected getDeleteChoiceButtons = this.locatorForAll( + getAddChoiceButton = this.locatorFor(MatButtonHarness.with({ selector: '.add-choice-button' })); + getChoices = this.locatorForAll('.choice-container'); + getDeleteChoiceButtons = this.locatorForAll( MatButtonHarness.with({ selector: '[aria-label="Delete"]' }) ); - protected getMoveDownButtons = this.locatorForAll( + getMoveDownButtons = this.locatorForAll( MatButtonHarness.with({ selector: '[aria-label="Down"]' }) ); - protected getMoveUpButtons = this.locatorForAll( - MatButtonHarness.with({ selector: '[aria-label="Up"]' }) - ); - protected getMultipleAnswerRadioChoice = this.locatorFor( + getMoveUpButtons = this.locatorForAll(MatButtonHarness.with({ selector: '[aria-label="Up"]' })); + getMultipleAnswerRadioChoice = this.locatorFor( MatRadioButtonHarness.with({ label: 'Multiple Answer' }) ); - protected getSingleAnswerRadioChoice = this.locatorFor( + getSingleAnswerRadioChoice = this.locatorFor( MatRadioButtonHarness.with({ label: 'Single Answer' }) ); - async clickAddChoiceButton(): Promise { - return (await this.getAddChoiceButton()).click(); - } - - async clickDeleteChoiceButton(index: number): Promise { - await (await this.getDeleteChoiceButtons())[index].click(); - } - - async clickMoveChoiceDownButton(index: number): Promise { - await (await this.getMoveDownButtons())[index].click(); - } - - async clickMoveChoiceUpButton(index: number): Promise { - await (await this.getMoveUpButtons())[index].click(); + async getDeleteChoiceButton(index: number): Promise { + return (await this.getDeleteChoiceButtons())[index]; } - async clickMultipleAnswerRadioChoice(): Promise { - return (await this.getMultipleAnswerRadioChoice()).check(); + async getMoveChoiceDownButton(index: number): Promise { + return (await this.getMoveDownButtons())[index]; } - async clickSingleAnswerRadioChoice(): Promise { - return (await this.getSingleAnswerRadioChoice()).check(); + async getMoveChoiceUpButton(index: number): Promise { + return (await this.getMoveUpButtons())[index]; } async getNumChoices(): Promise { diff --git a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts similarity index 89% rename from src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts rename to src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts index fc62789453c..28add200bb1 100644 --- a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/mulitiple-choice-authoring.spec.ts +++ b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts @@ -68,7 +68,7 @@ describe('MultipleChoiceAuthoringComponent', () => { function addChoice() { describe('add choice button is clicked', () => { it('adds a new choice', async () => { - await multipleChoiceAuthoringHarness.clickAddChoiceButton(); + await (await multipleChoiceAuthoringHarness.getAddChoiceButton()).click(); expect(await multipleChoiceAuthoringHarness.getNumChoices()).toBe(1); }); }); @@ -81,7 +81,7 @@ function deleteChoice() { }); it('deletes a choice', async () => { spyOn(window, 'confirm').and.returnValue(true); - await multipleChoiceAuthoringHarness.clickDeleteChoiceButton(0); + await (await multipleChoiceAuthoringHarness.getDeleteChoiceButton(0)).click(); expect(await multipleChoiceAuthoringHarness.getNumChoices()).toBe(0); }); }); @@ -91,7 +91,7 @@ function changeChoiceType() { describe('single answer is currently selected', () => { describe('multiple answer is clicked', () => { it('sets the choice type to checkbox', async () => { - await multipleChoiceAuthoringHarness.clickMultipleAnswerRadioChoice(); + await (await multipleChoiceAuthoringHarness.getMultipleAnswerRadioChoice()).check(); expect(component.componentContent.choiceType).toBe('checkbox'); }); }); @@ -102,7 +102,7 @@ function changeChoiceType() { component.componentContent.choiceType = 'checkbox'; }); it('sets the choice type to radio', async () => { - await multipleChoiceAuthoringHarness.clickSingleAnswerRadioChoice(); + await (await multipleChoiceAuthoringHarness.getSingleAnswerRadioChoice()).check(); expect(component.componentContent.choiceType).toBe('radio'); }); }); @@ -119,13 +119,13 @@ function moveChoice() { }); describe('move choice down is clicked on the first choice', () => { it('moves the choice down', async () => { - await multipleChoiceAuthoringHarness.clickMoveChoiceDownButton(0); + await (await multipleChoiceAuthoringHarness.getMoveChoiceDownButton(0)).click(); expectChoiceOrder(['choice2', 'choice1']); }); }); describe('move choice up is clicked on the second choice', () => { it('moves the choice up', async () => { - await multipleChoiceAuthoringHarness.clickMoveChoiceUpButton(1); + await (await multipleChoiceAuthoringHarness.getMoveChoiceUpButton(1)).click(); expectChoiceOrder(['choice2', 'choice1']); }); }); From 4f782911725fe177c8bc54f3b3bb9e8c0555f55a Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Fri, 13 Oct 2023 13:26:54 -0400 Subject: [PATCH 3/3] test(Multiple Choice): Fix failing tests --- .../multiple-choice-authoring.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts index 28add200bb1..5b1eb079fc2 100644 --- a/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts +++ b/src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts @@ -15,6 +15,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MultipleChoiceAuthoringHarness } from './multiple-choice-authoring.harness'; import { MatCheckboxModule } from '@angular/material/checkbox'; +import { TeacherNodeService } from '../../../services/teacherNodeService'; let component: MultipleChoiceAuthoring; let fixture: ComponentFixture; @@ -37,7 +38,7 @@ describe('MultipleChoiceAuthoringComponent', () => { MatRadioModule, StudentTeacherCommonServicesModule ], - providers: [ProjectAssetService, TeacherProjectService] + providers: [ProjectAssetService, TeacherNodeService, TeacherProjectService] }); }) );