UNPKG

isoxml-angular

Version:

JavaScript library to parse and generate ISOXML (ISO11783-10) files

296 lines (295 loc) 18.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = require("fs"); const jszip_1 = __importDefault(require("jszip")); const ISOXMLManager_1 = require("./ISOXMLManager"); const xmlManager_1 = require("./xmlManager"); // make sure that Array and Object prototype pollution doesn't break the library Array.prototype.anyCustomMethod = () => 0; Object.prototype.anyCustomMethod = () => 0; function modifyZip(filename, modifier) { return __awaiter(this, void 0, void 0, function* () { const data = (0, fs_1.readFileSync)(filename); const zip = yield jszip_1.default.loadAsync(data); yield modifier(zip); return yield zip.generateAsync({ type: 'uint8array' }); }); } describe('ISOXML Manager', () => { it('should parse ISOXML as ZIP', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/test1.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.rootElement).toBeTruthy(); expect(isoxmlManager.getWarnings()).toHaveLength(0); })); it('should parse TASKDATA.XML as string', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/test1.zip'); const zip = yield jszip_1.default.loadAsync(isoxmlData); const taskDataStr = yield zip.file("TASKDATA/TASKDATA.XML").async('string'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(taskDataStr, 'application/xml'); expect(isoxmlManager.rootElement).toBeTruthy(); expect(isoxmlManager.rootElement.attributes.Task).toHaveLength(2); expect(isoxmlManager.options.rootFolder).toBe(''); })); it('should parse ISOXML with external files', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/2021-04-09T15_33_26_taskdata.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.rootElement.attributes.Task).toBeTruthy(); expect(isoxmlManager.getReferenceByXmlId('TSK-1').entity).toBeTruthy(); expect(isoxmlManager.rootElement.attributes.ExternalFileReference).toHaveLength(0); expect(isoxmlManager.getWarnings()).toHaveLength(2); // const data = await isoxmlManager.saveISOXML() // writeFileSync('./data/test1_out.zip', data) })); it('should parse and save grid files', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/task_with_grid.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(1); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test_grid_out.zip', data) expect(data.length).toBe(14065); const zip = yield jszip_1.default.loadAsync(data); expect(zip.file("TASKDATA/GRD00001.bin")).toBeTruthy(); })); it('should parse and save timelog files', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/2021-04-09T15_33_26_taskdata.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(2); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test_timelog_out.zip', data) const zip = yield jszip_1.default.loadAsync(data); expect(zip.file("TASKDATA/TLG00001.xml")).toBeTruthy(); expect(zip.file("TASKDATA/TLG00001.bin")).toBeTruthy(); })); it('should preserve attached files', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/task_full.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(0); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test_grid_out.zip', data) const zip = yield jszip_1.default.loadAsync(data); expect(zip.file("TASKDATA/TEST1234.BIN")).toBeTruthy(); })); it('should preserve proprietary attributes and elements', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/task_full.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(0); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test_grid_out.zip', data) const isoxmlManager2 = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager2.parseISOXMLFile(data, 'application/zip'); expect(isoxmlManager2.getWarnings()).toHaveLength(0); expect(isoxmlManager2.rootElement.attributes.ProprietaryTags).toHaveProperty('P1234_Area'); expect(isoxmlManager2.rootElement.attributes.BaseStation[0].attributes.ProprietaryAttributes).toHaveProperty('P123_Area'); })); it('should parse and save ISOXML', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/test1.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(0); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test1_out.zip', data) expect(data.length).toBe(4044); })); it('should manually create ISOXML', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const task = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); isoxmlManager.registerEntity(task); isoxmlManager.rootElement.attributes.Task = [task]; const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test1_out.zip', data) expect(data.length).toBe(470); const zip = yield jszip_1.default.loadAsync(data); expect(zip.file("TASKDATA/TASKDATA.XML")).toBeTruthy(); })); it('should handle strings with special characters properly', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const task = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); isoxmlManager.registerEntity(task); isoxmlManager.rootElement.attributes.Task = [task]; isoxmlManager.updateOptions({ fmisTitle: `&<>'"` }); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/out_characters.zip', data) const isoxmlManager2 = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager2.parseISOXMLFile(data, 'application/zip'); expect(isoxmlManager2.options.fmisTitle).toBe(`&<>'"`); })); it('should preserve FMIS IDs', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager({ fmisURI: 'http://example.com' }); const task = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); const ref = isoxmlManager.registerEntity(task, null, '777'); isoxmlManager.rootElement.attributes.Task = [task]; const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test1_out.zip', data) const isoxmlManager2 = new ISOXMLManager_1.ISOXMLManager({ fmisURI: 'http://example.com' }); yield isoxmlManager2.parseISOXMLFile(data, 'application/zip'); const parsedRef = isoxmlManager2.getReferenceByXmlId(ref.xmlId); expect(parsedRef.fmisId).toBe('777'); })); it('should support "rootFolder" option', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager({ rootFolder: "testFolder" }); const task = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); isoxmlManager.registerEntity(task); isoxmlManager.rootElement.attributes.Task = [task]; const data = yield isoxmlManager.saveISOXML(); const zip = yield jszip_1.default.loadAsync(data); expect(zip.file("testFolder/TASKDATA.XML")).toBeTruthy(); })); it('should generate unique filenames', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const firstName = isoxmlManager.generateUniqueFilename("GRD" /* TAGS.Grid */); expect(firstName).toBe('GRD00001'); isoxmlManager.addFileToSave('', firstName + '.BIN'); const secondName = isoxmlManager.generateUniqueFilename("GRD" /* TAGS.Grid */); expect(secondName).toBe('GRD00002'); })); it('should not save V4Only elements in V3', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/task_full.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(0); isoxmlManager.updateOptions({ version: 3 }); const data = yield isoxmlManager.saveISOXML(); // writeFileSync('./data/test_grid_out.zip', data) const isoxmlManager2 = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager2.parseISOXMLFile(data, 'application/zip'); expect(isoxmlManager2.getWarnings()).toHaveLength(0); expect(isoxmlManager2.options.version).toBe(3); expect(isoxmlManager2.rootElement.attributes).not.toHaveProperty('BaseStation'); expect(isoxmlManager2.rootElement.attributes.CropType[0].attributes).not.toHaveProperty('ProductGroupIdRef'); })); it('should add warnings', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/task_with_warnings.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); const warnings = isoxmlManager.getWarnings(); expect(warnings).toHaveLength(3); expect(warnings.find(warn => warn.startsWith('[TSK1->TZN[1]]'))).toBeTruthy(); expect(warnings.find(warn => warn.startsWith('[TSK1]'))).toBeTruthy(); })); it('getParsedFile should not throw errors', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlData = (0, fs_1.readFileSync)('./data/test1.zip'); const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); expect(isoxmlManager.getParsedFile('not_existing.xml', false)).toBeNull(); yield isoxmlManager.parseISOXMLFile(new Uint8Array(isoxmlData.buffer), 'application/zip'); expect(isoxmlManager.getParsedFile('not_existing.xml', false)).toBeNull(); })); it('getEntityByXmlId should not throw errors', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); expect(isoxmlManager.getEntityByXmlId('XXX')).toBeNull(); })); it('should handle unknown data types', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield expect(isoxmlManager.parseISOXMLFile('XXX', 'unknown/type')).rejects.toThrow(); })); it('should handle invalid XML', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const invalidXML = (0, xmlManager_1.js2xml)({ 'tag': 'value' }); yield expect(isoxmlManager.parseISOXMLFile(invalidXML, 'application/xml')).rejects.toThrow(); const zipWriter = new jszip_1.default(); zipWriter.file('TASKDATA/TASKDATA.XML', invalidXML); const zip = yield zipWriter.generateAsync({ type: 'uint8array' }); yield expect(isoxmlManager.parseISOXMLFile(zip, 'application/zip')).rejects.toThrow(); })); it('should add a warning for zip files with multiple main files', () => __awaiter(void 0, void 0, void 0, function* () { // create updated file const updatedZip = yield modifyZip('./data/test1.zip', (zip) => __awaiter(void 0, void 0, void 0, function* () { const taskDataStr = yield zip.file("TASKDATA/TASKDATA.XML").async('string'); zip.file("TASKDATA_NEW/TASKDATA.XML", taskDataStr); })); // parse updated file const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(updatedZip, 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(1); })); it('should read main file from any directory', () => __awaiter(void 0, void 0, void 0, function* () { // create updated file const updatedZip = yield modifyZip('./data/test1.zip', (zip) => __awaiter(void 0, void 0, void 0, function* () { const taskDataStr = yield zip.file("TASKDATA/TASKDATA.XML").async('string'); zip.remove("TASKDATA/TASKDATA.XML"); zip.file("TASKDATA_NEW/TASKDATA.xml", taskDataStr); })); // parse updated file const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(updatedZip, 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(1); })); it('should add a warning for zip files with wrong letter case', () => __awaiter(void 0, void 0, void 0, function* () { // create updated file const updatedZip = yield modifyZip('./data/test1.zip', (zip) => __awaiter(void 0, void 0, void 0, function* () { const taskDataStr = yield zip.file("TASKDATA/TASKDATA.XML").async('string'); zip.remove("TASKDATA/TASKDATA.XML"); zip.file("TASKDATA/TaskData.xml", taskDataStr); })); // parse updated file const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield isoxmlManager.parseISOXMLFile(updatedZip, 'application/zip'); expect(isoxmlManager.getWarnings()).toHaveLength(1); })); it('should not parse zip files without main file', () => __awaiter(void 0, void 0, void 0, function* () { // create updated file const updatedZip = yield modifyZip('./data/test1.zip', (zip) => __awaiter(void 0, void 0, void 0, function* () { zip.remove("TASKDATA/TASKDATA.XML"); })); // parse updated file const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); yield expect(isoxmlManager.parseISOXMLFile(updatedZip, 'application/zip')).rejects.toThrow(); })); it('should return null for unknown entity types', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); expect(isoxmlManager.createEntityFromAttributes('unknown_tag', {})).toBeNull(); expect(isoxmlManager.createEntityFromXML('unknown_tag', {})).toBeNull(); })); describe('registerEntity', () => { it('should catch inconsistency errors in entities', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const task = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); expect(isoxmlManager.registerEntity(task, 'invalid')).toBeUndefined(); expect(isoxmlManager.registerEntity(task, 'FRM-1')).toBeUndefined(); expect(isoxmlManager.registerEntity()).toBeUndefined(); })); it('should not register duplicated entities', () => __awaiter(void 0, void 0, void 0, function* () { const isoxmlManager = new ISOXMLManager_1.ISOXMLManager(); const task1 = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); const task2 = isoxmlManager.createEntityFromAttributes("TSK" /* TAGS.Task */, { TaskStatus: "1" /* TaskTaskStatusEnum.Planned */ }); isoxmlManager.registerEntity(task1, 'TSK-1', 'ext_id_1'); const ref1 = isoxmlManager.registerEntity(task1); expect(ref1.xmlId).toEqual('TSK-1'); const ref2 = isoxmlManager.registerEntity(task2, null, 'ext_id_1'); expect(ref2.xmlId).toEqual('TSK-1'); })); }); });