Skip to content

Commit 699f290

Browse files
Merge branch 'develop' into grade-by-component
~ Conflicts: ~ src/assets/wise5/directives/summary-display/summary-display.component.ts ~ src/messages.xlf
2 parents 22b15be + 9ebc326 commit 699f290

24 files changed

+863
-960
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { ComponentState } from './componentState';
2+
3+
export class DummyComponentState extends ComponentState {}

src/app/services/summaryService.spec.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { TestBed } from '@angular/core/testing';
2-
import { SummaryService } from '../../assets/wise5/components/summary/summaryService';
3-
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
4-
import { ConfigService } from '../../assets/wise5/services/configService';
51
import { AnnotationService } from '../../assets/wise5/services/annotationService';
2+
import { ConfigService } from '../../assets/wise5/services/configService';
3+
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
64
import { ProjectService } from '../../assets/wise5/services/projectService';
7-
import { TagService } from '../../assets/wise5/services/tagService';
8-
import { SessionService } from '../../assets/wise5/services/sessionService';
95
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
6+
import { SessionService } from '../../assets/wise5/services/sessionService';
7+
import { SummaryService } from '../../assets/wise5/components/summary/summaryService';
8+
import { TagService } from '../../assets/wise5/services/tagService';
9+
import { TestBed } from '@angular/core/testing';
1010

