diff --git a/app/js/service-serializer.js b/app/js/service-serializer.js index d42c4c36..e1a11f63 100755 --- a/app/js/service-serializer.js +++ b/app/js/service-serializer.js @@ -72,7 +72,7 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' internal = ship.internal; var data = { - $schema: 'http://cdn.coriolis.io/schemas/ship-loadout/1.json#', + $schema: 'http://cdn.coriolis.io/schemas/ship-loadout/2.json#', name: buildName, ship: ship.name, references: [{ @@ -84,13 +84,13 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' components: { standard: { bulkheads: ship.bulkheads.c.name, - powerPlant: { class: standard[0].c.class, rating: standard[0].c.rating }, - thrusters: { class: standard[1].c.class, rating: standard[1].c.rating }, - frameShiftDrive: { class: standard[2].c.class, rating: standard[2].c.rating }, - lifeSupport: { class: standard[3].c.class, rating: standard[3].c.rating }, - powerDistributor: { class: standard[4].c.class, rating: standard[4].c.rating }, - sensors: { class: standard[5].c.class, rating: standard[5].c.rating }, - fuelTank: { class: standard[6].c.class, rating: standard[6].c.rating } + powerPlant: { class: standard[0].c.class, rating: standard[0].c.rating, enabled: Boolean(standard[0].enabled), priority: standard[0].priority + 1 }, + thrusters: { class: standard[1].c.class, rating: standard[1].c.rating, enabled: Boolean(standard[1].enabled), priority: standard[1].priority + 1 }, + frameShiftDrive: { class: standard[2].c.class, rating: standard[2].c.rating, enabled: Boolean(standard[2].enabled), priority: standard[2].priority + 1 }, + lifeSupport: { class: standard[3].c.class, rating: standard[3].c.rating, enabled: Boolean(standard[3].enabled), priority: standard[3].priority + 1 }, + powerDistributor: { class: standard[4].c.class, rating: standard[4].c.rating, enabled: Boolean(standard[4].enabled), priority: standard[4].priority + 1 }, + sensors: { class: standard[5].c.class, rating: standard[5].c.rating, enabled: Boolean(standard[5].enabled), priority: standard[5].priority + 1 }, + fuelTank: { class: standard[6].c.class, rating: standard[6].c.rating, enabled: Boolean(standard[6].enabled), priority: standard[6].priority + 1 } }, hardpoints: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass > 0; }), slotToSchema), utility: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass === 0; }), slotToSchema), @@ -116,6 +116,8 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' } var comps = detailedBuild.components; + var priorities = [ 0 ]; // cargoScoop + var enabled = [ true ]; // assume cargoScoop enabled var shipData = ShipsDB[shipId]; var ship = new Ship(shipId, shipData.properties, shipData.slots); var bulkheads = Components.bulkheadIndex(comps.standard.bulkheads); @@ -130,6 +132,8 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' if (!comps.standard[c].class || !comps.standard[c].rating) { throw 'Invalid value for ' + c; } + priorities.push(comps.standard[c].priority === undefined ? 0 : comps.standard[c].priority - 1); + enabled.push(comps.standard[c].enabled === undefined ? true : comps.standard[c].enabled); return comps.standard[c].class + comps.standard[c].rating; } ); @@ -143,7 +147,15 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' return c ? Components.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount]) : 0; })); - ship.buildWith({ bulkheads: bulkheads, common: common, hardpoints: hardpoints, internal: internal }); + // The ordering of these arrays must match the order in which they are read in Ship.buildWith + priorities = priorities.concat(_.map(comps.hardpoints, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; }), + _.map(comps.utility, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; }), + _.map(comps.internal, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; })); + enabled = enabled.concat(_.map(comps.hardpoints, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; }), + _.map(comps.utility, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; }), + _.map(comps.internal, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; })); + + ship.buildWith({ bulkheads: bulkheads, common: common, hardpoints: hardpoints, internal: internal }, priorities, enabled); return ship; }; @@ -213,7 +225,7 @@ angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', ' function slotToSchema(slot) { if (slot.c) { - var o = { class: slot.c.class, rating: slot.c.rating, group: GroupMap[slot.c.grp] }; + var o = { class: slot.c.class, rating: slot.c.rating, enabled: Boolean(slot.enabled), priority: slot.priority + 1, group: GroupMap[slot.c.grp] }; if (slot.c.name) { o.name = slot.c.name; } diff --git a/app/js/shipyard/factory-ship.js b/app/js/shipyard/factory-ship.js index cd30ffcb..5b5dc81c 100755 --- a/app/js/shipyard/factory-ship.js +++ b/app/js/shipyard/factory-ship.js @@ -97,7 +97,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', this.bulkheads.c = null; 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; + this.cargoScoop.enabled = enabled ? enabled[0] * true : true; for (i = 0, l = this.priorityBands.length; i < l; i++) { this.priorityBands[i].deployed = 0; @@ -111,7 +111,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', for (i = 0; i < cl; i++) { common[i].cat = 0; - common[i].enabled = enabled ? enabled[i + 1] * 1 : true; + common[i].enabled = enabled ? enabled[i + 1] * true : true; common[i].priority = priorities ? priorities[i + 1] * 1 : 0; common[i].type = 'SYS'; common[i].c = common[i].id = null; // Resetting 'old' component if there was one @@ -128,7 +128,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', for (i = 0, l = hps.length; i < l; i++) { hps[i].cat = 1; - hps[i].enabled = enabled ? enabled[cl + i] * 1 : true; + hps[i].enabled = enabled ? enabled[cl + i] * true : true; hps[i].priority = priorities ? priorities[cl + i] * 1 : 0; hps[i].type = hps[i].maxClass ? 'WEP' : 'SYS'; hps[i].c = hps[i].id = null; // Resetting 'old' component if there was one @@ -143,7 +143,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', for (i = 0, l = internal.length; i < l; i++) { internal[i].cat = 2; - internal[i].enabled = enabled ? enabled[cl + i] * 1 : true; + internal[i].enabled = enabled ? enabled[cl + i] * true : true; internal[i].priority = priorities ? priorities[cl + i] * 1 : 0; internal[i].type = 'SYS'; internal[i].id = internal[i].c = null; // Resetting 'old' component if there was one diff --git a/app/schemas/ship-loadout/2.json b/app/schemas/ship-loadout/2.json new file mode 100644 index 00000000..3420eef7 --- /dev/null +++ b/app/schemas/ship-loadout/2.json @@ -0,0 +1,301 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://cdn.coriolis.io/schemas/ship-loadout/2.json#", + "title": "Ship Loadout", + "type": "object", + "description": "The details for a specific ship build/loadout", + "required": ["name", "ship", "components"], + "properties": { + "name": { + "description": "The name of the build/loadout", + "type": "string", + "minLength": 2 + }, + "ship": { + "description": "The full display name of the ship", + "type": "string", + "minimum": 3 + }, + "manufacturer": { + "description": "The ship manufacturer", + "type": "string" + }, + "references" : { + "description": "3rd Party references and/or links to this build/loadout", + "type": "array", + "items": { + "type": "object", + "required": ["name","url"], + "additionalProperties": true, + "properties": { + "name": { + "description": "The name of the 3rd party, .e.g 'Coriolis.io' or 'E:D Shipyard'", + "type": "string" + }, + "url": { + "description": "The link/url to the 3rd party referencing this build/loadout", + "type": "string" + } + } + } + }, + "components": { + "description": "The components used by this build", + "type": "object", + "additionalProperties": false, + "required": ["standard", "internal", "hardpoints", "utility"], + "properties": { + "standard": { + "description": "The set of standard components across all ships", + "type": "object", + "additionalProperties": false, + "required": ["bulkheads", "powerPlant", "thrusters", "frameShiftDrive", "lifeSupport", "powerDistributor", "sensors", "fuelTank"], + "properties": { + "bulkheads": { + "enum": ["Lightweight Alloy", "Reinforced Alloy", "Military Grade Composite", "Mirrored Surface Composite", "Reactive Surface Composite"] + }, + "powerPlant": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "thrusters": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "frameShiftDrive": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "lifeSupport": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 6 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "powerDistributor": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "sensors": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + }, + "fuelTank": { + "required": ["class", "rating", "enabled", "priority"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 6 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 } + } + } + } + }, + "internal": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "enabled", "priority", "group"], + "properties" : { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 }, + "group": { + "description": "The group of the component, e.g. 'Shield Generator', or 'Cargo Rack'", + "type": "string" + }, + "name": { + "description": "The name identifying the component (if applicable), e.g. 'Advance Discovery Scanner', or 'Detailed Surface Scanner'", + "type": "string" + } + } + }, + "minItems": 3 + }, + "hardpoints": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "enabled", "priority", "group", "mount"], + "properties" : { + "class": { "type": "integer", "minimum": 1, "maximum": 4 }, + "rating": { "$ref": "#/definitions/allRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 }, + "mount": { "type": "string", "enum": ["Fixed", "Gimballed", "Turret"] }, + "group": { + "description": "The group of the component, e.g. 'Beam Laser', or 'Missile Rack'", + "type": "string" + }, + "name": { + "description": "The name identifing the component (if applicable), e.g. 'Retributor', or 'Mining Lance'", + "type": "string" + } + } + }, + "minItems": 1 + }, + "utility": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "enabled", "priority", "group"], + "properties" : { + "class": { "type": "integer", "minimum": 0, "maximum": 0 }, + "rating": { "$ref": "#/definitions/allRatings" }, + "enabled": { "type": "boolean" }, + "priority": { "type": "integer", "minimum": 1, "maximum": 5 }, + "group": { + "description": "The group of the component, e.g. 'Shield Booster', or 'Kill Warrant Scanner'", + "type": "string" + }, + "name": { + "description": "The name identifing the component (if applicable), e.g. 'Point Defence', or 'Electronic Countermeasure'", + "type": "string" + } + } + }, + "minItems": 1 + } + } + }, + "stats": { + "description": "Optional statistics from the build", + "type": "object", + "additionalProperties": true, + "properties": { + "agility": { + "type": "integer", + "minimum": 0 + }, + "armour": { + "description": "Sum of base armour + any hull reinforcements", + "type": "integer", + "minimum": 1 + }, + "armourAdded":{ + "description": "Armour added through Hull reinforcement", + "type": "integer", + "minimum": 1 + }, + "baseShieldStrength": { + "type": "integer", + "minimum": 1 + }, + "baseArmour": { + "type": "integer", + "minimum": 1 + }, + "boost": { + "description": "Maximum boost speed of the ships (4 pips, straight-line)", + "type": "number", + "minimum": 1 + }, + "cargoCapacity": { + "type": "integer", + "minimum": 0 + }, + "class": { + "description": "Ship Class/Size [Small, Medium, Large]", + "enum": [1,2,3] + }, + "dps": { + "description": "Cumulative DPS based on the in-game 1-10 statistic", + "type": "integer", + "minimum": 0 + }, + "hullCost": { + "description": "Cost of the ship's hull", + "type": "integer", + "minimum": 1 + }, + "hullMass": { + "description": "Mass of the Ship hull only", + "type": "number", + "minimum": 1 + }, + "fuelCapacity": { + "type": "integer", + "minimum": 1 + }, + "fullTankRange": { + "description": "Single Jump range with a full tank (unladenMass + fuel)", + "type": "number", + "minimum": 0 + }, + "ladenMass": { + "description": "Mass of the Ship + fuel + cargo (hull + all components + fuel tank + cargo capacity)", + "type": "number", + "minimum": 1 + }, + "ladenRange": { + "description": "Single Jump range with full cargo load, see ladenMass", + "type": "number", + "minimum": 0 + }, + "masslock": { + "description": "Mass Lock Factor of the Ship", + "type": "integer", + "minimum": 1 + }, + "shieldStrength": { + "description": "Shield strengh in Mega Joules (Mj)", + "type": "number", + "minimum": 0 + }, + "speed": { + "description": "Maximum speed of the ships (4 pips, straight-line)", + "type": "number", + "minimum": 1 + }, + "totalCost": { + "type": "integer", + "minimum": 1 + }, + "unladenRange": { + "description": "Single Jump range when unladen, see unladenMass", + "type": "number", + "minimum": 0 + }, + "unladenMass": { + "description": "Mass of the Ship (hull + all components)", + "type": "number", + "minimum": 1 + } + } + } + }, + "definitions": { + "standardRatings": { "enum": ["A", "B", "C", "D", "E"] }, + "allRatings": { "enum": ["A", "B", "C", "D", "E", "F", "I" ] } + } +} diff --git a/test/fixtures/anaconda-test-detailed-export.json b/test/fixtures/anaconda-test-detailed-export.json index 7e82c5a7..748b8b46 100644 --- a/test/fixtures/anaconda-test-detailed-export.json +++ b/test/fixtures/anaconda-test-detailed-export.json @@ -1,12 +1,12 @@ { - "$schema": "http://cdn.coriolis.io/schemas/ship-loadout/1.json#", + "$schema": "http://cdn.coriolis.io/schemas/ship-loadout/2.json#", "name": "Test", "ship": "Anaconda", "references": [ { "name": "Coriolis.io", - "url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b?bn=Test", - "code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b", + "url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA%3D%3D%3D.AwhMJBGaei%2BJCyyiA%3D%3D%3D?bn=Test", + "code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA===.AwhMJBGaei+JCyyiA===", "shipId": "anaconda" } ], @@ -15,79 +15,109 @@ "bulkheads": "Reactive Surface Composite", "powerPlant": { "class": 8, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 1 }, "thrusters": { "class": 6, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 1 }, "frameShiftDrive": { "class": 6, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 3 }, "lifeSupport": { "class": 5, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 1 }, "powerDistributor": { "class": 8, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 1 }, "sensors": { "class": 8, - "rating": "A" + "rating": "A", + "enabled": true, + "priority": 1 }, "fuelTank": { "class": 5, - "rating": "C" + "rating": "C", + "enabled": true, + "priority": 1 } }, "hardpoints": [ { "class": 4, "rating": "A", + "enabled": true, + "priority": 2, "group": "Plasma Accelerator", "mount": "Fixed" }, { "class": 3, "rating": "D", + "enabled": true, + "priority": 2, "group": "Beam Laser", "mount": "Turret" }, { "class": 3, "rating": "D", + "enabled": true, + "priority": 2, "group": "Beam Laser", "mount": "Turret" }, { "class": 3, "rating": "D", + "enabled": true, + "priority": 2, "group": "Beam Laser", "mount": "Turret" }, { "class": 2, "rating": "E", + "enabled": true, + "priority": 2, "group": "Cannon", "mount": "Turret" }, { "class": 2, "rating": "E", + "enabled": true, + "priority": 2, "group": "Cannon", "mount": "Turret" }, { "class": 1, "rating": "F", + "enabled": true, + "priority": 2, "group": "Beam Laser", "mount": "Turret" }, { "class": 1, "rating": "F", + "enabled": true, + "priority": 2, "group": "Beam Laser", "mount": "Turret" } @@ -96,39 +126,53 @@ { "class": 0, "rating": "A", + "enabled": true, + "priority": 1, "group": "Shield Booster" }, { "class": 0, "rating": "A", + "enabled": true, + "priority": 1, "group": "Shield Booster" }, null, { "class": 0, "rating": "C", + "enabled": true, + "priority": 2, "group": "Kill Warrant Scanner" }, { "class": 0, "rating": "C", + "enabled": true, + "priority": 2, "group": "Cargo Scanner" }, { "class": 0, "rating": "F", + "enabled": false, + "priority": 1, "group": "Countermeasure", "name": "Electronic Countermeasure" }, { "class": 0, "rating": "I", + "enabled": true, + "priority": 1, "group": "Countermeasure", "name": "Chaff Launcher" }, { "class": 0, "rating": "I", + "enabled": true, + "priority": 2, "group": "Countermeasure", "name": "Point Defence" } @@ -137,26 +181,36 @@ { "class": 7, "rating": "A", + "enabled": true, + "priority": 1, "group": "Shield Generator" }, { "class": 6, "rating": "A", + "enabled": true, + "priority": 1, "group": "Shield Cell Bank" }, { "class": 6, "rating": "E", + "enabled": true, + "priority": 1, "group": "Cargo Rack" }, { "class": 5, "rating": "D", + "enabled": true, + "priority": 1, "group": "Hull Reinforcement Package" }, { "class": 5, "rating": "E", + "enabled": true, + "priority": 1, "group": "Cargo Rack" }, null, @@ -164,21 +218,29 @@ { "class": 4, "rating": "E", + "enabled": true, + "priority": 1, "group": "Cargo Rack" }, { "class": 4, "rating": "E", + "enabled": true, + "priority": 1, "group": "Cargo Rack" }, { "class": 4, "rating": "A", + "enabled": true, + "priority": 3, "group": "Fuel Scoop" }, { "class": 2, "rating": "A", + "enabled": true, + "priority": 3, "group": "FSD Interdictor" } ] @@ -208,7 +270,7 @@ "totalDps": 29, "powerAvailable": 36, "powerRetracted": 23.93, - "powerDeployed": 35.56, + "powerDeployed": 35.36, "unladenRange": 18.49, "fullTankRange": 18.12, "ladenRange": 16.39, diff --git a/test/tests/test-controller-import.js b/test/tests/test-controller-import.js index e66cf744..2a373559 100644 --- a/test/tests/test-controller-import.js +++ b/test/tests/test-controller-import.js @@ -108,7 +108,7 @@ describe('Import Controller', function() { expect(scope.processed).toBeTruthy(); scope.import(); expect(angular.fromJson(localStorage.getItem('builds'))).toEqual({ - anaconda: { 'Test': '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18ZlA=.Aw18ZlA=' } + anaconda: { 'Test': '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA===.AwhMJBGaei+JCyyiA===' } }); }); diff --git a/test/tests/test-service-serializer.js b/test/tests/test-service-serializer.js index 25000896..2380d159 100644 --- a/test/tests/test-service-serializer.js +++ b/test/tests/test-service-serializer.js @@ -3,7 +3,7 @@ describe("Serializer Service", function() { var Ship, Serializer, - code = '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b', + code = '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA===.AwhMJBGaei+JCyyiA===', anaconda = DB.ships['anaconda'], testBuild, exportData; @@ -21,13 +21,20 @@ describe("Serializer Service", function() { exportData = Serializer.toDetailedBuild('Test', testBuild, code); }); - it("conforms to the ship-loadout schema", function() { + it("conforms to the v1 ship-loadout schema", function() { var shipLoadoutSchema = __json__['schemas/ship-loadout/1']; var validate = jsen(shipLoadoutSchema); var valid = validate(exportData); expect(valid).toBeTruthy(); }); + it("conforms to the v2 ship-loadout schema", function() { + var shipLoadoutSchema = __json__['schemas/ship-loadout/2']; + var validate = jsen(shipLoadoutSchema); + var valid = validate(exportData); + expect(valid).toBeTruthy(); + }); + it("contains the correct components and stats", function() { var anacondaTestExport = __json__['fixtures/anaconda-test-detailed-export']; expect(exportData.components).toEqual(anacondaTestExport.components);