-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Adding two new feature flags * Adding new common cartridge import module * Adding new REST endpoint for course import
- Loading branch information
Showing
37 changed files
with
1,428 additions
and
28 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
apps/server/src/modules/common-cartridge/import/common-cartridge-file-parser.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import AdmZip from 'adm-zip'; | ||
import { CommonCartridgeFileParser } from './common-cartridge-file-parser'; | ||
|
||
describe('CommonCartridgeFileParser', () => { | ||
describe('constructor', () => { | ||
describe('when manifest file is found', () => { | ||
const setup = (manifestName: string) => { | ||
const archive = new AdmZip(); | ||
|
||
archive.addFile(manifestName, Buffer.from('<manifest></manifest>')); | ||
|
||
const file = archive.toBuffer(); | ||
|
||
return { file }; | ||
}; | ||
|
||
it('should use imsmanifest.xml as manifest', () => { | ||
const { file } = setup('imsmanifest.xml'); | ||
const parser = new CommonCartridgeFileParser(file); | ||
|
||
expect(parser.manifest).toBeDefined(); | ||
}); | ||
|
||
it('should use manifest.xml as manifest', () => { | ||
const { file } = setup('manifest.xml'); | ||
const parser = new CommonCartridgeFileParser(file); | ||
|
||
expect(parser.manifest).toBeDefined(); | ||
}); | ||
}); | ||
|
||
describe('when manifest file is not found', () => { | ||
const setup = () => { | ||
const archive = new AdmZip(); | ||
const file = archive.toBuffer(); | ||
|
||
return { file }; | ||
}; | ||
|
||
it('should throw', () => { | ||
const { file } = setup(); | ||
|
||
expect(() => new CommonCartridgeFileParser(file)).toThrow('Manifest file not found'); | ||
}); | ||
}); | ||
}); | ||
}); |
28 changes: 28 additions & 0 deletions
28
apps/server/src/modules/common-cartridge/import/common-cartridge-file-parser.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import AdmZip from 'adm-zip'; | ||
import { CommonCartridgeManifestParser } from './common-cartridge-manifest-parser'; | ||
import { CommonCartridgeManifestNotFoundException } from './utils/common-cartridge-manifest-not-found.exception'; | ||
|
||
export class CommonCartridgeFileParser { | ||
private readonly manifestParser: CommonCartridgeManifestParser; | ||
|
||
public constructor(file: Buffer) { | ||
const archive = new AdmZip(file); | ||
|
||
this.manifestParser = new CommonCartridgeManifestParser(this.getManifestFileAsString(archive)); | ||
} | ||
|
||
public get manifest(): CommonCartridgeManifestParser { | ||
return this.manifestParser; | ||
} | ||
|
||
private getManifestFileAsString(archive: AdmZip): string | never { | ||
// imsmanifest.xml is the standard name, but manifest.xml is also valid until v1.3 | ||
const manifest = archive.getEntry('imsmanifest.xml') || archive.getEntry('manifest.xml'); | ||
|
||
if (manifest) { | ||
return archive.readAsText(manifest); | ||
} | ||
|
||
throw new CommonCartridgeManifestNotFoundException(); | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
apps/server/src/modules/common-cartridge/import/common-cartridge-manifest-parser.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import AdmZip from 'adm-zip'; | ||
import { readFile } from 'fs/promises'; | ||
import { CommonCartridgeManifestParser } from './common-cartridge-manifest-parser'; | ||
|
||
describe('CommonCartridgeManifestParser', () => { | ||
const setupFile = async (loadFile: boolean) => { | ||
if (!loadFile) { | ||
const sut = new CommonCartridgeManifestParser('<manifest></manifest>'); | ||
|
||
return { sut }; | ||
} | ||
|
||
const buffer = await readFile('./apps/server/test/assets/common-cartridge/us_history_since_1877.imscc'); | ||
const archive = new AdmZip(buffer); | ||
const sut = new CommonCartridgeManifestParser(archive.readAsText('imsmanifest.xml')); | ||
|
||
return { sut }; | ||
}; | ||
|
||
describe('getSchema', () => { | ||
describe('when schema is present', () => { | ||
const setup = async () => setupFile(true); | ||
|
||
it('should return the schema', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getSchema(); | ||
|
||
expect(result).toBe('IMS Common Cartridge'); | ||
}); | ||
}); | ||
|
||
describe('when schema is not present', () => { | ||
const setup = async () => setupFile(false); | ||
|
||
it('should return undefined', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getSchema(); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getVersion', () => { | ||
describe('when version is present', () => { | ||
const setup = async () => setupFile(true); | ||
|
||
it('should return the version', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getVersion(); | ||
|
||
expect(result).toBe('1.3.0'); | ||
}); | ||
}); | ||
|
||
describe('when version is not present', () => { | ||
const setup = async () => setupFile(false); | ||
|
||
it('should return undefined', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getVersion(); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getTitle', () => { | ||
describe('when title is present', () => { | ||
const setup = async () => setupFile(true); | ||
|
||
it('should return the title', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getTitle(); | ||
|
||
expect(result).toBe('201510-AMH-2020-70C-12218-US History Since 1877'); | ||
}); | ||
}); | ||
|
||
describe('when title is not present', () => { | ||
const setup = async () => setupFile(false); | ||
|
||
it('should return null', async () => { | ||
const { sut } = await setup(); | ||
const result = sut.getTitle(); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
}); |
27 changes: 27 additions & 0 deletions
27
apps/server/src/modules/common-cartridge/import/common-cartridge-manifest-parser.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { JSDOM } from 'jsdom'; | ||
|
||
export class CommonCartridgeManifestParser { | ||
private readonly doc: Document; | ||
|
||
public constructor(manifest: string) { | ||
this.doc = new JSDOM(manifest, { contentType: 'text/xml' }).window.document; | ||
} | ||
|
||
public getSchema(): string | undefined { | ||
const result = this.doc.querySelector('manifest > metadata > schema'); | ||
|
||
return result?.textContent ?? undefined; | ||
} | ||
|
||
public getVersion(): string | undefined { | ||
const result = this.doc.querySelector('manifest > metadata > schemaversion'); | ||
|
||
return result?.textContent ?? undefined; | ||
} | ||
|
||
public getTitle(): string | undefined { | ||
const result = this.doc.querySelector('manifest > metadata > lom > general > title > string'); | ||
|
||
return result?.textContent ?? undefined; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { CommonCartridgeFileParser } from './common-cartridge-file-parser'; |
11 changes: 11 additions & 0 deletions
11
apps/server/src/modules/common-cartridge/import/jsdom.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// This is a workaround for the missing types for jsdom, because the types are not included in the package itself. | ||
// This is a declaration file for the JSDOM class, which is used in the CommonCartridgeManifestParser. | ||
// Currently the JSDOM types are bit buggy and don't work properly with our project setup. | ||
|
||
declare module 'jsdom' { | ||
class JSDOM { | ||
constructor(html: string, options?: Record<string, unknown>); | ||
|
||
window: Window; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...dules/common-cartridge/import/utils/common-cartridge-manifest-not-found.exception.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { CommonCartridgeManifestNotFoundException } from './common-cartridge-manifest-not-found.exception'; | ||
|
||
describe('CommonCartridgeManifestNotFoundException', () => { | ||
describe('getLogMessage', () => { | ||
describe('when returning a message', () => { | ||
const setup = () => { | ||
const sut = new CommonCartridgeManifestNotFoundException(); | ||
|
||
return { sut }; | ||
}; | ||
|
||
it('should contain the type', () => { | ||
const { sut } = setup(); | ||
|
||
const result = sut.getLogMessage(); | ||
|
||
expect(result.type).toEqual('WRONG_FILE_FORMAT'); | ||
}); | ||
|
||
it('should contain the stack', () => { | ||
const { sut } = setup(); | ||
|
||
const result = sut.getLogMessage(); | ||
|
||
expect(result.stack).toEqual(sut.stack); | ||
}); | ||
}); | ||
}); | ||
}); |
17 changes: 17 additions & 0 deletions
17
...rc/modules/common-cartridge/import/utils/common-cartridge-manifest-not-found.exception.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { BadRequestException } from '@nestjs/common'; | ||
import { ErrorLogMessage, Loggable } from '@src/core/logger'; | ||
|
||
export class CommonCartridgeManifestNotFoundException extends BadRequestException implements Loggable { | ||
constructor() { | ||
super('Manifest file not found.'); | ||
} | ||
|
||
public getLogMessage(): ErrorLogMessage { | ||
const message: ErrorLogMessage = { | ||
type: 'WRONG_FILE_FORMAT', | ||
stack: this.stack, | ||
}; | ||
|
||
return message; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
apps/server/src/modules/learnroom/controller/dto/course-import.body.params.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
|
||
export class CourseImportBodyParams { | ||
@ApiProperty({ | ||
type: String, | ||
format: 'binary', | ||
required: true, | ||
description: 'The Common Cartridge file to import.', | ||
}) | ||
file!: Express.Multer.File; | ||
} |
Oops, something went wrong.