diff --git a/__tests__/fixtures/asp-test-detailed-export-v4.json b/__tests__/fixtures/asp-test-detailed-export-v4.json new file mode 100644 index 00000000..ba14ef4d --- /dev/null +++ b/__tests__/fixtures/asp-test-detailed-export-v4.json @@ -0,0 +1,255 @@ +{ + "$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#", + "name": "Multi-purpose Asp Explorer", + "ship": "Asp Explorer", + "references": [ + { + "name": "Coriolis.io", + "url": "https://coriolis.edcd.io/outfit/asp?code=0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FAwDFxwtofAAAAA%3D%3D&bn=Multi-purpose%20Asp%20Explorer", + "code": "0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx/78YG5AltB7I/8/0TwImJboDSPJ/+/f/v/KlX///i3AwMTBIfARK/Gf+JwVSxArStVAYqOjvz///JVo5GRhE2IBc4SKQSSz/DGEmCa398P8//2+gTf//AwDFxwtofAAAAA==", + "shipId": "asp" + } + ], + "components": { + "standard": { + "bulkheads": "Lightweight Alloy", + "cargoHatch": { + "enabled": false, + "priority": 5 + }, + "powerPlant": { + "class": 5, + "rating": "A", + "enabled": true, + "priority": 2, + "modifications": { + "eff": -1850, + "pgen": 6, + "mass": 431 + }, + "blueprint": { + "id": 64, + "name": "Low emissions", + "grade": 1 + } + }, + "thrusters": { + "class": 5, + "rating": "D", + "enabled": true, + "priority": 1, + "modifications": { + "optmul": 440, + "integrity": -266, + "thermload": -1326, + "optmass": 520, + "power": 241 + }, + "blueprint": { + "id": 24, + "name": "Clean", + "grade": 1 + } + }, + "frameShiftDrive": { + "class": 5, + "rating": "A", + "enabled": true, + "priority": 1, + "modifications": { + "mass": 5025, + "integrity": -1539, + "power": 2437, + "optmass": 4870, + "maxfuel": 370 + }, + "blueprint": { + "id": 26, + "name": "Increased range", + "grade": 5 + } + }, + "lifeSupport": { + "class": 4, + "rating": "A", + "enabled": true, + "priority": 1, + "modifications": { + "mass": -3923, + "integrity": -1797 + }, + "blueprint": { + "id": 49, + "name": "Lightweight", + "grade": 1 + } + }, + "powerDistributor": { + "class": 3, + "rating": "D", + "enabled": true, + "priority": 1 + }, + "sensors": { + "class": 5, + "rating": "D", + "enabled": true, + "priority": 1 + }, + "fuelTank": { + "class": 5, + "rating": "C", + "enabled": true, + "priority": 1 + } + }, + "hardpoints": [ + null, + null, + null, + null, + null, + null + ], + "utility": [ + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Heat Sink Launcher", + "name": "Heat Sink Launcher" + }, + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Heat Sink Launcher", + "name": "Heat Sink Launcher" + }, + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Heat Sink Launcher", + "name": "Heat Sink Launcher" + }, + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Point Defence", + "name": "Point Defence" + } + ], + "internal": [ + { + "class": 6, + "rating": "A", + "enabled": true, + "priority": 1, + "group": "Fuel Scoop" + }, + { + "class": 5, + "rating": "E", + "enabled": true, + "priority": 2, + "group": "Cargo Rack" + }, + { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1, + "group": "Shield Generator" + }, + { + "class": 3, + "rating": "E", + "enabled": true, + "priority": 2, + "group": "Cargo Rack" + }, + { + "class": 2, + "rating": "G", + "enabled": true, + "priority": 1, + "group": "Planetary Vehicle Hangar" + }, + { + "class": 1, + "rating": "C", + "enabled": true, + "priority": 2, + "group": "Scanner", + "name": "Advanced Discovery Scanner" + }, + { + "class": 1, + "rating": "C", + "enabled": true, + "priority": 2, + "group": "Scanner", + "name": "Detailed Surface Scanner" + } + ] + }, + "stats": { + "class": 2, + "hullCost": 6135660, + "speed": 250, + "boost": 340, + "boostEnergy": 13, + "agility": 6, + "baseShieldStrength": 140, + "baseArmour": 210, + "hullMass": 280, + "masslock": 11, + "pipSpeed": 0.13, + "moduleCostMultiplier": 1, + "fuelCapacity": 32, + "cargoCapacity": 40, + "ladenMass": 435.26, + "armour": 378, + "shield": 113.43, + "shieldCells": 0, + "totalCost": 48402550, + "unladenMass": 363.26, + "totalDpe": 0, + "totalExplDpe": 0, + "totalKinDpe": 0, + "totalThermDpe": 0, + "totalDps": 0, + "totalExplDps": 0, + "totalKinDps": 0, + "totalThermDps": 0, + "totalSDps": 0, + "totalExplSDps": 0, + "totalKinSDps": 0, + "totalThermSDps": 0, + "totalEps": 1.2, + "totalHps": 1, + "shieldExplRes": 0.5, + "shieldKinRes": 0.6, + "shieldThermRes": 1.2, + "hullExplRes": 1.4, + "hullKinRes": 1.2, + "hullThermRes": 1, + "powerAvailable": 20.41, + "powerRetracted": 11.91, + "powerDeployed": 11.91, + "unladenRange": 50.45, + "fullTankRange": 47.03, + "ladenRange": 42.71, + "unladenFastestRange": 317.24, + "ladenFastestRange": 287.02, + "maxJumpCount": 7, + "topSpeed": 274.01, + "topBoost": 372.65 + } +} diff --git a/__tests__/fixtures/expected-builds.json b/__tests__/fixtures/expected-builds.json index 2b985df4..054de777 100644 --- a/__tests__/fixtures/expected-builds.json +++ b/__tests__/fixtures/expected-builds.json @@ -1,8 +1,8 @@ { "type_6_transporter": { - "Cargo": "0p0tdFal8d8s8f4-----04040303430101.Iw1-kA==.Aw1-kA==.", - "Miner": "0p5tdFal8d8s8f42l2l---040403451q0101.Iw1-kA==.Aw1-kA==.", - "Hopper": "0p0tdFal8d0s8f41717---030302024300-.Iw1-kA==.Aw1-kA==." + "Cargo": "0p0tdFal8d8s8f4-----04040303430101.Iw1/kA==.Aw1/kA==.", + "Miner": "0p5tdFal8d8s8f42l2l---040403451q0101.Iw1/kA==.Aw1/kA==.", + "Hopper": "0p0tdFal8d0s8f41717---030302024300-.Iw1/kA==.Aw1/kA==." }, "type_7_transport": { "Cargo": "0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.", @@ -36,7 +36,7 @@ "Test": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18ZlA=.Aw18ZlA=." }, "diamondback_explorer": { - "Explorer": "0p0tdFfldddsdf5---0202--320p432i2f.Iw1-kA==.Aw1-kA==." + "Explorer": "0p0tdFfldddsdf5---0202--320p432i2f.Iw1/kA==.Aw1/kA==." }, "vulture": { "Bounty Hunter": "3patcFalddksff31e1e0404-0l4a5d27662j.Iw19kA==.Aw19kA==." @@ -45,6 +45,6 @@ "Attack": "2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.Aw18aQ==." }, "eagle": { - "Figther": "4p0t5F5l3d5s5f20p0p24-40532j-.Iw1-EA==.Aw1-EA==." + "Figther": "4p0t5F5l3d5s5f20p0p24-40532j-.Iw1/EA==.Aw1/EA==." } } diff --git a/__tests__/test-import.js b/__tests__/test-import.js index fd5ef1b1..7f863270 100644 --- a/__tests__/test-import.js +++ b/__tests__/test-import.js @@ -142,7 +142,7 @@ describe('Import Modal', function() { expect(modal.state.singleBuild).toBe(true); clickProceed(); expect(MockRouter.go.mock.calls.length).toBe(1); - expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda/4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.?bn=Test%20My%20Ship'); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA%3D%3D.CwBhCYzBGW9qCTSqs5xA.&bn=Test%20My%20Ship'); }); it('catches an invalid build', function() { @@ -167,7 +167,24 @@ describe('Import Modal', function() { expect(modal.state.singleBuild).toBe(true); clickProceed(); expect(MockRouter.go.mock.calls.length).toBe(1); - expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda/4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA==?bn=Test%20My%20Ship'); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA%3D%3D.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2P8xwAEf0GE2AtmBob%2F%2FwFvM%2BjKEgAAAA%3D%3D&bn=Test%20My%20Ship'); + }); + }); + + describe('Import Detailed Engineered V4 Build', function() { + + beforeEach(reset); + + it('imports a valid v4 build', function() { + const importData = require('./fixtures/asp-test-detailed-export-v4'); + pasteText(JSON.stringify(importData)); + + expect(modal.state.importValid).toBeTruthy(); + expect(modal.state.errorMsg).toEqual(null); + expect(modal.state.singleBuild).toBe(true); + clickProceed(); + expect(MockRouter.go.mock.calls.length).toBe(1); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FAwDFxwtofAAAAA%3D%3D&bn=Multi-purpose%20Asp%20Explorer'); }); }); @@ -209,13 +226,13 @@ describe('Import Modal', function() { expect(modal.state.singleBuild).toBe(true); clickProceed(); expect(MockRouter.go.mock.calls.length).toBe(1); - expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette/2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifhv66g2f.AwRj4zNaKA==.CwRgDBldUExuBiQqA===.H4sIAAAAAAAAAx2Rzy4DURTGz7TuzHRu47ZjWreKlg5iQ9KFZ9CENyBWtWo8gIUFsamteAIJi0qEWIhdN11ZEN1IwyNYVKRpcXzH5su553f_XyfvKiLTYma-TkScyHVcokoYEdmbBNDsiDla-WUOT5LgyfAshHdvyGyjFFHUQCSrBU8TLT4gYq4DNL_LhNTFN3PwiqdZQyX2C-sekep-Mrs1RIbnDppsIogD1UAtN7JEM9eIzZg8hmhsEU32gFmrdgB_UARvjYEr4QMUMffoxGnV-M8X3hZ_lAO-gmWq2Eq2IVtDOzZ2Hbbuws6KxCKmKUUydgRb3woSiUXMs6Cs7Qt6FCQSi5hxkNKhj6qhfcPU_kU4wYrFMseSOmFXMKbuwZsViUWMlq1sbhvJ_lKyfqTqEJGJyoC5eIpU9x2TRnUswYXyF77BW4Z3qQuv05GDTpfvcDzvSbxJ5DtV_aHS1I4clyB2A5_b-pAL8x_enn626gEAAA==?bn=Imported%20Federal%20Corvette'); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifhv66g2f.AwRj4zNaKA%3D%3D.CwRgDBldUExuBiQqA%3D%3D%3D.H4sIAAAAAAAAA02Svy9DURTHT1t9%2FfEat32eem1V0YdYSDpgkBhpwsxATDU1%2FgCDQWKpVfwFEoZKhBjE1qWTgegiDX%2BCoSJNyz2%2BR%2FLkLd%2Bce7%2Bf8333vnMDeoWIfgKQtBEmUnVmjlaw5KBOixWCDDcNoqJlEzk3QUBjfWZ7XjNbJ7A5pLNCop2sMwv%2Bfo%2FZsWNEdhU9HNbLXtJUxCSafkA50QQ0uYeQ2MU3c%2FwVS7WAdI7qTe9MmYMIUbjzyWyU0WOdY9PZAM5xveVlhqv4kmE7RPlr9CeXsFesbhONtAGy6SMbcZCHOZD1AY%2FswlH3OAcnfGTtL1PIhpCLQl6hUiW5JW5FThmHYaVXvcM6axCzhTIl4oqomgQnfVAfat4KJOKKqGeBUj6oI9CjQCKuiBoEUziK4puWj3zDjc0XIQmVK5U6lrghHzSHK5lt%2BCkRV0SZ8m8cvfE%2F4x1Em5eSJE1uD5vBYpc5d4o44x2IXcEP4Iwue8HjX3gIkVn4My0sA00Z36jPv8OoIk%2Fih7AOlOS1FHTe87O7MlSCOOt4PYkPmSz%2FAiP2EO%2BUAgAA&bn=Imported%20Federal%20Corvette'); }); }); describe('Import E:D Shipyard Builds', function() { - it('imports a valid builds', function() { + it('imports a valid build', function() { const imports = require('./fixtures/ed-shipyard-import-valid'); for (let i = 0; i < imports.length; i++ ) { @@ -226,7 +243,7 @@ describe('Import Modal', function() { expect(modal.state.errorMsg).toEqual(null); clickProceed(); expect(MockRouter.go.mock.calls.length).toBe(1); - expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/' + fixture.shipId + '/' + fixture.buildCode + '?bn=' + encodeURIComponent(fixture.buildName)); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/' + fixture.shipId + '?code=' + encodeURIComponent(fixture.buildCode) + '&bn=' + encodeURIComponent(fixture.buildName)); } }); diff --git a/package.json b/package.json index 113483eb..7f54a676 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coriolis_shipyard", - "version": "2.2.2", + "version": "2.2.3beta", "repository": { "type": "git", "url": "https://github.com/EDCD/coriolis" diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index fa3e29e5..b3851423 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -44,6 +44,12 @@ export default class HardpointSlot extends Slot { let validMods = Modifications.validity[m.grp] || []; let showModuleResistances = Persist.showModuleResistances(); + // Modifications tooltip shows blueprint and grade, if available + let modTT = translate('modified'); + if (m && m.blueprint) { + modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade; + } + return