From dcf45c2740b02ed04d72122f927e6010f97ada99 Mon Sep 17 00:00:00 2001 From: xenticore Date: Wed, 16 Apr 2025 14:04:39 -0400 Subject: [PATCH] refactor: split currency and key/metal formatting into separate units this simplifies functions and tests, and will make currency optional/variable later --- __tests__/currency.test.ts | 17 +++++++++++++++++ __tests__/formatting.test.ts | 18 +++++++++--------- src/content/uiRenderer.ts | 19 +++++++++++++++++-- src/content/utils/currency.ts | 8 ++++++++ src/content/utils/formatting.ts | 8 -------- 5 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 __tests__/currency.test.ts create mode 100644 src/content/utils/currency.ts diff --git a/__tests__/currency.test.ts b/__tests__/currency.test.ts new file mode 100644 index 0000000..d38d9ff --- /dev/null +++ b/__tests__/currency.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, test, jest, mock, beforeEach } from "bun:test"; +import { convertTF2PriceToUSD } from '../src/content/utils/currency' + +mock.module('../src/content/config', () => ({ + conversion_ref_usd: 0.05 // Mock conversion rate +})) + + +describe('Currency Service', () => { + beforeEach(() => { + jest.clearAllMocks() + }); + + test('convertTF2PriceToUSD returns correct price', () => { + expect(convertTF2PriceToUSD(1, 10, 50)).toBe(3); + }) +}) diff --git a/__tests__/formatting.test.ts b/__tests__/formatting.test.ts index a2b2bbc..9f3085c 100644 --- a/__tests__/formatting.test.ts +++ b/__tests__/formatting.test.ts @@ -16,34 +16,34 @@ describe('formatPrice', () => { }); test('formats price with keys and metal', () => { - expect(formatPrice(2, 10, 50)).toBe('2.2 keys (US$5.50)'); + expect(formatPrice(2, 10, 50)).toBe('2.2 keys'); expect($T).toHaveBeenCalledWith('%@ keys'); }); test('formats price with metal only', () => { - expect(formatPrice(0, 15.75, 50)).toBe('15.75 ref (US$0.79)'); + expect(formatPrice(0, 15.75, 50)).toBe('15.75 ref'); }); test('formats price with metal only and whole number', () => { - expect(formatPrice(0, 3, 50)).toBe('3 ref (US$0.16)'); + expect(formatPrice(0, 3, 50)).toBe('3 ref'); }); test('uses singular key form', () => { - expect(formatPrice(1, 0, 50)).toBe('1 key (US$2.50)'); + expect(formatPrice(1, 0, 50)).toBe('1 key'); expect($T).toHaveBeenCalledWith('%@ key'); }); test('rounds USD up to nearest cent', () => { - expect(formatPrice(3, 7.33, 35)).toBe('3.21 keys (US$5.62)'); // (3 * 35 + 7.33) * 0.05 = 5.6165 → 5.62 + expect(formatPrice(3, 7.33, 35)).toBe('3.21 keys'); // (3 * 35 + 7.33) * 0.05 = 5.6165 → 5.62 }); test('handles different locale formatting', () => { - expect(formatPrice(2, 10, 50, 'de')).toMatch(/2,2 keys \(US\$5,50\)/); - expect(formatPrice(0, 15.75, 50, 'de')).toMatch(/15,75 ref \(US\$0,79\)/); + expect(formatPrice(2, 10, 50, 'de')).toMatch(/2,2 keys/); + expect(formatPrice(0, 15.75, 50, 'de')).toMatch(/15,75 ref/); }); test('handles zero values', () => { - expect(formatPrice(0, 0, 50)).toBe('0 ref (US$0.00)'); - expect(formatPrice(0, 0, 50, 'de')).toMatch(/0 ref \(US\$0,00\)/); + expect(formatPrice(0, 0, 50)).toBe('0 ref'); + expect(formatPrice(0, 0, 50, 'de')).toMatch(/0 ref/); }); }); \ No newline at end of file diff --git a/src/content/uiRenderer.ts b/src/content/uiRenderer.ts index 3d65acf..c62f1ba 100644 --- a/src/content/uiRenderer.ts +++ b/src/content/uiRenderer.ts @@ -1,4 +1,5 @@ import { ItemPriceData } from "./priceService"; +import { convertTF2PriceToUSD } from "./utils/currency"; import { formatPrice } from "./utils/formatting"; import { $T } from "./utils/localization"; @@ -19,8 +20,22 @@ export function createPriceRow(qualityName: string, data: ItemPriceData, keyPric const priceData = document.createElement("td"); const priceLink = document.createElement("span"); - const priceString = data ? formatPrice(data.keys, data.metal, keyPrice.metal, locale).trim() : $T('Data unavailable') - priceLink.innerHTML = priceString // + `
$${data.scmPrice}` + var priceString: string = '' + + if(data) { + const currencyFormatter = new Intl.NumberFormat(locale, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }); + + priceString += [ + formatPrice(data.keys, data.metal, keyPrice.metal, locale).trim(), + '(US$' + currencyFormatter.format(convertTF2PriceToUSD(data.keys, data.metal, keyPrice.metal)) + ')' + ].join(' ').trim() + } else { + priceString += $T('Data unavailable') + } + priceLink.innerHTML = priceString priceData.appendChild(priceLink); priceRow.appendChild(priceData); return priceRow; diff --git a/src/content/utils/currency.ts b/src/content/utils/currency.ts new file mode 100644 index 0000000..a84202f --- /dev/null +++ b/src/content/utils/currency.ts @@ -0,0 +1,8 @@ +import { conversion_ref_usd } from '../config'; + +export function convertTF2PriceToUSD(keys: number, metal: number, keyPrice: number): number { + const pureMetal = (keys * keyPrice) + metal; + + // Round price up to nearest cent + return Math.ceil(pureMetal * conversion_ref_usd * 100) / 100 +} diff --git a/src/content/utils/formatting.ts b/src/content/utils/formatting.ts index 3ac4b9c..4c27a1e 100644 --- a/src/content/utils/formatting.ts +++ b/src/content/utils/formatting.ts @@ -7,7 +7,6 @@ function toFixed(num: number, fixed: number) { } export function formatPrice(keys: number, metal: number, keyPrice: number, locale: string = 'en') { - const pureMetal = (keys * keyPrice) + metal; const formattedKeys = +(keys + (metal / keyPrice)).toFixed(2) var output: string = '' @@ -16,13 +15,6 @@ export function formatPrice(keys: number, metal: number, keyPrice: number, local } else { output += $T("%@ ref").replace('%@', (+toFixed(metal, 2)).toLocaleString(locale)) } - const currencyFormatter = new Intl.NumberFormat(locale, { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }); - // Round price up to nearest cent - const price = Math.ceil(pureMetal * conversion_ref_usd * 100) / 100 - output += ` (US$${currencyFormatter.format(price)})` return output; }