1
0

StoreTests.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Threading;
  4. using Content.Server.Store.Systems;
  5. using Content.Server.Traitor.Uplink;
  6. using Content.Shared.FixedPoint;
  7. using Content.Shared.Inventory;
  8. using Content.Shared.Mind;
  9. using Content.Shared.Store;
  10. using Content.Shared.Store.Components;
  11. using Content.Shared.StoreDiscount.Components;
  12. using Robust.Shared.GameObjects;
  13. using Robust.Shared.Prototypes;
  14. using Robust.Shared.Random;
  15. namespace Content.IntegrationTests.Tests;
  16. [TestFixture]
  17. public sealed class StoreTests
  18. {
  19. [TestPrototypes]
  20. private const string Prototypes = @"
  21. - type: entity
  22. name: InventoryPdaDummy
  23. id: InventoryPdaDummy
  24. parent: BasePDA
  25. components:
  26. - type: Clothing
  27. QuickEquip: false
  28. slots:
  29. - idcard
  30. - type: Pda
  31. ";
  32. [Test]
  33. public async Task StoreDiscountAndRefund()
  34. {
  35. await using var pair = await PoolManager.GetServerClient();
  36. var server = pair.Server;
  37. var testMap = await pair.CreateTestMap();
  38. await server.WaitIdleAsync();
  39. var serverRandom = server.ResolveDependency<IRobustRandom>();
  40. serverRandom.SetSeed(534);
  41. var entManager = server.ResolveDependency<IEntityManager>();
  42. var mapSystem = server.System<SharedMapSystem>();
  43. var prototypeManager = server.ProtoMan;
  44. Assert.That(mapSystem.IsInitialized(testMap.MapId));
  45. EntityUid human = default;
  46. EntityUid uniform = default;
  47. EntityUid pda = default;
  48. var uplinkSystem = entManager.System<UplinkSystem>();
  49. var listingPrototypes = prototypeManager.EnumeratePrototypes<ListingPrototype>()
  50. .ToArray();
  51. var coordinates = testMap.GridCoords;
  52. await server.WaitAssertion(() =>
  53. {
  54. var invSystem = entManager.System<InventorySystem>();
  55. var mindSystem = entManager.System<SharedMindSystem>();
  56. human = entManager.SpawnEntity("HumanUniformDummy", coordinates);
  57. uniform = entManager.SpawnEntity("UniformDummy", coordinates);
  58. pda = entManager.SpawnEntity("InventoryPdaDummy", coordinates);
  59. Assert.That(invSystem.TryEquip(human, uniform, "jumpsuit"));
  60. Assert.That(invSystem.TryEquip(human, pda, "id"));
  61. var mind = mindSystem.CreateMind(null);
  62. mindSystem.TransferTo(mind, human, mind: mind);
  63. FixedPoint2 originalBalance = 20;
  64. uplinkSystem.AddUplink(human, originalBalance, null, true);
  65. var storeComponent = entManager.GetComponent<StoreComponent>(pda);
  66. var discountComponent = entManager.GetComponent<StoreDiscountComponent>(pda);
  67. Assert.That(
  68. discountComponent.Discounts,
  69. Has.Exactly(6).Items,
  70. $"After applying discount total discounted items count was expected to be '6' "
  71. + $"but was actually {discountComponent.Discounts.Count}- this can be due to discount "
  72. + $"categories settings (maxItems, weight) not being realistically set, or default "
  73. + $"discounted count being changed from '6' in StoreDiscountSystem.InitializeDiscounts."
  74. );
  75. var discountedListingItems = storeComponent.FullListingsCatalog
  76. .Where(x => x.IsCostModified)
  77. .OrderBy(x => x.ID)
  78. .ToArray();
  79. Assert.That(discountComponent.Discounts
  80. .Select(x => x.ListingId.Id),
  81. Is.EquivalentTo(discountedListingItems.Select(x => x.ID)),
  82. $"{nameof(StoreComponent)}.{nameof(StoreComponent.FullListingsCatalog)} does not contain all "
  83. + $"items that are marked as discounted, or they don't have flag '{nameof(ListingDataWithCostModifiers.IsCostModified)}'"
  84. + $"flag as 'true'. This marks the fact that cost modifier of discount is not applied properly!"
  85. );
  86. // The storeComponent returns discounted items with conditions randomly, so we remove these to sanitize the data.
  87. foreach (var discountedItem in discountedListingItems)
  88. {
  89. discountedItem.Conditions = null;
  90. }
  91. // Refund action requests re-generation of listing items so we will be re-acquiring items from component a lot of times.
  92. var itemIds = discountedListingItems.Select(x => x.ID);
  93. foreach (var itemId in itemIds)
  94. {
  95. Assert.Multiple(() =>
  96. {
  97. storeComponent.RefundAllowed = true;
  98. var discountedListingItem = storeComponent.FullListingsCatalog.First(x => x.ID == itemId);
  99. var plainDiscountedCost = discountedListingItem.Cost[UplinkSystem.TelecrystalCurrencyPrototype];
  100. var prototype = listingPrototypes.First(x => x.ID == discountedListingItem.ID);
  101. var prototypeCost = prototype.Cost[UplinkSystem.TelecrystalCurrencyPrototype];
  102. var discountDownTo = prototype.DiscountDownTo[UplinkSystem.TelecrystalCurrencyPrototype];
  103. Assert.That(plainDiscountedCost.Value, Is.GreaterThanOrEqualTo(discountDownTo.Value), "Expected discounted cost to be greater then DiscountDownTo value.");
  104. Assert.That(plainDiscountedCost.Value, Is.LessThan(prototypeCost.Value), "Expected discounted cost to be lower then prototype cost.");
  105. var buyMsg = new StoreBuyListingMessage(discountedListingItem.ID){Actor = human};
  106. server.EntMan.EventBus.RaiseComponentEvent(pda, storeComponent, buyMsg);
  107. var newBalance = storeComponent.Balance[UplinkSystem.TelecrystalCurrencyPrototype];
  108. Assert.That(newBalance.Value, Is.EqualTo((originalBalance - plainDiscountedCost).Value), "Expected to have balance reduced by discounted cost");
  109. Assert.That(
  110. discountedListingItem.IsCostModified,
  111. Is.False,
  112. $"Expected item cost to not be modified after Buying discounted item."
  113. );
  114. var costAfterBuy = discountedListingItem.Cost[UplinkSystem.TelecrystalCurrencyPrototype];
  115. Assert.That(costAfterBuy.Value, Is.EqualTo(prototypeCost.Value), "Expected cost after discount refund to be equal to prototype cost.");
  116. var refundMsg = new StoreRequestRefundMessage { Actor = human };
  117. server.EntMan.EventBus.RaiseComponentEvent(pda, storeComponent, refundMsg);
  118. // get refreshed item after refund re-generated items
  119. discountedListingItem = storeComponent.FullListingsCatalog.First(x => x.ID == itemId);
  120. // The storeComponent can give a discounted item a condition at random, so we remove it to sanitize the data.
  121. discountedListingItem.Conditions = null;
  122. var afterRefundBalance = storeComponent.Balance[UplinkSystem.TelecrystalCurrencyPrototype];
  123. Assert.That(afterRefundBalance.Value, Is.EqualTo(originalBalance.Value), "Expected refund to return all discounted cost value.");
  124. Assert.That(
  125. discountComponent.Discounts.First(x => x.ListingId == discountedListingItem.ID).Count,
  126. Is.EqualTo(0),
  127. "Discounted count should still be zero even after refund."
  128. );
  129. Assert.That(
  130. discountedListingItem.IsCostModified,
  131. Is.False,
  132. $"Expected item cost to not be modified after Buying discounted item (even after refund was done)."
  133. );
  134. var costAfterRefund = discountedListingItem.Cost[UplinkSystem.TelecrystalCurrencyPrototype];
  135. Assert.That(costAfterRefund.Value, Is.EqualTo(prototypeCost.Value), "Expected cost after discount refund to be equal to prototype cost.");
  136. });
  137. }
  138. });
  139. await pair.CleanReturnAsync();
  140. }
  141. }