Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UpgradeModification.js @@ -0,0 +1,159 @@ +Engine.LoadHelperScript("Player.js"); +Engine.LoadHelperScript("ValueModification.js"); +Resources = { + "BuildSchema": type => { + let schema = ""; + for (let res of ["food", "metal", "stone", "wood"]) + schema += + "" + + "" + + "" + + "" + + ""; + return "" + schema + ""; + } +}; +Engine.LoadComponentScript("interfaces/AuraManager.js"); // Provides `IID_AuraManager`, tested for in helpers/ValueModification.js. +Engine.LoadComponentScript("interfaces/TechnologyManager.js"); // Provides `IID_TechnologyManager`, used below. +Engine.LoadComponentScript("interfaces/Timer.js"); // Provides `IID_Timer`, used below. + +// What we're testing: +Engine.LoadComponentScript("interfaces/Upgrade.js"); +Engine.LoadComponentScript("Upgrade.js"); + +// Input (bare minimum needed for tests): +let techs = { + "alter_tower_upgrade_cost": { + "modifications": [ + { "value": "Upgrade/Cost/stone", "add": 60.0 }, + { "value": "Upgrade/Cost/wood", "multiply": 0.5 }, + { "value": "Upgrade/Time", "replace": 90 } + ], + "affects": ["Tower"] + } +}; +let template = { + "Identity": { + "Classes": { '@datatype': "tokens", "_string": "Tower" }, + "VisibleClasses": { '@datatype': "tokens", "_string": "" } + }, + "Upgrade": { + "Tower": { + "Cost": { "stone": "100", "wood": "50" }, + "Entity": "structures/{civ}_defense_tower", + "Time": "100" + } + } +}; +let civCode = "pony"; +let playerID = 1; + +// Usually, the tech modifications would be worked out by the TechnologyManager +// with assistance from globalscripts. This test is not about testing the +// TechnologyManager, so the modifications (both with and without the technology +// researched) are worked out before hand and placed here. +let isResearched = false; +let templateTechModifications = { + "without": {}, + "with": { + "Upgrade/Cost/stone": [{ "affects": [["Tower"]], "add": 60 }], + "Upgrade/Cost/wood": [{ "affects": [["Tower"]], "multiply": 0.5 }], + "Upgrade/Time": [{ "affects": [["Tower"]], "replace": 90 }] + } +}; +let entityTechModifications = { + "without": { + 'Upgrade/Cost/stone': { 20: { "origValue": 100, "newValue": 100 } }, + 'Upgrade/Cost/wood': { 20: { "origValue": 50, "newValue": 50 } }, + 'Upgrade/Time': { 20: { "origValue": 100, "newValue": 100 } } + }, + "with": { + 'Upgrade/Cost/stone': { 20: { "origValue": 100, "newValue": 160 } }, + 'Upgrade/Cost/wood': { 20: { "origValue": 50, "newValue": 25 } }, + 'Upgrade/Time': { 20: { "origValue": 100, "newValue": 90 } } + } +}; + +/** + * Initialise various bits. + */ +// System Entities: +AddMock(SYSTEM_ENTITY, IID_PlayerManager, { + "GetPlayerByID": pID => 10 // Called in helpers/player.js::QueryPlayerIDInterface(), as part of Tests T2 and T5. +}); +AddMock(SYSTEM_ENTITY, IID_TemplateManager, { + "GetTemplate": () => template // Called in components/Upgrade.js::ChangeUpgradedEntityCount(). +}); +AddMock(SYSTEM_ENTITY, IID_Timer, { + "SetInterval": () => 1, // Called in components/Upgrade.js::Upgrade(). + "CancelTimer": () => {} // Called in components/Upgrade.js::CancelUpgrade(). +}); + +// Init Player: +AddMock(10, IID_Player, { + "AddResources": () => {}, // Called in components/Upgrade.js::CancelUpgrade(). + "GetPlayerID": () => playerID, // Called in helpers/Player.js::QueryOwnerInterface() (and several times below). + "GetCheatTimeMultiplier": () => 1.0, // Called in components/Upgrade.js::GetUpgradeTime(). + "TrySubtractResources": () => true // Called in components/Upgrade.js::Upgrade(). +}); +AddMock(10, IID_TechnologyManager, { + "ApplyModificationsTemplate": (valueName, curValue, template) => { + // Called in helpers/ValueModification.js::ApplyValueModificationsToTemplate() + // as part of Tests T2 and T5 below. + let mods = isResearched ? templateTechModifications.with : templateTechModifications.without; + return GetTechModifiedProperty(mods, GetIdentityClasses(template.Identity), valueName, curValue); + }, + "ApplyModifications": (valueName, curValue, ent) => { + // Called in helpers/ValueModification.js::ApplyValueModificationsToEntity() + // as part of Tests T3, T6 and T7 below. + let mods = isResearched ? entityTechModifications.with : entityTechModifications.without; + return mods[valueName][ent].newValue; + } +}); + +// Create an entity with an Upgrade component: +AddMock(20, IID_Ownership, { + "GetOwner": () => playerID // Called in helpers/Player.js::QueryOwnerInterface(). +}); +AddMock(20, IID_Identity, { + "GetCiv": () => civCode // Called in components/Upgrade.js::init(). +}); +let cmpUpgrade = ConstructComponent(20, "Upgrade", template.Upgrade); +cmpUpgrade.owner = playerID; + +/** + * Now to start the test proper + * To start with, no techs are researched... + */ +// T1: Check the cost of the upgrade without a player value being passed (as it would be in the structree). +let parsed_template = GetTemplateDataHelper(template, null, {}, Resources); +TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); + +// T2: Check the value, with a player ID (as it would be in-session). +parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources); +TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); + +// T3: Check that the value is correct within the Update Component. +TS_ASSERT_UNEVAL_EQUALS(cmpUpgrade.GetUpgrades()[0].cost, { "stone": 100, "wood": 50, "time": 100 }); + +/** + * Tell the Upgrade component to start the Upgrade, + * then mark the technology that alters the upgrade cost as researched. + */ +cmpUpgrade.Upgrade("structures/"+civCode+"_defense_tower"); +isResearched = true; + +// T4: Check that the player-less value hasn't increased... +parsed_template = GetTemplateDataHelper(template, null, {}, Resources); +TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 100, "wood": 50, "time": 100 }); + +// T5: ...but the player-backed value has. +parsed_template = GetTemplateDataHelper(template, playerID, {}, Resources); +TS_ASSERT_UNEVAL_EQUALS(parsed_template.upgrades[0].cost, { "stone": 160, "wood": 25, "time": 90 }); + +// T6: The upgrade component should still be using the old resource cost (but new time cost) for the upgrade in progress... +TS_ASSERT_UNEVAL_EQUALS(cmpUpgrade.GetUpgrades()[0].cost, { "stone": 100, "wood": 50, "time": 90 }); + +// T7: ...but with the upgrade cancelled, it now uses the modified value. +cmpUpgrade.CancelUpgrade(playerID); +TS_ASSERT_UNEVAL_EQUALS(cmpUpgrade.GetUpgrades()[0].cost, { "stone": 160, "wood": 25, "time": 90 });