1111
const ALL_PERIODS = 'allPeriods';
1212
const componentId = 'component1';
@@ -37,8 +37,8 @@ const scoreSummaryDisallowedComponentTypes = summaryDisallowedComponentTypes;
3737
describe('SummaryService', () => {
3838
beforeEach(() => {
3939
TestBed.configureTestingModule({
40-
imports: [],
41-
providers: [
40+
imports: [],
41+
providers: [
4242
AnnotationService,
4343
ConfigService,
4444
ProjectService,
@@ -47,8 +47,8 @@ describe('SummaryService', () => {
4747
TagService,
4848
provideHttpClient(withInterceptorsFromDi()),
4949
provideHttpClientTesting()
50-
]
51-
});
50+
]
51+
});
5252
service = TestBed.get(SummaryService);
5353
http = TestBed.get(HttpTestingController);
5454
spyOn(TestBed.inject(ConfigService), 'getRunId').and.returnValue(runId);
@@ -62,6 +62,8 @@ describe('SummaryService', () => {
6262
getLatestClassmateStudentWorkInClass();
6363
getLatestClassmateScoresInPeriod();
6464
getLatestClassmateScoresInClass();
65+
cleanLabel();
66+
convertToNumber();
6567
});
6668

6769
function createComponent() {
@@ -188,3 +190,28 @@ function getLatestClassmateScoresInX(source: string, expectedUrl: string) {
188190
});
189191
http.expectOne(expectedUrl).flush(expectedScores);
190192
}
193+
194+
function cleanLabel() {
195+
describe('cleanLabel', () => {
196+
it('should clean the label', () => {
197+
expect(service.cleanLabel('hello world')).toEqual('Hello World');
198+
});
199+
});
200+
}
201+
202+
function convertToNumber() {
203+
describe('convertToNumber', () => {
204+
it('should convert to number when value is an empty string', () => {
205+
expect(service.convertToNumber('')).toEqual(0);
206+
});
207+
it('should convert to number when value is not a number', () => {
208+
expect(service.convertToNumber('a')).toEqual(0);
209+
});
210+
it('should convert to number when value is a number string', () => {
211+
expect(service.convertToNumber('1')).toEqual(1);
212+
});
213+
it('should convert to number when value is a number', () => {
214+
expect(service.convertToNumber(1)).toEqual(1);
215+
});
216+
});
217+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Annotation } from './Annotation';
2+
3+
export class DummyAnnotation extends Annotation {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { SeriesDataPoint } from './SeriesDataPoint';
2+
3+
export class SeriesData {
4+
private dataPoints: SeriesDataPoint[];
5+
6+
constructor(dataPoints?: SeriesDataPoint[]) {
7+
this.dataPoints = dataPoints ?? [];
8+
}
9+
10+
getDataPoints(): SeriesDataPoint[] {
11+
return this.dataPoints;
12+
}
13+
14+
addDataPoint(dataPoint: SeriesDataPoint): void {
15+
this.dataPoints.push(dataPoint);
16+
}
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export class SeriesDataPoint {
2+
name: string | number;
3+
y: number;
4+
color: string;
5+
6+
constructor(name: string | number, y: number, color?: string) {
7+
this.name = name;
8+
this.y = y;
9+
if (color) {
10+
this.color = color;
11+
}
12+
}
13+
}

src/assets/wise5/components/component/component-student.module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { StudentAssetsDialogModule } from '../../vle/studentAsset/student-assets
77
import { AnimationStudentModule } from '../animation/animation-student/animation-student.module';
88
import { AudioOscillatorStudentModule } from '../audioOscillator/audio-oscillator-student/audio-oscillator.module';
99
import { ConceptMapStudentModule } from '../conceptMap/concept-map-student/concept-map-student.module';
10-
import { DialogGuidanceStudentModule } from '../dialogGuidance/dialogGuidanceStudentModule';
1110
import { DiscussionStudentModule } from '../discussion/discussion-student/discussion-student.module';
1211
import { DrawStudentModule } from '../draw/draw-student/draw-student-module';
1312
import { EmbeddedStudentModule } from '../embedded/embedded-student/embedded-student.module';
@@ -26,6 +25,7 @@ import { ComponentComponent } from './component.component';
2625
import { AiChatStudentModule } from '../aiChat/ai-chat-student/ai-chat-student.module';
2726
import { HelpIconComponent } from '../../themes/default/themeComponents/helpIcon/help-icon.component';
2827
import { MultipleChoiceStudentComponent } from '../multipleChoice/multiple-choice-student/multiple-choice-student.component';
28+
import { DialogGuidanceStudentComponent } from '../dialogGuidance/dialog-guidance-student/dialog-guidance-student.component';
2929

3030
@NgModule({
3131
imports: [
@@ -35,7 +35,7 @@ import { MultipleChoiceStudentComponent } from '../multipleChoice/multiple-choic
3535
CommonModule,
3636
ComponentComponent,
3737
ConceptMapStudentModule,
38-
DialogGuidanceStudentModule,
38+
DialogGuidanceStudentComponent,
3939
DiscussionStudentModule,
4040
DrawStudentModule,
4141
EmbeddedStudentModule,
Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
<computer-avatar-selector
2-
*ngIf="computerAvatarSelectorVisible"
3-
[computerAvatarSettings]="componentContent.computerAvatarSettings"
4-
(chooseAvatarEvent)="selectComputerAvatar($event)"
5-
/>
6-
<mat-card appearance="outlined" *ngIf="!computerAvatarSelectorVisible" class="mat-elevation-z2">
7-
<component-header [component]="component"></component-header>
8-
<dialog-responses
9-
[responses]="responses"
10-
[isWaitingForComputerResponse]="isWaitingForComputerResponse"
11-
[computerAvatar]="computerAvatar"
12-
>
13-
</dialog-responses>
14-
<chat-input
15-
*ngIf="studentCanRespond"
16-
[submitDisabled]="isWaitingForComputerResponse"
17-
(submitEvent)="submitStudentResponse($event)"
18-
></chat-input>
19-
</mat-card>
1+
@if (computerAvatarSelectorVisible) {
2+
<computer-avatar-selector
3+
[computerAvatarSettings]="componentContent.computerAvatarSettings"
4+
(chooseAvatarEvent)="selectComputerAvatar($event)"
5+
/>
6+
} @else {
7+
<mat-card appearance="outlined" class="mat-elevation-z2">
8+
<component-header [component]="component" />
9+
<dialog-responses
10+
[responses]="responses"
11+
[isWaitingForComputerResponse]="isWaitingForComputerResponse"
12+
[computerAvatar]="computerAvatar"
13+
/>
14+
@if (studentCanRespond) {
15+
<chat-input
16+
[submitDisabled]="isWaitingForComputerResponse"
17+
(submitEvent)="submitStudentResponse($event)"
18+
/>
19+
}
20+
</mat-card>
21+
}

src/assets/wise5/components/dialogGuidance/dialog-guidance-student/dialog-guidance-student.component.spec.ts

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
1-
import { provideHttpClientTesting } from '@angular/common/http/testing';
21
import { ComponentFixture, TestBed } from '@angular/core/testing';
3-
import { FormsModule } from '@angular/forms';
4-
import { MatCardModule } from '@angular/material/card';
5-
import { MatDialogModule } from '@angular/material/dialog';
6-
import { MatFormFieldModule } from '@angular/material/form-field';
7-
import { MatIconModule } from '@angular/material/icon';
8-
import { MatInputModule } from '@angular/material/input';
92
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
103
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
114
import { ComputerAvatar } from '../../../common/computer-avatar/ComputerAvatar';
12-
import { ComponentHeaderComponent } from '../../../directives/component-header/component-header.component';
135
import { ComputerAvatarService } from '../../../services/computerAvatarService';
146
import { DialogGuidanceFeedbackService } from '../../../services/dialogGuidanceFeedbackService';
157
import { ProjectService } from '../../../services/projectService';
@@ -19,57 +11,24 @@ import { ComputerDialogResponseMultipleScores } from '../ComputerDialogResponseM
1911
import { ComputerDialogResponseSingleScore } from '../ComputerDialogResponseSingleScore';
2012
import { CRaterResponse } from '../../common/cRater/CRaterResponse';
2113
import { CRaterScore } from '../../common/cRater/CRaterScore';
22-
import { DialogResponsesComponent } from '../dialog-responses/dialog-responses.component';
2314
import { DialogGuidanceService } from '../dialogGuidanceService';
2415
import { DialogGuidanceStudentComponent } from './dialog-guidance-student.component';
2516
import { DialogGuidanceComponent } from '../DialogGuidanceComponent';
2617
import { RawCRaterResponse } from '../../common/cRater/RawCRaterResponse';
27-
import { NO_ERRORS_SCHEMA } from '@angular/core';
28-
import { ChatInputComponent } from '../../../common/chat-input/chat-input.component';
2918
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
3019

3120
let component: DialogGuidanceStudentComponent;
3221
let fixture: ComponentFixture<DialogGuidanceStudentComponent>;
3322
const robotAvatar = new ComputerAvatar('robot', 'Robot', 'robot.png');
34-
35-
function initializeComponent(isComputerAvatarEnabled: boolean): void {
36-
fixture = TestBed.createComponent(DialogGuidanceStudentComponent);
37-
component = fixture.componentInstance;
38-
component.component = createDialogGuidanceComponent(isComputerAvatarEnabled);
39-
spyOn(component, 'subscribeToSubscriptions').and.callFake(() => {});
40-
spyOn(component, 'isNotebookEnabled').and.returnValue(false);
41-
fixture.detectChanges();
42-
}
43-
44-
function createDialogGuidanceComponent(isComputerAvatarEnabled: boolean): DialogGuidanceComponent {
45-
const componentContent = TestBed.inject(DialogGuidanceService).createComponent();
46-
componentContent.isComputerAvatarEnabled = isComputerAvatarEnabled;
47-
return new DialogGuidanceComponent(componentContent, null);
48-
}
49-
5023
describe('DialogGuidanceStudentComponent', () => {
5124
beforeEach(async () => {
5225
await TestBed.configureTestingModule({
53-
declarations: [DialogGuidanceStudentComponent],
54-
schemas: [NO_ERRORS_SCHEMA],
5526
imports: [
5627
BrowserAnimationsModule,
57-
ChatInputComponent,
58-
ComponentHeaderComponent,
59-
DialogResponsesComponent,
60-
FormsModule,
61-
MatCardModule,
62-
MatDialogModule,
63-
MatFormFieldModule,
64-
MatIconModule,
65-
MatInputModule,
28+
DialogGuidanceStudentComponent,
6629
StudentTeacherCommonServicesModule
6730
],
68-
providers: [
69-
DialogGuidanceFeedbackService,
70-
provideHttpClient(withInterceptorsFromDi()),
71-
provideHttpClientTesting()
72-
]
31+
providers: [DialogGuidanceFeedbackService, provideHttpClient(withInterceptorsFromDi())]
7332
}).compileComponents();
7433
});
7534

@@ -101,19 +60,19 @@ describe('DialogGuidanceStudentComponent', () => {
10160
);
10261
component.setIsSubmitDirty(true);
10362
const response = createDummyScoringResponse();
104-
expect(component.responses.length).toEqual(0);
63+
expect(component['responses'].length).toEqual(0);
10564
component.cRaterSuccessResponse(response);
10665
expect(broadcastComponentSubmitTriggeredSpy).toHaveBeenCalled();
107-
expect(component.responses.length).toEqual(1);
66+
expect(component['responses'].length).toEqual(1);
10867
});
10968

11069
it('should disable submit button after using all submits', () => {
11170
component.componentContent.maxSubmitCount = 2;
112-
expect(component.studentCanRespond).toEqual(true);
71+
expect(component['studentCanRespond']).toEqual(true);
11372
simulateSubmit(component);
114-
expect(component.studentCanRespond).toEqual(true);
73+
expect(component['studentCanRespond']).toEqual(true);
11574
simulateSubmit(component);
116-
expect(component.studentCanRespond).toEqual(false);
75+
expect(component['studentCanRespond']).toEqual(false);
11776
});
11877

11978
it('should handle crater error response', () => {
@@ -129,7 +88,7 @@ describe('DialogGuidanceStudentComponent', () => {
12988
it('should initialize computer avatar to default computer avatar', () => {
13089
initializeComponent(false);
13190
expectComputerAvatarSelectorNotToBeShown(component);
132-
expect(component.computerAvatar).not.toBeNull();
91+
expect(component['computerAvatar']).not.toBeNull();
13392
});
13493

13594
it(`should initialize computer avatar when the student has not previously chosen a computer
@@ -183,7 +142,7 @@ describe('DialogGuidanceStudentComponent', () => {
183142

184143
it('should select computer avatar', () => {
185144
component.selectComputerAvatar(robotAvatar);
186-
expect(component.computerAvatar).toEqual(robotAvatar);
145+
expect(component['computerAvatar']).toEqual(robotAvatar);
187146
expectComputerAvatarSelectorNotToBeShown(component);
188147
});
189148

@@ -196,19 +155,34 @@ describe('DialogGuidanceStudentComponent', () => {
196155
const defaultComputerAvatar = computerAvatarService.getDefaultAvatar();
197156
spyOn(computerAvatarService, 'getAvatar').and.returnValue(defaultComputerAvatar);
198157
component.initializeComputerAvatar();
199-
expect(component.computerAvatar).toEqual(defaultComputerAvatar);
158+
expect(component['computerAvatar']).toEqual(defaultComputerAvatar);
200159
});
201160

202161
it('should select computer avatar when there is a computer avatar initial response', () => {
203162
const text = 'Hi there, who lives in a pineapple under sea?';
204163
component.componentContent.computerAvatarSettings.initialResponse = text;
205-
expect(component.responses.length).toEqual(0);
164+
expect(component['responses'].length).toEqual(0);
206165
component.selectComputerAvatar(robotAvatar);
207-
expect(component.responses.length).toEqual(1);
208-
expect(component.responses[0].text).toEqual(text);
166+
expect(component['responses'].length).toEqual(1);
167+
expect(component['responses'][0].text).toEqual(text);
209168
});
210169
});
211170

171+
function initializeComponent(isComputerAvatarEnabled: boolean): void {
172+
fixture = TestBed.createComponent(DialogGuidanceStudentComponent);
173+
component = fixture.componentInstance;
174+
component.component = createDialogGuidanceComponent(isComputerAvatarEnabled);
175+
spyOn(component, 'subscribeToSubscriptions').and.callFake(() => {});
176+
spyOn(component, 'isNotebookEnabled').and.returnValue(false);
177+
fixture.detectChanges();
178+
}
179+
180+
function createDialogGuidanceComponent(isComputerAvatarEnabled: boolean): DialogGuidanceComponent {
181+
const componentContent = TestBed.inject(DialogGuidanceService).createComponent();
182+
componentContent.isComputerAvatarEnabled = isComputerAvatarEnabled;
183+
return new DialogGuidanceComponent(componentContent, null);
184+
}
185+
212186
function simulateSubmit(component: DialogGuidanceStudentComponent): void {
213187
const response = createDummyScoringResponse();
214188
component.setIsSubmitDirty(true);

0 commit comments

Comments
 (0)