From 0728af14dd645505729bf860570264a20d885773 Mon Sep 17 00:00:00 2001 From: Colin McLeod Date: Thu, 13 Aug 2015 23:22:13 -0700 Subject: [PATCH] Support import of E:D shipyard text exports --- app/js/controllers/controller-import.js | 156 +++++++++++++++--- app/js/controllers/controller-outfit.js | 9 +- app/js/directives/directive-loader.js | 2 +- app/js/shipyard/factory-ship.js | 19 ++- app/js/shipyard/service-components.js | 50 ++++-- app/views/modal-import.html | 6 +- test/fixtures/ed-shipyard-import-invalid.json | 22 +++ test/fixtures/ed-shipyard-import-valid.json | 26 +++ test/tests/test-controller-import.js | 95 +++++++---- 9 files changed, 304 insertions(+), 81 deletions(-) create mode 100644 test/fixtures/ed-shipyard-import-invalid.json create mode 100644 test/fixtures/ed-shipyard-import-valid.json diff --git a/app/js/controllers/controller-import.js b/app/js/controllers/controller-import.js index 25985dda..6f373227 100755 --- a/app/js/controllers/controller-import.js +++ b/app/js/controllers/controller-import.js @@ -1,11 +1,25 @@ -angular.module('app').controller('ImportController', ['lodash', '$rootScope', '$scope', '$stateParams', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function(_, $rootScope, $scope, $stateParams, Ships, Ship, Persist, Serializer) { - $scope.jsonValid = false; - $scope.importJSON = null; +angular.module('app').controller('ImportController', ['lodash', '$rootScope', '$scope', '$stateParams', 'ShipsDB', 'Ship', 'Components', 'GroupMap', 'Persist', 'Serializer', function(_, $rootScope, $scope, $stateParams, Ships, Ship, Components, GroupMap, Persist, Serializer) { + $scope.importValid = false; + $scope.importString = null; $scope.errorMsg = null; $scope.canEdit = true; $scope.builds = $stateParams.obj || null; $scope.ships = Ships; + var textBuildRegex = new RegExp('^\\[([\\w \\-]+)\\]\n'); + var lineRegex = new RegExp('^([\\dA-Z]{1,2}): (\\d)([A-I])[/]?([FGT])?([SD])? ([\\w\\- ]+)'); + var mountMap = { 'H': 4, 'L': 3, 'M': 2, 'S': 1, 'U': 0 }; + var commonMap = { 'RB': 0, 'TM': 1, 'FH': 2, 'EC': 3, 'PC': 4, 'SS': 5, 'FS': 6 }; + var bhMap = { 'lightweight alloy': 0, 'reinforced alloy': 1, 'military grade composite': 2, 'mirrored surface composite': 3, 'reactive surface composite': 4 }; + + function isEmptySlot(slot) { + return slot.maxClass == this && slot.c === null; + } + + function equalsIgnoreCase(str) { + return str.toLowerCase() == this.toLowerCase(); + } + function validateBuild(shipId, code, name) { var shipData = Ships[shipId]; @@ -83,40 +97,134 @@ angular.module('app').controller('ImportController', ['lodash', '$rootScope', '$ $scope.builds = builds; } - $scope.validateJson = function() { + function importTextBuild(buildStr) { + var buildName = textBuildRegex.exec(buildStr)[1].trim(); + var shipName = buildName.toLowerCase(); + var shipId = null; + + for (var sId in Ships) { + if (Ships[sId].properties.name.toLowerCase() == shipName) { + shipId = sId; + break; + } + } + + if (!shipId) { throw 'No such ship found: "' + buildName + '"'; } + + var lines = buildStr.split('\n'); + var ship = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots); + ship.buildWith(null); + + for (var i = 1; i < lines.length; i++) { + var line = lines[i].trim(); + + if (!line) { continue; } + if (line.substring(0, 3) == '---') { break; } + + var parts = lineRegex.exec(line); + + if (!parts) { throw 'Error parsing: "' + line + '"'; } + + var typeSize = parts[1]; + var cl = parts[2]; + var rating = parts[3]; + var mount = parts[4]; + var missile = parts[5]; + var name = parts[6].trim(); + var slot, group; + + if (isNaN(typeSize)) { // Common or Hardpoint + if (typeSize.length == 1) { // Hardpoint + var slotClass = mountMap[typeSize]; + + if (cl > slotClass) { throw cl + rating + ' ' + name + ' exceeds slot size: "' + line + '"'; } + + slot = _.find(ship.hardpoints, isEmptySlot, slotClass); + + if (!slot) { throw 'No hardpoint slot available for: "' + line + '"'; } + + group = _.find(GroupMap, equalsIgnoreCase, name); + + var hpid = Components.findHardpointId(group, cl, rating, group ? null : name, mount, missile); + + if (!hpid) { throw 'Unknown component: "' + line + '"'; } + + ship.use(slot, hpid, Components.hardpoints(hpid), true); + + } else if (typeSize == 'BH') { + var bhId = bhMap[name.toLowerCase()]; + + if (bhId === undefined) { throw 'Unknown bulkhead: "' + line + '"'; } + + ship.useBulkhead(bhId, true); + + } else if (commonMap[typeSize] != undefined) { + var commonIndex = commonMap[typeSize]; + + if (ship.common[commonIndex].maxClass < cl) { throw name + ' exceeds max class for the ' + ship.name; } + + ship.use(ship.common[commonIndex], cl + rating, Components.common(commonIndex, cl + rating), true); + + } else { + throw 'Unknown component: "' + line + '"'; + } + } else { + if (cl > typeSize) { throw cl + rating + ' ' + name + ' exceeds slot size: "' + line + '"'; } + + slot = _.find(ship.internal, isEmptySlot, typeSize); + + if (!slot) { throw 'No internal slot available for: "' + line + '"'; } + + group = _.find(GroupMap, equalsIgnoreCase, name); + + var intId = Components.findInternalId(group, cl, rating, group ? null : name); + + if (!intId) { throw 'Unknown component: "' + line + '"'; } + + ship.use(slot, intId, Components.internal(intId)); + } + } + + var builds = {}; + builds[shipId] = {}; + builds[shipId]['Imported ' + buildName] = Serializer.fromShip(ship); + $scope.builds = builds; + } + + $scope.validateImport = function() { var importData = null; - $scope.jsonValid = false; + var importString = $scope.importString.trim(); + $scope.importValid = false; $scope.errorMsg = null; $scope.builds = $scope.discounts = $scope.comparisons = $scope.insurance = null; - if (!$scope.importJSON) { return; } + if (!importString) { return; } + try { - importData = angular.fromJson($scope.importJSON); - } catch (e) { - $scope.errorMsg = 'Cannot Parse JSON!'; - return; - } + if (textBuildRegex.test(importString)) { // E:D Shipyard build text + importTextBuild(importString); + } else { // JSON Build data + importData = angular.fromJson($scope.importString); - if (!importData || typeof importData != 'object') { - $scope.errorMsg = 'Must be an object or array!'; - return; - } + if (!importData || typeof importData != 'object') { + throw 'Must be an object or array!'; + } - try { - if (importData instanceof Array) { // Must be detailed export json - importDetailedArray(importData); - } else if (importData.ship && importData.name) { // Using JSON from a single ship build export - importDetailedArray([importData]); // Convert to array with singleobject - } else { // Using Backup JSON - importBackup(importData); + if (importData instanceof Array) { // Must be detailed export json + importDetailedArray(importData); + } else if (importData.ship && importData.name) { // Using JSON from a single ship build export + importDetailedArray([importData]); // Convert to array with singleobject + } else { // Using Backup JSON + importBackup(importData); + } } } catch (e) { - $scope.errorMsg = e; + $scope.errorMsg = (typeof e == 'string') ? e : 'Cannot Parse the data!'; return; } - $scope.jsonValid = true; + $scope.importValid = true; }; $scope.hasBuild = function(shipId, name) { diff --git a/app/js/controllers/controller-outfit.js b/app/js/controllers/controller-outfit.js index 1b0c99b3..3ed630f0 100755 --- a/app/js/controllers/controller-outfit.js +++ b/app/js/controllers/controller-outfit.js @@ -145,7 +145,14 @@ angular.module('app').controller('OutfitController', ['$window', '$rootScope', ' */ $scope.select = function(type, slot, e, id) { e.stopPropagation(); - id = id || angular.element(e.target).attr('cpid'); // Get component ID + + if (!id) { // Find component id if not passed + var elem = e.target; + while (elem && elem !== e.currentTarget && !elem.getAttribute('cpid')) { + elem = elem.parentElement; + } + id = elem.getAttribute('cpid'); + } if (id) { if (id == 'empty') { diff --git a/app/js/directives/directive-loader.js b/app/js/directives/directive-loader.js index 8bcbe7c6..b7743337 100644 --- a/app/js/directives/directive-loader.js +++ b/app/js/directives/directive-loader.js @@ -3,7 +3,7 @@ angular.module('app').directive('loader', function() { restrict: 'A', link: function(scope, element) { element.addClass('loader'); - element.html(''); + element.html(''); } }; }); diff --git a/app/js/shipyard/factory-ship.js b/app/js/shipyard/factory-ship.js index dc0b10ec..cd30ffcb 100755 --- a/app/js/shipyard/factory-ship.js +++ b/app/js/shipyard/factory-ship.js @@ -95,7 +95,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', this.totalDps = 0; this.bulkheads.c = null; - this.useBulkhead(comps.bulkheads || 0, true); + this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true); this.cargoScoop.priority = priorities ? priorities[0] * 1 : 0; this.cargoScoop.enabled = enabled ? enabled[0] * 1 : true; @@ -116,7 +116,10 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', common[i].type = 'SYS'; common[i].c = common[i].id = null; // Resetting 'old' component if there was one common[i].discountedCost = 0; - this.use(common[i], comps.common[i], Components.common(i, comps.common[i]), true); + + if (comps) { + this.use(common[i], comps.common[i], Components.common(i, comps.common[i]), true); + } } common[1].type = 'ENG'; // Thrusters @@ -131,7 +134,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', hps[i].c = hps[i].id = null; // Resetting 'old' component if there was one hps[i].discountedCost = 0; - if (comps.hardpoints[i] !== 0) { + if (comps && comps.hardpoints[i] !== 0) { this.use(hps[i], comps.hardpoints[i], Components.hardpoints(comps.hardpoints[i]), true); } } @@ -146,15 +149,17 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', internal[i].id = internal[i].c = null; // Resetting 'old' component if there was one internal[i].discountedCost = 0; - if (comps.internal[i] !== 0) { + if (comps && comps.internal[i] !== 0) { this.use(internal[i], comps.internal[i], Components.internal(comps.internal[i]), true); } } // Update aggragated stats - this.updatePower(); - this.updateJumpStats(); - this.updateShieldStrength(); + if (comps) { + this.updatePower(); + this.updateJumpStats(); + this.updateShieldStrength(); + } }; Ship.prototype.useBulkhead = function(index, preventUpdate) { diff --git a/app/js/shipyard/service-components.js b/app/js/shipyard/service-components.js index 2a387c68..1b412aa7 100755 --- a/app/js/shipyard/service-components.js +++ b/app/js/shipyard/service-components.js @@ -33,15 +33,25 @@ angular.module('shipyard').service('Components', ['lodash', 'ComponentsDB', 'Shi }; this.findInternalId = function(groupName, clss, rating, name) { - var group = C.internal[groupName]; + var groups = {}; - if (!group) { - throw 'Invalid internal group: ' + groupName; + if (groupName) { + if (!C.internal[groupName]) { + throw 'Invalid internal group: ' + groupName; + } + groups[groupName] = C.internal[groupName]; + } else if (name) { + groups = C.internal; + } else { + throw 'Invalid group or name not provided'; } - for (var i = 0, l = group.length; i < l; i++) { - if (group[i].class == clss && group[i].rating == rating && ((!name && !group[i].name) || group[i].name == name)) { - return group[i].id; + for (var g in groups) { + var group = groups[g]; + for (var i = 0, l = group.length; i < l; i++) { + if (group[i].class == clss && group[i].rating == rating && ((!name && !group[i].name) || group[i].name == name)) { + return group[i].id; + } } } @@ -49,18 +59,28 @@ angular.module('shipyard').service('Components', ['lodash', 'ComponentsDB', 'Shi }; this.findHardpointId = function(groupName, clss, rating, name, mode, missile) { - var group = C.hardpoints[groupName]; + var groups = {}; - if (!group) { - throw 'Invalid hardpoint group: ' + groupName; + if (groupName) { + if (!C.hardpoints[groupName]) { + throw 'Invalid internal group: ' + groupName; + } + groups[groupName] = C.hardpoints[groupName]; + } else if (name) { + groups = C.hardpoints; + } else { + throw 'Invalid group or name not provided'; } - for (var i = 0, l = group.length; i < l; i++) { - if (group[i].class == clss && group[i].rating == rating && group[i].mode == mode - && ((!name && !group[i].name) || group[i].name == name) - && ((!missile && !group[i].missile) || group[i].missile == missile) - ) { - return group[i].id; + for (var g in groups) { + var group = groups[g]; + for (var i = 0, l = group.length; i < l; i++) { + if (group[i].class == clss && group[i].rating == rating && group[i].mode == mode + && ((!name && !group[i].name) || group[i].name == name) + && ((!missile && !group[i].missile) || group[i].missile == missile) + ) { + return group[i].id; + } } } diff --git a/app/views/modal-import.html b/app/views/modal-import.html index 4cf89df4..9dfcc69b 100755 --- a/app/views/modal-import.html +++ b/app/views/modal-import.html @@ -1,7 +1,7 @@

Import

- - + +
{{errorMsg}}
@@ -34,7 +34,7 @@ - + \ No newline at end of file diff --git a/test/fixtures/ed-shipyard-import-invalid.json b/test/fixtures/ed-shipyard-import-invalid.json new file mode 100644 index 00000000..7e2b29a6 --- /dev/null +++ b/test/fixtures/ed-shipyard-import-invalid.json @@ -0,0 +1,22 @@ +[ + { + "buildText": "[Imaginary Ship]\nbla bla", + "errorMsg": "No such ship found: \"Imaginary Ship\"" + }, + { + "buildText": "[Viper]\nS: 1F/F Pulse Laser\nsome un-parseable nonsense\nS: 1F/F Pulse Laser\n", + "errorMsg": "Error parsing: \"some un-parseable nonsense\"" + }, + { + "buildText": "[Sidewinder]\nS: 2F/F Pulse Laser\nS: 1F/F Pulse Laser\n", + "errorMsg": "2F Pulse Laser exceeds slot size: \"S: 2F/F Pulse Laser\"" + }, + { + "buildText": "[Sidewinder]\nL: 2F/F Pulse Laser\nS: 1F/F Pulse Laser\n", + "errorMsg": "No hardpoint slot available for: \"L: 2F/F Pulse Laser\"" + }, + { + "buildText": "[Sidewinder]\nS: 1F/F Magic Thing\nS: 1F/F Pulse Laser\n", + "errorMsg": "Unknown component: \"S: 1F/F Magic Thing\"" + } +] \ No newline at end of file diff --git a/test/fixtures/ed-shipyard-import-valid.json b/test/fixtures/ed-shipyard-import-valid.json new file mode 100644 index 00000000..71b6ef3a --- /dev/null +++ b/test/fixtures/ed-shipyard-import-valid.json @@ -0,0 +1,26 @@ +[ + { + "shipId": "anaconda", + "buildName": "Imported Anaconda", + "buildCode": "08E7E6E5E8E8E5C------1717--------05044j-03--2h--00.Iw18ZlA=.Aw18ZlA=", + "buildText": "[Anaconda]\nS: 1F/F Pulse Laser\nS: 1F/F Pulse Laser\n\nBH: 1I Lightweight Alloy\nRB: 8E Power Plant\nTM: 7E Thrusters\nFH: 6E Frame Shift Drive\nEC: 5E Life Support\nPC: 8E Power Distributor\nSS: 8E Sensors\nFS: 5C Fuel Tank (Capacity: 32)\n\n7: 6E Cargo Rack (Capacity: 64)\n6: 5E Cargo Rack (Capacity: 32)\n6: 6E Shield Generator\n5: 4E Cargo Rack (Capacity: 16)\n4: 1E Basic Discovery Scanner\n2: 1E Cargo Rack (Capacity: 2)\n" + }, + { + "shipId": "cobra_mk_iii", + "buildName": "Imported Cobra Mk III", + "buildCode": "04A4C4E3D2A3D4C1712222503040202490f242h.Iw1-kA==.Aw1-kA==", + "buildText": "[Cobra Mk III]\nM: 1F/F Pulse Laser\nM: 1G/G Burst Laser\nS: 1E/T Fragment Cannon\nS: 1G/T Multi-cannon\nU: 0I Point Defence\nU: 0A Shield Booster\n\nBH: 1I Lightweight Alloy\nRB: 4A Power Plant\nTM: 4C Thrusters\nFH: 4E Frame Shift Drive\nEC: 3D Life Support\nPC: 2A Power Distributor\nSS: 3D Sensors\nFS: 4C Fuel Tank (Capacity: 16)\n\n4: 3E Cargo Rack (Capacity: 8)\n4: 3E Cargo Rack (Capacity: 8)\n4: 4E Shield Generator\n2: 2C Auto Field-Maintenance Unit\n2: 1E Standard Docking Computer\n2: 1E Basic Discovery Scanner\n---\nShield: 112.29 MJ\nPower : 10.45 MW retracted (67%)\n 12.16 MW deployed (78%)\n 15.60 MW available\nCargo : 16 T\nFuel : 16 T\nMass : 235.5 T empty\n 267.5 T full\nRange : 10.69 LY unladen\n 10.05 LY laden\nPrice : 2,929,040 CR\nRe-Buy: 146,452 CR @ 95% insurance\n" + }, + { + "shipId": "type_9_heavy", + "buildName": "Imported Type-9 Heavy", + "buildCode": "35A7D6A5A4D4D5C7e2k2f2h110001020306054j03022f01242i.Iw18eQ==.Aw18eQ==", + "buildText": "[Type-9 Heavy]\nM: 2D/G Fragment Cannon\nM: 2I/F Mine Launcher\nM: 2B/FD Missile Rack\nS: 1I/FS Torpedo Pylon\nS: 1F/F Burst Laser\nU: 0I Chaff Launcher\nU: 0F Electronic Countermeasure\nU: 0I Heat Sink Launcher\nU: 0I Point Defence\n\nBH: 1I Mirrored Surface Composite\nRB: 5A Power Plant\nTM: 7D Thrusters\nFH: 6A Frame Shift Drive\nEC: 5A Life Support\nPC: 4D Power Distributor\nSS: 4D Sensors\nFS: 5C Fuel Tank (Capacity: 32)\n\n8: 7E Cargo Rack (Capacity: 128)\n7: 6E Cargo Rack (Capacity: 64)\n6: 6E Shield Generator\n5: 4E Cargo Rack (Capacity: 16)\n4: 3E Cargo Rack (Capacity: 8)\n4: 1C Advanced Discovery Scanner\n3: 2E Cargo Rack (Capacity: 4)\n3: 1E Standard Docking Computer\n2: 1C Detailed Surface Scanner\n" + }, + { + "shipId": "vulture", + "buildName": "Imported Vulture", + "buildCode": "44A5A4A3D5A4D3C1e1e0e0j04044a0n532jf1.Iw19kA==.Aw19kA==", + "buildText": "[Vulture]\nL: 3E/G Pulse Laser\nL: 3E/G Pulse Laser\nU: 0A Frame Shift Wake Scanner\nU: 0A Kill Warrant Scanner\nU: 0A Shield Booster\nU: 0A Shield Booster\n\nBH: 1I Reactive Surface Composite\nRB: 4A Power Plant\nTM: 5A Thrusters\nFH: 4A Frame Shift Drive\nEC: 3D Life Support\nPC: 5A Power Distributor\nSS: 4D Sensors\nFS: 3C Fuel Tank (Capacity: 8)\n\n5: 5A Shield Generator\n4: 4A Auto Field-Maintenance Unit\n2: 2A Shield Cell Bank\n1: 1A Fuel Scoop\n1: 1C Fuel Tank (Capacity: 2)" + } +] \ No newline at end of file diff --git a/test/tests/test-controller-import.js b/test/tests/test-controller-import.js index fea84a41..e66cf744 100644 --- a/test/tests/test-controller-import.js +++ b/test/tests/test-controller-import.js @@ -37,9 +37,9 @@ describe('Import Controller', function() { it('imports a valid backup', function() { var importData = __json__['fixtures/valid-backup']; - scope.importJSON = angular.toJson(importData); - scope.validateJson(); - expect(scope.jsonValid).toBeTruthy(); + scope.importString = angular.toJson(importData); + scope.validateImport(); + expect(scope.importValid).toBeTruthy(); expect(scope.errorMsg).toEqual(null); scope.process(); expect(scope.processed).toBeTruthy(); @@ -52,9 +52,9 @@ describe('Import Controller', function() { it('imports an old valid backup', function() { var importData = __json__['fixtures/old-valid-export']; - scope.importJSON = angular.toJson(importData); - scope.validateJson(); - expect(scope.jsonValid).toBeTruthy(); + scope.importString = angular.toJson(importData); + scope.validateImport(); + expect(scope.importValid).toBeTruthy(); expect(scope.errorMsg).toEqual(null); scope.process(); expect(scope.processed).toBeTruthy(); @@ -65,31 +65,31 @@ describe('Import Controller', function() { it('catches an invalid backup', function() { var importData = __json__['fixtures/valid-backup']; - scope.importJSON = 'null'; - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = 'null'; + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('Must be an object or array!'); - scope.importJSON = '{ "builds": "Should not be a string" }'; - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = '{ "builds": "Should not be a string" }'; + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('builds must be an object!'); - scope.importJSON = angular.toJson(importData).replace('anaconda', 'invalid_ship'); - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = angular.toJson(importData).replace('anaconda', 'invalid_ship'); + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('"invalid_ship" is not a valid Ship Id!'); - scope.importJSON = angular.toJson(importData).replace('Dream', ''); - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = angular.toJson(importData).replace('Dream', ''); + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('Imperial Clipper build "" must be a string at least 3 characters long!'); invalidImportData = angular.copy(importData); invalidImportData.builds.asp = null; // Remove Asp Miner build used in comparison - scope.importJSON = angular.toJson(invalidImportData); - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = angular.toJson(invalidImportData); + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('asp build "Miner" data is missing!'); }); @@ -100,9 +100,9 @@ describe('Import Controller', function() { it('imports a valid build', function() { var importData = __json__['fixtures/anaconda-test-detailed-export']; - scope.importJSON = angular.toJson(importData); - scope.validateJson(); - expect(scope.jsonValid).toBeTruthy(); + scope.importString = angular.toJson(importData); + scope.validateImport(); + expect(scope.importValid).toBeTruthy(); expect(scope.errorMsg).toEqual(null); scope.process(); expect(scope.processed).toBeTruthy(); @@ -114,9 +114,9 @@ describe('Import Controller', function() { it('catches an invalid build', function() { var importData = __json__['fixtures/anaconda-test-detailed-export']; - scope.importJSON = angular.toJson(importData).replace('components', 'comps'); - scope.validateJson(); - expect(scope.jsonValid).toBeFalsy(); + scope.importString = angular.toJson(importData).replace('components', 'comps'); + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); expect(scope.errorMsg).toEqual('Anaconda Build "Test": Invalid data'); }); @@ -127,9 +127,9 @@ describe('Import Controller', function() { it('imports all builds', function() { var importData = __json__['fixtures/valid-detailed-export']; var expectedBuilds = __json__['fixtures/expected-builds']; - scope.importJSON = angular.toJson(importData); - scope.validateJson(); - expect(scope.jsonValid).toBeTruthy(); + scope.importString = angular.toJson(importData); + scope.validateImport(); + expect(scope.importValid).toBeTruthy(); expect(scope.errorMsg).toEqual(null); scope.process(); expect(scope.processed).toBeTruthy(); @@ -144,4 +144,39 @@ describe('Import Controller', function() { }); + describe('Import E:D Shipyard Builds', function() { + + it('imports a valid builds', function() { + var imports = __json__['fixtures/ed-shipyard-import-valid']; + + for (var i = 0; i < imports.length; i++ ) { + scope.importString = imports[i].buildText; + scope.validateImport(); + expect(scope.importValid).toBeTruthy(); + expect(scope.errorMsg).toEqual(null, 'Build #' + i + ': ' + imports[i].buildName); + + if (scope.importValid) { // No point in carrying out other assertions + scope.process(); + expect(scope.processed).toBeTruthy(); + scope.import(); + var allBuilds = angular.fromJson(localStorage.getItem('builds')); + var shipBuilds = allBuilds ? allBuilds[imports[i].shipId] : null; + var build = shipBuilds ? shipBuilds[imports[i].buildName] : null; + expect(build).toEqual(imports[i].buildCode, 'Build #' + i + ': ' + imports[i].buildName); + } + } + }); + + it('catches invalid builds', function() { + var imports = __json__['fixtures/ed-shipyard-import-invalid']; + for (var i = 0; i < imports.length; i++ ) { + scope.importString = imports[i].buildText; + scope.validateImport(); + expect(scope.importValid).toBeFalsy(); + expect(scope.errorMsg).toEqual(imports[i].errorMsg); + } + }); + + }); + });