Skip to content

Commit 5dd0a22

Browse files
andrewsignori-aotguru-aot
authored andcommitted
#1683 - Completed application - E2E tests for application tracker (#1832)
- Fix for PIR decline throwing an error while completing the process. - Refactor application progress details to get rid of the Sonarcloud issue. - Icon spacing adjusted (@hellolynn-tbtb is aware of and approved it). - Renamed factory method saveFakeApplicationCOE to saveFakeApplicationDisbursements allowing it to be used for these E2E tests also. - Removed prefix ${ClientTypeBaseRoute.Institution} from some E2E that were wrongly added. - E2E tests for the new endpoint added for the completed status. ApplicationStudentsController(e2e)-getCompletedApplicationDetails ✓ Should throw NotFoundException when the application is not associated with the authenticated student. (390 ms) ✓ Should throw NotFoundException when the application is not in 'Completed' status. (75 ms) ✓ Should get application details when application is in 'Completed' status. (76 ms) ✓ Should get application details with scholastic standing change type when application has a scholastic standing 'Student did not complete program associated with. (60 ms) ✓ Should get application details with the most updated appeal status when the application has more than one student appeals associated with. (78 ms)
1 parent 47c6a88 commit 5dd0a22

16 files changed

+634
-265
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
import { HttpStatus, INestApplication } from "@nestjs/common";
2+
import * as request from "supertest";
3+
import { DataSource, Repository } from "typeorm";
4+
import {
5+
BEARER_AUTH_TYPE,
6+
createTestingAppModule,
7+
FakeStudentUsersTypes,
8+
getStudentToken,
9+
getStudentByFakeStudentUserType,
10+
} from "../../../testHelpers";
11+
import {
12+
createFakeStudentAppeal,
13+
createFakeStudentAppealRequest,
14+
createFakeStudentScholasticStanding,
15+
createFakeUser,
16+
saveFakeApplicationDisbursements,
17+
} from "@sims/test-utils";
18+
import {
19+
Application,
20+
ApplicationStatus,
21+
COEStatus,
22+
DisbursementSchedule,
23+
Student,
24+
StudentAppeal,
25+
StudentAppealStatus,
26+
StudentScholasticStanding,
27+
StudentScholasticStandingChangeType,
28+
User,
29+
} from "@sims/sims-db";
30+
import { addDays } from "@sims/utilities";
31+
32+
describe("ApplicationStudentsController(e2e)-getCompletedApplicationDetails", () => {
33+
let app: INestApplication;
34+
let appDataSource: DataSource;
35+
let applicationRepo: Repository<Application>;
36+
let disbursementScheduleRepo: Repository<DisbursementSchedule>;
37+
let studentScholasticStandingRepo: Repository<StudentScholasticStanding>;
38+
let studentAppealRepo: Repository<StudentAppeal>;
39+
let submittedByInstitutionUser: User;
40+
let student: Student;
41+
42+
beforeAll(async () => {
43+
const { nestApplication, dataSource } = await createTestingAppModule();
44+
app = nestApplication;
45+
appDataSource = dataSource;
46+
const userRepo = dataSource.getRepository(User);
47+
applicationRepo = dataSource.getRepository(Application);
48+
disbursementScheduleRepo = dataSource.getRepository(DisbursementSchedule);
49+
studentScholasticStandingRepo = dataSource.getRepository(
50+
StudentScholasticStanding,
51+
);
52+
studentAppealRepo = dataSource.getRepository(StudentAppeal);
53+
submittedByInstitutionUser = await userRepo.save(createFakeUser());
54+
student = await getStudentByFakeStudentUserType(
55+
FakeStudentUsersTypes.FakeStudentUserType1,
56+
dataSource,
57+
);
58+
});
59+
60+
it("Should throw NotFoundException when the application is not associated with the authenticated student.", async () => {
61+
// Arrange
62+
// The application will be generated with a fake user.
63+
const application = await saveFakeApplicationDisbursements(
64+
appDataSource,
65+
undefined,
66+
{ applicationStatus: ApplicationStatus.Completed },
67+
);
68+
const endpoint = `/students/application/${application.id}/completed`;
69+
const token = await getStudentToken(
70+
FakeStudentUsersTypes.FakeStudentUserType1,
71+
);
72+
// Act/Assert
73+
await request(app.getHttpServer())
74+
.get(endpoint)
75+
.auth(token, BEARER_AUTH_TYPE)
76+
.expect(HttpStatus.NOT_FOUND)
77+
.expect({
78+
statusCode: 404,
79+
message: "Application not found or not on Completed status.",
80+
error: "Not Found",
81+
});
82+
});
83+
84+
it("Should throw NotFoundException when the application is not in 'Completed' status.", async () => {
85+
// Arrange
86+
const application = await saveFakeApplicationDisbursements(
87+
appDataSource,
88+
{ student },
89+
{ createSecondDisbursement: true },
90+
);
91+
const endpoint = `/students/application/${application.id}/completed`;
92+
const token = await getStudentToken(
93+
FakeStudentUsersTypes.FakeStudentUserType1,
94+
);
95+
// Act/Assert
96+
await request(app.getHttpServer())
97+
.get(endpoint)
98+
.auth(token, BEARER_AUTH_TYPE)
99+
.expect(HttpStatus.NOT_FOUND)
100+
.expect({
101+
statusCode: 404,
102+
message: "Application not found or not on Completed status.",
103+
error: "Not Found",
104+
});
105+
});
106+
107+
it("Should get application details when application is in 'Completed' status.", async () => {
108+
// Arrange
109+
const application = await saveFakeApplicationDisbursements(
110+
appDataSource,
111+
{ student },
112+
{ createSecondDisbursement: true },
113+
);
114+
application.applicationStatus = ApplicationStatus.Completed;
115+
await applicationRepo.save(application);
116+
const [firstDisbursement, secondDisbursement] =
117+
application.currentAssessment.disbursementSchedules;
118+
firstDisbursement.coeStatus = COEStatus.completed;
119+
await disbursementScheduleRepo.save(firstDisbursement);
120+
const endpoint = `/students/application/${application.id}/completed`;
121+
const token = await getStudentToken(
122+
FakeStudentUsersTypes.FakeStudentUserType1,
123+
);
124+
// Act/Assert
125+
await request(app.getHttpServer())
126+
.get(endpoint)
127+
.auth(token, BEARER_AUTH_TYPE)
128+
.expect(HttpStatus.OK)
129+
.expect({
130+
firstDisbursement: {
131+
coeStatus: firstDisbursement.coeStatus,
132+
disbursementScheduleStatus:
133+
firstDisbursement.disbursementScheduleStatus,
134+
},
135+
secondDisbursement: {
136+
coeStatus: secondDisbursement.coeStatus,
137+
disbursementScheduleStatus:
138+
secondDisbursement.disbursementScheduleStatus,
139+
},
140+
assessmentTriggerType: application.currentAssessment.triggerType,
141+
});
142+
});
143+
144+
it(`Should get application details with scholastic standing change type when application has a scholastic standing '${StudentScholasticStandingChangeType.StudentDidNotCompleteProgram} associated with.`, async () => {
145+
// Arrange
146+
const application = await saveFakeApplicationDisbursements(
147+
appDataSource,
148+
{
149+
student,
150+
},
151+
{ applicationStatus: ApplicationStatus.Completed },
152+
);
153+
const [firstDisbursement] =
154+
application.currentAssessment.disbursementSchedules;
155+
await disbursementScheduleRepo.save(firstDisbursement);
156+
// Create a scholastic standing and have it associated with the completed application.
157+
// 'Student did not complete program' is the only 'scholastic standing that does not generate an assessment.
158+
// The below record has only a relationship with the application which must be enough to
159+
// have the scholasticStandingChangeType returned.
160+
const scholasticStanding = createFakeStudentScholasticStanding({
161+
submittedBy: submittedByInstitutionUser,
162+
application,
163+
});
164+
await studentScholasticStandingRepo.save(scholasticStanding);
165+
166+
const endpoint = `/students/application/${application.id}/completed`;
167+
const token = await getStudentToken(
168+
FakeStudentUsersTypes.FakeStudentUserType1,
169+
);
170+
// Act/Assert
171+
await request(app.getHttpServer())
172+
.get(endpoint)
173+
.auth(token, BEARER_AUTH_TYPE)
174+
.expect(HttpStatus.OK)
175+
.expect({
176+
firstDisbursement: {
177+
coeStatus: firstDisbursement.coeStatus,
178+
disbursementScheduleStatus:
179+
firstDisbursement.disbursementScheduleStatus,
180+
},
181+
assessmentTriggerType: application.currentAssessment.triggerType,
182+
scholasticStandingChangeType:
183+
StudentScholasticStandingChangeType.StudentDidNotCompleteProgram,
184+
});
185+
});
186+
187+
it(`Should get application details with the most updated appeal status when the application has more than one student appeals associated with.`, async () => {
188+
// Arrange
189+
const application = await saveFakeApplicationDisbursements(
190+
appDataSource,
191+
{ student },
192+
{ applicationStatus: ApplicationStatus.Completed },
193+
);
194+
const [firstDisbursement] =
195+
application.currentAssessment.disbursementSchedules;
196+
// Create approved student appeal submitted yesterday.
197+
const approvedAppealRequest = createFakeStudentAppealRequest();
198+
approvedAppealRequest.appealStatus = StudentAppealStatus.Approved;
199+
const approvedAppeal = createFakeStudentAppeal({
200+
application,
201+
appealRequests: [approvedAppealRequest],
202+
});
203+
approvedAppeal.submittedDate = addDays(-1);
204+
// Create pending student appeal submitted today.
205+
const pendingAppealRequest = createFakeStudentAppealRequest();
206+
pendingAppealRequest.appealStatus = StudentAppealStatus.Pending;
207+
const pendingAppeal = createFakeStudentAppeal({
208+
application,
209+
appealRequests: [pendingAppealRequest],
210+
});
211+
await studentAppealRepo.save([approvedAppeal, pendingAppeal]);
212+
213+
const endpoint = `/students/application/${application.id}/completed`;
214+
const token = await getStudentToken(
215+
FakeStudentUsersTypes.FakeStudentUserType1,
216+
);
217+
// Act/Assert
218+
await request(app.getHttpServer())
219+
.get(endpoint)
220+
.auth(token, BEARER_AUTH_TYPE)
221+
.expect(HttpStatus.OK)
222+
.expect({
223+
firstDisbursement: {
224+
coeStatus: firstDisbursement.coeStatus,
225+
disbursementScheduleStatus:
226+
firstDisbursement.disbursementScheduleStatus,
227+
},
228+
assessmentTriggerType: application.currentAssessment.triggerType,
229+
appealStatus: StudentAppealStatus.Pending,
230+
});
231+
});
232+
233+
afterAll(async () => {
234+
await app?.close();
235+
});
236+
});

