utils.spec.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. import {PlanDetailsLookupFixture} from 'getsentry-test/fixtures/planDetailsLookup';
  2. import {DataCategory} from 'sentry/types/core';
  3. import {PlanTier} from 'getsentry/types';
  4. import * as utils from 'getsentry/views/amCheckout/utils';
  5. import {getCheckoutAPIData} from 'getsentry/views/amCheckout/utils';
  6. describe('utils', function () {
  7. const teamPlan = PlanDetailsLookupFixture('am1_team')!;
  8. const teamPlanAnnual = PlanDetailsLookupFixture('am1_team_auf')!;
  9. const bizPlan = PlanDetailsLookupFixture('am1_business')!;
  10. const bizPlanAnnual = PlanDetailsLookupFixture('am1_business_auf')!;
  11. describe('getReservedTotal', function () {
  12. it('can get base price for team plan', function () {
  13. const priceDollars = utils.getReservedTotal({
  14. plan: teamPlan,
  15. reserved: {
  16. errors: 50_000,
  17. transactions: 100_000,
  18. attachments: 1,
  19. },
  20. });
  21. expect(priceDollars).toBe('29');
  22. });
  23. it('can get base price for annual team plan', function () {
  24. const priceDollars = utils.getReservedTotal({
  25. plan: teamPlanAnnual,
  26. reserved: {
  27. errors: 50_000,
  28. transactions: 100_000,
  29. attachments: 1,
  30. },
  31. });
  32. expect(priceDollars).toBe('312');
  33. });
  34. it('can get base price for business plan', function () {
  35. const priceDollars = utils.getReservedTotal({
  36. plan: bizPlan,
  37. reserved: {
  38. errors: 50_000,
  39. transactions: 100_000,
  40. attachments: 1,
  41. },
  42. });
  43. expect(priceDollars).toBe('89');
  44. });
  45. it('can get base price for annual business plan', function () {
  46. const priceDollars = utils.getReservedTotal({
  47. plan: bizPlanAnnual,
  48. reserved: {
  49. errors: 50_000,
  50. transactions: 100_000,
  51. attachments: 1,
  52. },
  53. });
  54. expect(priceDollars).toBe('960');
  55. });
  56. it('adds comma to price', function () {
  57. const priceDollars = utils.getReservedTotal({
  58. plan: bizPlanAnnual,
  59. reserved: {
  60. errors: 200_000,
  61. transactions: 100_000,
  62. attachments: 1,
  63. },
  64. });
  65. expect(priceDollars).toBe('1,992');
  66. });
  67. });
  68. describe('discountPrice', function () {
  69. it('discounts price correctly', function () {
  70. expect(
  71. utils.getDiscountedPrice({
  72. basePrice: 1000,
  73. amount: 10 * 100,
  74. discountType: 'percentPoints',
  75. creditCategory: 'subscription',
  76. })
  77. ).toBe(900);
  78. expect(
  79. utils.getDiscountedPrice({
  80. basePrice: 8900,
  81. amount: 40 * 100,
  82. discountType: 'percentPoints',
  83. creditCategory: 'subscription',
  84. })
  85. ).toBe(5340);
  86. expect(
  87. utils.getDiscountedPrice({
  88. basePrice: 10000,
  89. amount: 1000,
  90. discountType: 'amountCents',
  91. creditCategory: 'subscription',
  92. })
  93. ).toBe(9000);
  94. });
  95. });
  96. describe('formatPrice', function () {
  97. it('formats price correctly', function () {
  98. expect(utils.formatPrice({cents: 0})).toBe('0');
  99. expect(utils.formatPrice({cents: 1500})).toBe('15');
  100. expect(utils.formatPrice({cents: 1510})).toBe('15.10');
  101. expect(utils.formatPrice({cents: 92400})).toBe('924');
  102. expect(utils.formatPrice({cents: 119400})).toBe('1,194');
  103. expect(utils.formatPrice({cents: -1510})).toBe('-15.10');
  104. });
  105. });
  106. describe('displayPrice', function () {
  107. it('formats price correctly', function () {
  108. expect(utils.displayPrice({cents: 0})).toBe('$0');
  109. expect(utils.displayPrice({cents: 1500})).toBe('$15');
  110. expect(utils.displayPrice({cents: 92430})).toBe('$924.30');
  111. expect(utils.displayPrice({cents: 119499})).toBe('$1,194.99');
  112. expect(utils.displayPrice({cents: -92430})).toBe('-$924.30');
  113. });
  114. });
  115. describe('displayPriceWithCents', function () {
  116. it('formats price correctly', function () {
  117. expect(utils.displayPriceWithCents({cents: 0})).toBe('$0.00');
  118. expect(utils.displayPriceWithCents({cents: 1500})).toBe('$15.00');
  119. expect(utils.displayPriceWithCents({cents: 92430})).toBe('$924.30');
  120. expect(utils.displayPriceWithCents({cents: 119499})).toBe('$1,194.99');
  121. expect(utils.displayPriceWithCents({cents: -92430})).toBe('-$924.30');
  122. });
  123. });
  124. describe('displayUnitPrice', function () {
  125. it('formats unit price correctly', function () {
  126. expect(utils.displayUnitPrice({cents: 24, minDigits: 2, maxDigits: 2})).toBe(
  127. '$0.24'
  128. );
  129. expect(utils.displayUnitPrice({cents: 24.5, minDigits: 2, maxDigits: 2})).toBe(
  130. '$0.25'
  131. );
  132. expect(utils.displayUnitPrice({cents: 245, minDigits: 2, maxDigits: 2})).toBe(
  133. '$2.45'
  134. );
  135. expect(utils.displayUnitPrice({cents: 0.0167})).toBe('$0.000167');
  136. expect(utils.displayUnitPrice({cents: 0.528})).toBe('$0.00528');
  137. });
  138. });
  139. describe('getEventsWithUnit', function () {
  140. it('returns correct event amount', function () {
  141. expect(utils.getEventsWithUnit(1_000, DataCategory.ERRORS)).toBe('1K');
  142. expect(utils.getEventsWithUnit(50_000, DataCategory.ERRORS)).toBe('50K');
  143. expect(utils.getEventsWithUnit(1_000_000, DataCategory.TRANSACTIONS)).toBe('1M');
  144. expect(utils.getEventsWithUnit(4_000_000, DataCategory.TRANSACTIONS)).toBe('4M');
  145. expect(utils.getEventsWithUnit(1, DataCategory.ATTACHMENTS)).toBe('1GB');
  146. expect(utils.getEventsWithUnit(25, DataCategory.ATTACHMENTS)).toBe('25GB');
  147. expect(utils.getEventsWithUnit(1_000, DataCategory.ATTACHMENTS)).toBe('1,000GB');
  148. expect(utils.getEventsWithUnit(4_000, DataCategory.ATTACHMENTS)).toBe('4,000GB');
  149. expect(utils.getEventsWithUnit(1_000_000_000, DataCategory.ERRORS)).toBe('1B');
  150. expect(utils.getEventsWithUnit(10_000_000_000, DataCategory.ERRORS)).toBe('10B');
  151. });
  152. });
  153. describe('utils.getBucket', function () {
  154. it('can get exact bucket by events', function () {
  155. const events = 100_000;
  156. const bucket = utils.getBucket({events, buckets: bizPlan.planCategories.errors});
  157. expect(bucket.events).toBe(events);
  158. });
  159. it('can get exact bucket by events with minimize strategy', function () {
  160. const events = 100_000;
  161. const bucket = utils.getBucket({
  162. events,
  163. buckets: bizPlan.planCategories.errors,
  164. shouldMinimize: true,
  165. });
  166. expect(bucket.events).toBe(events);
  167. });
  168. it('can get approximate bucket if event level does not exist', function () {
  169. const events = 90_000;
  170. const bucket = utils.getBucket({events, buckets: bizPlan.planCategories.errors});
  171. expect(bucket.events).toBeGreaterThanOrEqual(events);
  172. });
  173. it('can get approximate bucket if event level does not exist with minimize strategy', function () {
  174. const events = 90_000;
  175. const bucket = utils.getBucket({
  176. events,
  177. buckets: bizPlan.planCategories.errors,
  178. shouldMinimize: true,
  179. });
  180. expect(bucket.events).toBeLessThanOrEqual(events);
  181. });
  182. it('can get first bucket by events', function () {
  183. const events = 0;
  184. const bucket = utils.getBucket({
  185. events,
  186. buckets: teamPlan.planCategories.transactions,
  187. });
  188. expect(bucket.events).toBeGreaterThanOrEqual(events);
  189. });
  190. it('can get first bucket by events with minimize strategy', function () {
  191. const events = 0;
  192. const bucket = utils.getBucket({
  193. events,
  194. buckets: teamPlan.planCategories.transactions,
  195. shouldMinimize: true,
  196. });
  197. expect(bucket.events).toBeGreaterThanOrEqual(events);
  198. });
  199. it('can get last bucket by events', function () {
  200. const events = 1_000_000;
  201. const bucket = utils.getBucket({
  202. events,
  203. buckets: teamPlan.planCategories.attachments,
  204. });
  205. expect(bucket.events).toBeLessThanOrEqual(events);
  206. });
  207. it('can get last bucket by events with minimize strategy', function () {
  208. const events = 1_000_000;
  209. const bucket = utils.getBucket({
  210. events,
  211. buckets: teamPlan.planCategories.attachments,
  212. shouldMinimize: true,
  213. });
  214. expect(bucket.events).toBeLessThanOrEqual(events);
  215. });
  216. it('can get exact bucket by price', function () {
  217. const price = 48000;
  218. const bucket = utils.getBucket({
  219. price,
  220. buckets: bizPlan.planCategories.transactions,
  221. });
  222. expect(bucket.price).toBe(price);
  223. expect(bucket.events).toBe(3_500_000);
  224. });
  225. it('can get exact bucket by price with minimize strategy', function () {
  226. const price = 48000;
  227. const bucket = utils.getBucket({
  228. price,
  229. buckets: bizPlan.planCategories.transactions,
  230. shouldMinimize: true,
  231. });
  232. expect(bucket.price).toBe(price);
  233. expect(bucket.events).toBe(3_500_000);
  234. });
  235. it('can get approximate bucket if price level does not exist', function () {
  236. const price = 60000;
  237. const bucket = utils.getBucket({
  238. price,
  239. buckets: bizPlan.planCategories.transactions,
  240. });
  241. expect(bucket.price).toBeGreaterThanOrEqual(price);
  242. expect(bucket.events).toBe(4_500_000);
  243. });
  244. it('can get approximate bucket if price level does not exist with minimize strategy', function () {
  245. const price = 60000;
  246. const bucket = utils.getBucket({
  247. price,
  248. buckets: bizPlan.planCategories.transactions,
  249. shouldMinimize: true,
  250. });
  251. expect(bucket.price).toBeLessThanOrEqual(price);
  252. expect(bucket.events).toBe(4_000_000);
  253. });
  254. it('can get first bucket by price', function () {
  255. const price = 0;
  256. const bucket = utils.getBucket({
  257. price,
  258. buckets: teamPlan.planCategories.transactions,
  259. });
  260. expect(bucket.price).toBe(price);
  261. });
  262. it('can get first bucket by price with minimize strategy', function () {
  263. const price = 0;
  264. const bucket = utils.getBucket({
  265. price,
  266. buckets: teamPlan.planCategories.transactions,
  267. shouldMinimize: true,
  268. });
  269. expect(bucket.price).toBe(price);
  270. });
  271. it('can get last bucket by price', function () {
  272. const price = 263500;
  273. const bucket = utils.getBucket({
  274. price,
  275. buckets: teamPlan.planCategories.transactions,
  276. });
  277. expect(bucket.price).toBeLessThanOrEqual(price);
  278. });
  279. it('can get last bucket by price with minimize strategy', function () {
  280. const price = 263500;
  281. const bucket = utils.getBucket({
  282. price,
  283. buckets: teamPlan.planCategories.transactions,
  284. shouldMinimize: true,
  285. });
  286. expect(bucket.price).toBeLessThanOrEqual(price);
  287. });
  288. });
  289. describe('utils.getToggleTier', function () {
  290. it('gets the correct toggle tier given a checkout tier', function () {
  291. expect(utils.getToggleTier(undefined)).toBeNull();
  292. expect(utils.getToggleTier(PlanTier.AM3)).toBeNull();
  293. expect(utils.getToggleTier(PlanTier.AM2)).toBe(PlanTier.AM1);
  294. expect(utils.getToggleTier(PlanTier.AM1)).toBe(PlanTier.AM2);
  295. });
  296. });
  297. describe('utils.getCheckoutAPIData', function () {
  298. it('returns correct reserved api data', function () {
  299. const formData = {
  300. plan: 'am3_business',
  301. onDemandMaxSpend: 100,
  302. reserved: {
  303. errors: 10,
  304. transactions: 20,
  305. replays: 30,
  306. spans: 40,
  307. monitorSeats: 50,
  308. uptime: 60,
  309. attachments: 70,
  310. profileDuration: 80,
  311. },
  312. };
  313. expect(getCheckoutAPIData({formData})).toEqual({
  314. onDemandMaxSpend: 100,
  315. plan: 'am3_business',
  316. referrer: 'billing',
  317. reservedErrors: 10,
  318. reservedTransactions: 20,
  319. reservedReplays: 30,
  320. reservedSpans: 40,
  321. reservedMonitorSeats: 50,
  322. reservedUptime: 60,
  323. reservedAttachments: 70,
  324. reservedProfileDuration: 80,
  325. });
  326. });
  327. });
  328. });