-
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.
- Loading branch information
Showing
10 changed files
with
292 additions
and
89 deletions.
There are no files selected for viewing
151 changes: 128 additions & 23 deletions
151
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 |
---|---|---|
@@ -1,47 +1,152 @@ | ||
import { DeepMocked, createMock } from '@golevelup/ts-jest'; | ||
import AdmZip from 'adm-zip'; | ||
import { readFile } from 'node:fs/promises'; | ||
import { CommonCartridgeFileParser } from './common-cartridge-file-parser'; | ||
import { CommonCartridgeManifestParser } from './common-cartridge-manifest-parser'; | ||
import { CommonCartridgeManifestNotFoundException } from './utils/common-cartridge-manifest-not-found.exception'; | ||
|
||
describe('CommonCartridgeFileParser', () => { | ||
let sut: CommonCartridgeFileParser; | ||
let manifestParserMock: DeepMocked<CommonCartridgeManifestParser>; | ||
|
||
const setupFile = async (hasManifest: boolean) => { | ||
let file: Buffer; | ||
|
||
if (hasManifest) { | ||
const manifest = await readFile('./apps/server/src/modules/common-cartridge/testing/assets/v1.1.0/manifest.xml'); | ||
const archive = new AdmZip(); | ||
|
||
archive.addFile('imsmanifest.xml', manifest); | ||
|
||
file = archive.toBuffer(); | ||
} else { | ||
file = new AdmZip().toBuffer(); | ||
} | ||
|
||
return file; | ||
}; | ||
|
||
const setupParser = async (hasManifest: boolean) => { | ||
const file = await setupFile(hasManifest); | ||
|
||
return new CommonCartridgeFileParser(file); | ||
}; | ||
|
||
beforeAll(async () => { | ||
sut = await setupParser(true); | ||
manifestParserMock = createMock<CommonCartridgeManifestParser>(); | ||
|
||
jest.spyOn(CommonCartridgeManifestParser.prototype, 'getSchema').mockReturnValue('IMS Common Cartridge'); | ||
Reflect.set(sut, 'manifestParser', manifestParserMock); | ||
}); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe('constructor', () => { | ||
describe('when manifest file is found', () => { | ||
const setup = (manifestName: string) => { | ||
const archive = new AdmZip(); | ||
const setup = () => setupFile(true); | ||
|
||
archive.addFile(manifestName, Buffer.from('<manifest></manifest>')); | ||
it('should create instance', async () => { | ||
const file = await setup(); | ||
|
||
const file = archive.toBuffer(); | ||
expect(() => new CommonCartridgeFileParser(file)).not.toThrow(); | ||
}); | ||
}); | ||
|
||
return { file }; | ||
}; | ||
describe('when manifest file is not found', () => { | ||
const setup = () => setupFile(false); | ||
|
||
it('should use imsmanifest.xml as manifest', () => { | ||
const { file } = setup('imsmanifest.xml'); | ||
const parser = new CommonCartridgeFileParser(file); | ||
it('should throw CommonCartridgeManifestNotFoundException', async () => { | ||
const file = await setup(); | ||
|
||
expect(parser.manifest).toBeDefined(); | ||
expect(() => new CommonCartridgeFileParser(file)).toThrow(CommonCartridgeManifestNotFoundException); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getSchema', () => { | ||
describe('when schema is found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should use manifest.xml as manifest', () => { | ||
const { file } = setup('manifest.xml'); | ||
const parser = new CommonCartridgeFileParser(file); | ||
it('should return schema', async () => { | ||
const parser = await setup(); | ||
|
||
expect(parser.manifest).toBeDefined(); | ||
const schema = parser.getSchema(); | ||
|
||
expect(schema).toEqual('IMS Common Cartridge'); | ||
}); | ||
}); | ||
|
||
describe('when manifest file is not found', () => { | ||
const setup = () => { | ||
const archive = new AdmZip(); | ||
const file = archive.toBuffer(); | ||
describe('when schema is not found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should return undefined', async () => { | ||
const parser = await setup(); | ||
|
||
const schema = parser.getSchema(); | ||
|
||
expect(schema).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
return { file }; | ||
}; | ||
describe('getVersion', () => { | ||
describe('when version is found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should throw', () => { | ||
const { file } = setup(); | ||
it('should return version', async () => { | ||
const parser = await setup(); | ||
|
||
expect(() => new CommonCartridgeFileParser(file)).toThrow('Manifest file not found'); | ||
const version = parser.getVersion(); | ||
|
||
expect(version).toEqual('1.1.0'); | ||
}); | ||
}); | ||
|
||
describe('when version is not found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should return undefined', async () => { | ||
const parser = await setup(); | ||
|
||
const version = parser.getVersion(); | ||
|
||
expect(version).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getTitle', () => { | ||
describe('when title is found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should return title', async () => { | ||
const parser = await setup(); | ||
|
||
const title = parser.getTitle(); | ||
|
||
expect(title).toEqual('Common Cartridge Manifest'); | ||
}); | ||
}); | ||
|
||
describe('when title is not found', () => { | ||
const setup = () => setupParser(true); | ||
|
||
it('should return undefined', async () => { | ||
const parser = await setup(); | ||
|
||
const title = parser.getTitle(); | ||
|
||
expect(title).toBeUndefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getOrganizations', () => {}); | ||
|
||
describe('getResource', () => {}); | ||
|
||
describe('getResourceAsString', () => {}); | ||
}); |
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
9 changes: 9 additions & 0 deletions
9
apps/server/src/modules/common-cartridge/import/common-cartridge-import.enums.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,9 @@ | ||
export enum CommonCartridgeResourceTypeV1P1 { | ||
UNKNOWN = 'unknown', | ||
WEB_CONTENT = 'webcontent', | ||
WEB_LINK = 'imswl_xmlv1p1', | ||
} | ||
|
||
export enum CommonCartridgeResourceTypeV1P3 { | ||
WEB_LINK = 'imswl_xmlv1p3', | ||
} |
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
44 changes: 44 additions & 0 deletions
44
apps/server/src/modules/common-cartridge/import/common-cartridge-resource-factory.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,44 @@ | ||
import AdmZip from 'adm-zip'; | ||
import { JSDOM } from 'jsdom'; | ||
import { CommonCartridgeResourceTypeV1P1, CommonCartridgeResourceTypeV1P3 } from './common-cartridge-import.enums'; | ||
import { OrganizationProps, ResourceProps, WebLinkResourceProps } from './common-cartridge-import.types'; | ||
|
||
export class CommonCartridgeResourceFactory { | ||
constructor(private readonly archive: AdmZip) {} | ||
|
||
public create(organization: OrganizationProps): ResourceProps | undefined { | ||
if (!this.isValidOrganization(organization)) { | ||
return undefined; | ||
} | ||
|
||
const content = this.archive.readAsText(organization.resourcePath); | ||
|
||
switch (organization.resourceType) { | ||
case CommonCartridgeResourceTypeV1P1.WEB_LINK: | ||
case CommonCartridgeResourceTypeV1P3.WEB_LINK: | ||
return this.createWebLinkResource(content); | ||
default: | ||
return undefined; | ||
} | ||
} | ||
|
||
private isValidOrganization(organization: OrganizationProps): boolean { | ||
const { isResource, isInlined, resourcePath } = organization; | ||
const isValidOrganization = isResource && !isInlined && resourcePath !== ''; | ||
|
||
return isValidOrganization; | ||
} | ||
|
||
private createWebLinkResource(content: string): WebLinkResourceProps { | ||
// TODO: Can throw an error if the content is not a valid XML | ||
const resource = new JSDOM(content, { contentType: 'text/xml' }).window.document; | ||
const title = resource.querySelector('webLink > title')?.textContent || ''; | ||
const url = resource.querySelector('webLink > url')?.getAttribute('href') || ''; | ||
|
||
return { | ||
type: CommonCartridgeResourceTypeV1P1.WEB_LINK, | ||
title, | ||
url, | ||
}; | ||
} | ||
} |
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
Oops, something went wrong.