Skip to content

Commit

Permalink
chore(Run Menu): Add private/protected modifiers and create test harness
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreykwan committed Aug 23, 2023
1 parent 13ccc92 commit 328dc03
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 54 deletions.
61 changes: 34 additions & 27 deletions src/app/teacher/run-menu/run-menu.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RunMenuComponent } from './run-menu.component';
import { TeacherService } from '../teacher.service';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { BehaviorSubject, Observable } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { MatMenuModule } from '@angular/material/menu';
import { ConfigService } from '../../services/config.service';
Expand All @@ -15,7 +15,11 @@ import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ArchiveProjectService } from '../../services/archive-project.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { Project } from '../../domain/project';
import { RunMenuHarness } from './run-menu.harness';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MockArchiveProjectService } from '../../services/mock-archive-project.service';

export class MockTeacherService {
checkClassroomAuthorization(): Observable<string> {
Expand Down Expand Up @@ -63,6 +67,8 @@ export class MockConfigService {
let archiveProjectService: ArchiveProjectService;
let component: RunMenuComponent;
let fixture: ComponentFixture<RunMenuComponent>;
const owner = new User();
let runMenuHarness: RunMenuHarness;
let snackBarSpy: jasmine.Spy;
let teacherService: TeacherService;

Expand All @@ -73,13 +79,15 @@ describe('RunMenuComponent', () => {
imports: [
BrowserAnimationsModule,
HttpClientTestingModule,
MatButtonModule,
MatIconModule,
MatMenuModule,
MatSnackBarModule,
RouterTestingModule
],
declarations: [RunMenuComponent],
providers: [
ArchiveProjectService,
{ provide: ArchiveProjectService, useClass: MockArchiveProjectService },
{ provide: TeacherService, useClass: MockTeacherService },
{ provide: UserService, useClass: MockUserService },
{ provide: ConfigService, useClass: MockConfigService },
Expand All @@ -90,42 +98,39 @@ describe('RunMenuComponent', () => {
})
);

beforeEach(() => {
beforeEach(async () => {
fixture = TestBed.createComponent(RunMenuComponent);
component = fixture.componentInstance;
const owner = new User();
component.run = new TeacherRun({
id: 1,
name: 'Photosynthesis',
owner: owner,
project: {
id: 1,
owner: owner,
sharedOwners: []
}
});
setRun(false);
archiveProjectService = TestBed.inject(ArchiveProjectService);
teacherService = TestBed.inject(TeacherService);
snackBarSpy = spyOn(TestBed.inject(MatSnackBar), 'open');
spyOn(archiveProjectService, 'archiveProject').and.callFake((project: Project) => {
project.archived = true;
return of(project);
});
spyOn(archiveProjectService, 'unarchiveProject').and.callFake((project: Project) => {
project.archived = false;
return of(project);
});
fixture.detectChanges();
runMenuHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, RunMenuHarness);
});

archive();
unarchive();
});

function setRun(archived: boolean): void {
component.run = new TeacherRun({
id: 1,
name: 'Photosynthesis',
owner: owner,
project: {
id: 1,
owner: owner,
sharedOwners: []
},
archived: archived
});
}

function archive() {
describe('archive()', () => {
it('should archive a run', () => {
component.archive();
it('should archive a run', async () => {
await runMenuHarness.clickArchiveMenuButton();
expect(component.run.archived).toEqual(true);
expect(snackBarSpy).toHaveBeenCalledWith('Successfully Archived Run');
});
Expand All @@ -134,8 +139,10 @@ function archive() {

function unarchive() {
describe('unarchive()', () => {
it('should unarchive a run', () => {
component.unarchive();
it('should unarchive a run', async () => {
setRun(true);
component.ngOnInit();
await runMenuHarness.clickUnarchiveMenuButton();
expect(component.run.archived).toEqual(false);
expect(snackBarSpy).toHaveBeenCalledWith('Successfully Unarchived Run');
});
Expand Down
27 changes: 10 additions & 17 deletions src/app/teacher/run-menu/run-menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ import { ArchiveProjectResponse } from '../../domain/archiveProjectResponse';
styleUrls: ['./run-menu.component.scss']
})
export class RunMenuComponent implements OnInit {
private editLink: string = '';
protected reportProblemLink: string = '';
@Input() run: TeacherRun;
@Output() runArchiveStatusChangedEvent: EventEmitter<any> = new EventEmitter<any>();

editLink: string = '';
isOwner: boolean;
reportProblemLink: string = '';

constructor(
private archiveProjectService: ArchiveProjectService,
private dialog: MatDialog,
Expand All @@ -38,38 +36,33 @@ export class RunMenuComponent implements OnInit {
this.editLink = `${this.configService.getContextPath()}/teacher/edit/unit/${
this.run.project.id
}`;
this.isOwner = this.run.isOwner(this.userService.getUserId());
this.reportProblemLink = `${this.configService.getContextPath()}/contact?runId=${this.run.id}`;
}

shareRun() {
protected shareRun() {
this.dialog.open(ShareRunDialogComponent, {
data: { run: this.run },
panelClass: 'dialog-md'
});
}

showUnitDetails() {
protected showUnitDetails() {
const project = this.run.project;
this.dialog.open(LibraryProjectDetailsComponent, {
data: { project: project, isRunProject: true },
panelClass: 'dialog-md'
});
}

canEdit() {
protected canEdit() {
return this.run.project.canEdit(this.userService.getUserId());
}

canShare() {
protected canShare() {
return this.run.canGradeAndManage(this.userService.getUserId());
}

isRunCompleted() {
return this.run.isCompleted(this.configService.getCurrentServerTime());
}

showEditRunDetails() {
protected showEditRunDetails() {
const run = this.run;
this.dialog.open(RunSettingsDialogComponent, {
ariaLabel: $localize`Run Settings`,
Expand All @@ -79,7 +72,7 @@ export class RunMenuComponent implements OnInit {
});
}

editContent() {
protected editContent() {
if (this.run.lastRun) {
this.dialog.open(EditRunWarningDialogComponent, {
ariaLabel: $localize`Edit Classroom Unit Warning`,
Expand All @@ -91,7 +84,7 @@ export class RunMenuComponent implements OnInit {
}
}

archive(): void {
protected archive(): void {
const run = this.run;
this.archiveProjectService.archiveProject(run.project).subscribe({
next: (response: ArchiveProjectResponse) => {
Expand All @@ -105,7 +98,7 @@ export class RunMenuComponent implements OnInit {
});
}

unarchive(): void {
protected unarchive(): void {
const run = this.run;
this.archiveProjectService.unarchiveProject(run.project).subscribe({
next: (response: ArchiveProjectResponse) => {
Expand Down
21 changes: 21 additions & 0 deletions src/app/teacher/run-menu/run-menu.harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentHarness } from '@angular/cdk/testing';
import { MatMenuHarness } from '@angular/material/menu/testing';

export class RunMenuHarness extends ComponentHarness {
static hostSelector = 'app-run-menu';
protected getMenu = this.locatorFor(MatMenuHarness);

async clickMenuButton(menuButtonText: string): Promise<void> {
const menu = await this.getMenu();
await menu.open();
return menu.clickItem({ text: menuButtonText });
}

async clickArchiveMenuButton(): Promise<void> {
return await this.clickMenuButton('folderArchive');
}

async clickUnarchiveMenuButton(): Promise<void> {
return await this.clickMenuButton('folder_offUnarchive');
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ComponentHarness } from '@angular/cdk/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { MatCardHarness } from '@angular/material/card/testing';
import { RunMenuHarness } from '../run-menu/run-menu.harness';

export class TeacherRunListItemHarness extends ComponentHarness {
static hostSelector = 'app-teacher-run-list-item';
protected getCard = this.locatorFor(MatCardHarness);
protected getCheckbox = this.locatorFor(MatCheckboxHarness);
protected getMenu = this.locatorFor(MatMenuHarness);
protected getMenu = this.locatorFor(RunMenuHarness);

async checkCheckbox(): Promise<void> {
return (await this.getCheckbox()).check();
Expand All @@ -17,18 +17,12 @@ export class TeacherRunListItemHarness extends ComponentHarness {
return (await this.getCheckbox()).isChecked();
}

async clickMenuButton(menuButtonText: string): Promise<void> {
const menu = await this.getMenu();
await menu.open();
return menu.clickItem({ text: menuButtonText });
}

async clickArchiveMenuButton(): Promise<void> {
return await this.clickMenuButton('folderArchive');
return (await this.getMenu()).clickArchiveMenuButton();
}

async clickUnarchiveMenuButton(): Promise<void> {
return await this.clickMenuButton('folder_offUnarchive');
return (await this.getMenu()).clickUnarchiveMenuButton();
}

async getRunTitle(): Promise<string> {
Expand Down

0 comments on commit 328dc03

Please sign in to comment.