Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Peer Group): Non admins can not create new peer groupings #1434

Merged
merged 4 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PeerGrouping } from '../../../../../app/domain/peerGrouping';
import { ReferenceComponent } from '../../../../../app/domain/referenceComponent';
import { ProjectService } from '../../../services/projectService';
import { AVAILABLE_LOGIC, AVAILABLE_MODES, PeerGroupingLogic } from '../PeerGroupingLogic';
import { MatSnackBar } from '@angular/material/snack-bar';

@Directive()
export abstract class AuthorPeerGroupingDialogComponent implements OnInit {
Expand All @@ -18,7 +19,8 @@ export abstract class AuthorPeerGroupingDialogComponent implements OnInit {

constructor(
protected dialogRef: MatDialogRef<AuthorPeerGroupingDialogComponent>,
protected projectService: ProjectService
protected projectService: ProjectService,
protected snackBar: MatSnackBar
) {
this.availableLogic = AVAILABLE_LOGIC;
}
Expand Down Expand Up @@ -52,4 +54,15 @@ export abstract class AuthorPeerGroupingDialogComponent implements OnInit {
cancel(): void {
this.dialogRef.close();
}

protected handleError(error: any): void {
switch (error.messageCode) {
case 'genericError':
this.snackBar.open($localize`An error occurred. Please try again.`);
break;
case 'notAuthorized':
this.snackBar.open($localize`You are not allowed to perform this action.`);
break;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { of } from 'rxjs';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { of, throwError } from 'rxjs';
import { PeerGrouping } from '../../../../../app/domain/peerGrouping';
import { ReferenceComponent } from '../../../../../app/domain/referenceComponent';
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
Expand All @@ -13,8 +13,10 @@ const TAG1: string = 'tag1';
const REFERENCE_COMPONENT_NODE_ID1 = 'node1';
const REFERENCE_COMPONENT_COMPONENT_ID1 = 'component1';
let component: CreateNewPeerGroupingDialogComponent;
let createNewPeerGroupingSpy: jasmine.Spy, dialogCloseSpy: jasmine.Spy;
let createNewPeerGroupingSpy: jasmine.Spy;
let dialogCloseSpy: jasmine.Spy;
let fixture: ComponentFixture<CreateNewPeerGroupingDialogComponent>;
let snackBar: MatSnackBar;

describe('CreateNewPeerGroupingDialogComponent', () => {
beforeEach(async () => {
Expand All @@ -30,6 +32,7 @@ describe('CreateNewPeerGroupingDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(CreateNewPeerGroupingDialogComponent);
component = fixture.componentInstance;
snackBar = TestBed.inject(MatSnackBar);
fixture.detectChanges();
});
create();
Expand All @@ -41,6 +44,7 @@ function create() {
create_DifferentIdeasMaximizeLogic_ShouldCreatePeerGroup();
create_DifferentScoresAnyLogic_ShouldCreatePeerGroup();
create_DifferentScoresMaximizeLogic_ShouldCreatePeerGroup();
create_ErrorOccurs_ShowsError();
}

function create_RandomLogic_ShouldCreatePeerGroup() {
Expand Down Expand Up @@ -98,3 +102,41 @@ function expectLogicCreateNewPeerGrouping(logicType: string, mode: string) {
expect(createNewPeerGroupingSpy).toHaveBeenCalledWith(newPeerGrouping);
expect(dialogCloseSpy).toHaveBeenCalled();
}

function create_ErrorOccurs_ShowsError(): void {
describe('create new peer grouping returns error', () => {
create_GenericErrorOccurs_ShowsError();
create_NotAuthorizedErrorOccurs_ShowsError();
});
}

function create_GenericErrorOccurs_ShowsError(): void {
describe('returns generic error', () => {
it('shows generic error message in snackbar', async () => {
returnErrorExpectErrorMessage('genericError', 'An error occurred. Please try again.');
});
});
}

function create_NotAuthorizedErrorOccurs_ShowsError(): void {
describe('returns not authorized error', () => {
it('shows not authorized error in snackbar', async () => {
returnErrorExpectErrorMessage('notAuthorized', 'You are not allowed to perform this action.');
});
});
}

function returnErrorExpectErrorMessage(messageCode: string, errorMessage: string): void {
const snackBarSpy = spyOn(snackBar, 'open');
createNewPeerGroupingSpy.and.returnValue(
throwError(() => {
return {
error: {
messageCode: messageCode
}
};
})
);
component.create();
expect(snackBarSpy).toHaveBeenCalledWith(errorMessage);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export class CreateNewPeerGroupingDialogComponent extends AuthorPeerGroupingDial
protected dialogRef: MatDialogRef<CreateNewPeerGroupingDialogComponent>,
private peerGroupingAuthoringService: PeerGroupingAuthoringService,
protected projectService: ProjectService,
private snackBar: MatSnackBar
protected snackBar: MatSnackBar
) {
super(dialogRef, projectService);
super(dialogRef, projectService, snackBar);
}

ngOnInit(): void {
Expand All @@ -29,13 +29,13 @@ export class CreateNewPeerGroupingDialogComponent extends AuthorPeerGroupingDial
create(): Subscription {
this.peerGrouping.tag = this.peerGroupingAuthoringService.getUniqueTag();
this.updatePeerGroupingLogic();
return this.peerGroupingAuthoringService.createNewPeerGrouping(this.peerGrouping).subscribe(
() => {
return this.peerGroupingAuthoringService.createNewPeerGrouping(this.peerGrouping).subscribe({
next: () => {
this.dialogRef.close();
},
() => {
this.snackBar.open($localize`Please try again (Error: duplicate tag).`);
error: ({ error }) => {
this.handleError(error);
}
);
});
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { of, throwError } from 'rxjs';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { PeerGroupingAuthoringService } from '../../../services/peerGroupingAuthoringService';
import { PeerGroupingTestingModule } from '../peer-grouping-testing.module';
import { EditPeerGroupingDialogComponent } from './edit-peer-grouping-dialog.component';
import { PeerGrouping } from '../../../../../app/domain/peerGrouping';
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
import { DIFFERENT_IDEAS_VALUE, DIFFERENT_SCORES_VALUE } from '../PeerGroupingLogic';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';

let component: EditPeerGroupingDialogComponent;
const componentId1 = 'component1';
let dialogCloseSpy: jasmine.Spy;
let fixture: ComponentFixture<EditPeerGroupingDialogComponent>;
const modeAny: string = 'any';
const modeMaximize: string = 'maximize';
const nodeId1 = 'node1';
const modeMaximize: string = 'maximize';
let snackBar: MatSnackBar;
let peerGroupingAuthoringService;
let updatePeerGroupingSpy: jasmine.Spy;

describe('EditPeerGroupingDialogComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PeerGroupingTestingModule, StudentTeacherCommonServicesModule],
imports: [MatSnackBarModule, PeerGroupingTestingModule, StudentTeacherCommonServicesModule],
declarations: [EditPeerGroupingDialogComponent],
providers: [
{
Expand All @@ -36,7 +40,10 @@ describe('EditPeerGroupingDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(EditPeerGroupingDialogComponent);
component = fixture.componentInstance;
peerGroupingAuthoringService = TestBed.inject(PeerGroupingAuthoringService);
updatePeerGroupingSpy = spyOn(peerGroupingAuthoringService, 'updatePeerGrouping');
dialogCloseSpy = spyOn(TestBed.inject(MatDialogRef), 'close');
snackBar = TestBed.inject(MatSnackBar);
fixture.detectChanges();
});

Expand All @@ -46,56 +53,86 @@ describe('EditPeerGroupingDialogComponent', () => {
});

function savePeerGrouping() {
it('should save peer grouping', async () => {
const settings = new PeerGrouping();
component.peerGrouping = settings;
const updatePeerGroupingSpy = spyOn(
TestBed.inject(PeerGroupingAuthoringService),
'updatePeerGrouping'
).and.returnValue(of(settings));
component.save();
expect(updatePeerGroupingSpy).toHaveBeenCalledWith(settings);
expect(dialogCloseSpy).toHaveBeenCalled();
});
describe('save is clicked', () => {
describe('save to backend is successful', () => {
it('closes the dialog', async () => {
const settings = new PeerGrouping();
component.peerGrouping = settings;
updatePeerGroupingSpy.and.returnValue(of(settings));
component.save();
expect(updatePeerGroupingSpy).toHaveBeenCalledWith(settings);
expect(dialogCloseSpy).toHaveBeenCalled();
});
});

it('should save peer grouping with random logic', () => {
savePeerGroupingWithLogic('random', null, 'random');
});
describe('peer grouping logic is random', () => {
it('properly generates the random logic string', () => {
savePeerGroupingWithLogic('random', null, 'random');
});
});

it('should save peer grouping with manual logic', () => {
savePeerGroupingWithLogic('manual', null, 'manual');
});
describe('peer grouping logic is manual', () => {
it('properly generates the manual logic string', () => {
savePeerGroupingWithLogic('manual', null, 'manual');
});
});

it('should save peer grouping with different ideas any logic', () => {
savePeerGroupingWithLogic(
DIFFERENT_IDEAS_VALUE,
modeAny,
`${DIFFERENT_IDEAS_VALUE}("${nodeId1}", "${componentId1}", "${modeAny}")`
);
});
describe('peer grouping logic is different ideas', () => {
it('properly generates the different ideas logic string', () => {
savePeerGroupingWithLogic(
DIFFERENT_IDEAS_VALUE,
modeAny,
`${DIFFERENT_IDEAS_VALUE}("${nodeId1}", "${componentId1}", "${modeAny}")`
);
});
});

it('should save peer grouping with different ideas maximize logic', () => {
savePeerGroupingWithLogic(
DIFFERENT_IDEAS_VALUE,
modeMaximize,
`${DIFFERENT_IDEAS_VALUE}("${nodeId1}", "${componentId1}", "${modeMaximize}")`
);
});
describe('peer grouping logic is different ideas maximize logic', () => {
it('properly generates the different ideas maximize logic string', () => {
savePeerGroupingWithLogic(
DIFFERENT_IDEAS_VALUE,
modeMaximize,
`${DIFFERENT_IDEAS_VALUE}("${nodeId1}", "${componentId1}", "${modeMaximize}")`
);
});
});

it('should save peer grouping with different scores any logic', () => {
savePeerGroupingWithLogic(
DIFFERENT_SCORES_VALUE,
modeAny,
`${DIFFERENT_SCORES_VALUE}("${nodeId1}", "${componentId1}", "${modeAny}")`
);
});
describe('peer grouping logic is different scores', () => {
it('properly generates the different scores logic string', () => {
savePeerGroupingWithLogic(
DIFFERENT_SCORES_VALUE,
modeAny,
`${DIFFERENT_SCORES_VALUE}("${nodeId1}", "${componentId1}", "${modeAny}")`
);
});
});

describe('peer grouping logic is different scores maximize logic', () => {
it('proplery generates the different scores maximize logic string', () => {
savePeerGroupingWithLogic(
DIFFERENT_SCORES_VALUE,
modeMaximize,
`${DIFFERENT_SCORES_VALUE}("${nodeId1}", "${componentId1}", "${modeMaximize}")`
);
});
});

it('should save peer grouping with different scores maximize logic', () => {
savePeerGroupingWithLogic(
DIFFERENT_SCORES_VALUE,
modeMaximize,
`${DIFFERENT_SCORES_VALUE}("${nodeId1}", "${componentId1}", "${modeMaximize}")`
);
describe('save to backend returns not authorized error', () => {
it('shows not authorized error', () => {
const snackBarSpy = spyOn(snackBar, 'open');
updatePeerGroupingSpy.and.returnValue(
throwError(() => {
return {
error: {
messageCode: 'notAuthorized'
}
};
})
);
component.save();
expect(snackBarSpy).toHaveBeenCalledWith('You are not allowed to perform this action.');
});
});
});
}

Expand All @@ -108,24 +145,26 @@ function savePeerGroupingWithLogic(logicType: string, mode: string, expectedLogi
componentId: 'component1'
};
component.mode = mode;
spyOn(TestBed.inject(PeerGroupingAuthoringService), 'updatePeerGrouping').and.returnValue(
of(peerGrouping)
);
updatePeerGroupingSpy.and.returnValue(of(peerGrouping));
component.save();
expect(component.peerGrouping.logic).toEqual(expectedLogic);
}

function deletePeerGrouping() {
it('should delete peer grouping', () => {
spyOn(window, 'confirm').and.returnValue(true);
component.delete();
expect(dialogCloseSpy).toHaveBeenCalled();
describe('delete is clicked', () => {
it('deletes peer grouping', () => {
spyOn(window, 'confirm').and.returnValue(true);
component.delete();
expect(dialogCloseSpy).toHaveBeenCalled();
});
});
}

function cancelPeerGrouping() {
it('should cancel peer grouping', () => {
component.cancel();
expect(dialogCloseSpy).toHaveBeenCalled();
describe('cancel is clicked', () => {
it('cancels peer grouping', () => {
component.cancel();
expect(dialogCloseSpy).toHaveBeenCalled();
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DIFFERENT_SCORES_REGEX,
DIFFERENT_SCORES_VALUE
} from '../PeerGroupingLogic';
import { MatSnackBar } from '@angular/material/snack-bar';

@Component({
selector: 'edit-peer-grouping-dialog',
Expand All @@ -23,9 +24,10 @@ export class EditPeerGroupingDialogComponent extends AuthorPeerGroupingDialogCom
@Inject(MAT_DIALOG_DATA) public peerGrouping: PeerGrouping,
protected dialogRef: MatDialogRef<EditPeerGroupingDialogComponent>,
private peerGroupingAuthoringService: PeerGroupingAuthoringService,
protected projectService: ProjectService
protected projectService: ProjectService,
protected snackBar: MatSnackBar
) {
super(dialogRef, projectService);
super(dialogRef, projectService, snackBar);
}

ngOnInit(): void {
Expand Down Expand Up @@ -53,8 +55,13 @@ export class EditPeerGroupingDialogComponent extends AuthorPeerGroupingDialogCom

save(): void {
this.updatePeerGroupingLogic();
this.peerGroupingAuthoringService.updatePeerGrouping(this.peerGrouping).subscribe(() => {
this.dialogRef.close();
this.peerGroupingAuthoringService.updatePeerGrouping(this.peerGrouping).subscribe({
next: () => {
this.dialogRef.close();
},
error: ({ error }) => {
this.handleError(error);
}
});
}

Expand Down
Loading