Skip to content

Commit

Permalink
feat: numbas-test-numbas-service
Browse files Browse the repository at this point in the history
Added numbas service and numbas service test

daniel
  • Loading branch information
maddernd committed Sep 11, 2023
1 parent 1836cf2 commit c6c14d8
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/app/api/services/numbas.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@ import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map, retry } from 'rxjs/operators';
import API_URL from 'src/app/config/constants/apiURL';

@Injectable({
providedIn: 'root'
})
export class NumbasService {
private readonly API_URL = 'http://localhost:3000/api/numbas_api';
private readonly API_URL = `${API_URL}/numbas_api`;

constructor(private http: HttpClient) {}

/**
* Fetches a specified resource for a given unit and task.
*
* @param unitId - The ID of the unit
* @param taskId - The ID of the task
* @param resourcePath - Path to the desired resource
* @returns An Observable with the Blob of the fetched resource
*/
fetchResource(unitId: string, taskId: string, resourcePath: string): Observable<any> {
const resourceUrl = `${this.API_URL}/${unitId}/${taskId}/${resourcePath}`;
const resourceMimeType = this.getMimeType(resourcePath);

return this.http.get(resourceUrl, { responseType: 'blob' }).pipe(
retry(3), // Retrying up to 3 times before failing
retry(3),
map((blob) => new Blob([blob], { type: resourceMimeType })),
catchError((error: HttpErrorResponse) => {
console.error('Error fetching Numbas resource:', error);
Expand All @@ -25,6 +34,12 @@ export class NumbasService {
);
}

/**
* Determines the MIME type of a resource based on its extension.
*
* @param resourcePath - Path of the resource
* @returns MIME type string corresponding to the resource's extension
*/
getMimeType(resourcePath: string): string {
const extension = resourcePath.split('.').pop()?.toLowerCase();
const mimeTypeMap: { [key: string]: string } = {
Expand All @@ -40,6 +55,15 @@ export class NumbasService {

return mimeTypeMap[extension || ''] || 'text/plain';
}

/**
* Uploads a Numbas test file for a given unit and task.
*
* @param unitId - The ID of the unit
* @param taskId - The ID of the task
* @param file - File object representing the Numbas test to be uploaded
* @returns An Observable with the response from the server
*/
uploadTest(unitId: string, taskId: string, file: File): Observable<any> {
const uploadUrl = `${this.API_URL}/uploadNumbasTest`;
const formData = new FormData();
Expand All @@ -50,7 +74,6 @@ export class NumbasService {

const httpOptions = {
headers: new HttpHeaders({
// You might need to set some headers here depending on your backend requirements
'Accept': 'application/json'
})
};
Expand Down
65 changes: 65 additions & 0 deletions src/app/api/services/spec/numbas.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { NumbasService } from '../numbas.service';
import { HttpRequest } from '@angular/common/http';

describe('NumbasService', () => {
let numbasService: NumbasService;
let httpMock: HttpTestingController;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [NumbasService],
});

numbasService = TestBed.inject(NumbasService);
httpMock = TestBed.inject(HttpTestingController);
});

afterEach(() => {
httpMock.verify();
});

it('should fetch resource as expected', fakeAsync(() => {
const dummyBlob = new Blob(['dummy blob'], { type: 'text/html' });

const unitId = 'sampleUnitId';
const taskId = 'sampleTaskId';
const resourcePath = 'sampleResource.html';

numbasService.fetchResource(unitId, taskId, resourcePath).subscribe((blob) => {
expect(blob.size).toBe(dummyBlob.size);
expect(blob.type).toBe(dummyBlob.type);
});

const req = httpMock.expectOne(`http://localhost:3000/api/numbas_api/${unitId}/${taskId}/${resourcePath}`);
expect(req.request.method).toBe('GET');

req.flush(dummyBlob);

tick();
}));

it('should upload test as expected', fakeAsync(() => {
const dummyResponse = { success: true, message: 'File uploaded successfully' };

const unitId = 'sampleUnitId';
const taskId = 'sampleTaskId';
const file = new File(['dummy content'], 'sample.txt', { type: 'text/plain' });

numbasService.uploadTest(unitId, taskId, file).subscribe((response) => {
expect(response).toEqual(dummyResponse);
});

const req = httpMock.expectOne(`http://localhost:3000/api/numbas_api/uploadNumbasTest`);
expect(req.request.method).toBe('POST');

req.flush(dummyResponse);

tick();
}));

});


0 comments on commit c6c14d8

Please sign in to comment.