sources/packages/backend/apps/api/src/route-controllers/confirmation-of-enrollment/_tests_/e2e/confirmation-of-enrollment.aest.confirmEnrollment.e2e-spec.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import {
99
getAuthRelatedEntities,
1010
InstitutionTokenTypes,
1111
} from "../../../../testHelpers";
12-
import { createFakeInstitutionLocation } from "@sims/test-utils";
13-
import { saveFakeApplicationCOE } from "@sims/test-utils/factories/confirmation-of-enrollment";
12+
import {
13+
createFakeInstitutionLocation,
14+
saveFakeApplicationDisbursements,
15+
} from "@sims/test-utils";
1416
import {
1517
Application,
1618
ApplicationStatus,
@@ -19,9 +21,8 @@ import {
1921
InstitutionLocation,
2022
} from "@sims/sims-db";
2123
import { addDays, getISODateOnlyString } from "@sims/utilities";
22-
import { ClientTypeBaseRoute } from "../../../../types";
2324

24-
describe(`${ClientTypeBaseRoute.AEST}-ConfirmationOfEnrollmentInstitutionsController(e2e)-confirmEnrollment`, () => {
25+
describe("ConfirmationOfEnrollmentInstitutionsController(e2e)-confirmEnrollment", () => {
2526
let app: INestApplication;
2627
let appDataSource: DataSource;
2728
let applicationRepo: Repository<Application>;
@@ -46,10 +47,14 @@ describe(`${ClientTypeBaseRoute.AEST}-ConfirmationOfEnrollmentInstitutionsContro
4647

4748
it("Should allow the COE confirmation when COE is outside the valid COE window.", async () => {
4849
// Arrange
49-
const application = await saveFakeApplicationCOE(appDataSource, {
50-
institution: collegeC,
51-
institutionLocation: collegeCLocation,
52-
});
50+
const application = await saveFakeApplicationDisbursements(
51+
appDataSource,
52+
{
53+
institution: collegeC,
54+
institutionLocation: collegeCLocation,
55+
},
56+
{ applicationStatus: ApplicationStatus.Enrolment },
57+
);
5358
const [firstDisbursementSchedule] =
5459
application.currentAssessment.disbursementSchedules;
5560
const offeringEndDate = application.currentAssessment.offering.studyEndDate;

0 commit comments

Comments
 (0)