From 335e45096fce148adb639ddbcd026fee5b637b7c Mon Sep 17 00:00:00 2001 From: xenticore Date: Thu, 27 Mar 2025 14:03:54 -0400 Subject: [PATCH] test: add price service and prices.tf tests --- __tests__/priceService.test.ts | 109 +++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 __tests__/priceService.test.ts diff --git a/__tests__/priceService.test.ts b/__tests__/priceService.test.ts new file mode 100644 index 0000000..b9c421d --- /dev/null +++ b/__tests__/priceService.test.ts @@ -0,0 +1,109 @@ +import { describe, expect, test, jest, mock, beforeEach } from "bun:test"; +import { ItemPriceData, fetchPrice, fetchKeyPrice } from '../src/content/priceService' +import { PricesResponse, priceUsingPricesTF } from '../src/content/pricing/pricestf' +import { getStorageValue, setStorageValue } from '../src/content/storage' +import { defindex_key } from "../src/content/config"; + +// Mock the storage module +mock.module('../src/content/storage', () => ({ + getStorageValue: jest.fn(), + setStorageValue: jest.fn() +})) + +// Mock the pricing module +mock.module('../src/content/pricing/pricestf', () => ({ + priceUsingPricesTF: jest.fn() +})) + +describe('Price Service', () => { + const mockToken = 'test-token' + const mockDefIndex = 105 // Brigade Helm + const mockQuality = 11 // Strange + const mockSku = `${mockDefIndex};${mockQuality}` + const mockDate = new Date() + const mockTtl = 30 * 60 * 1000 // 30 minutes + + const mockPriceResponse: PricesResponse = { + keys: 1, + metal: 21.33 + } + + const mockKeyPriceResponse: PricesResponse = { + keys: 0, + metal: 60.11 + } + + const mockCachedData: ItemPriceData = { + sku: mockSku, + update: new Date(Date.now() - 15 * 60 * 1000), // 15 minutes ago + ttl: mockTtl, + keys: 1, + metal: 21.11, + scmPrice: 0 + } + + beforeEach(() => { + jest.clearAllMocks() + }) + + test('fetchPrice returns cached data if available and not expired', async () => { + (getStorageValue as jest.Mock).mockResolvedValue(mockCachedData) + + const result = await fetchPrice(mockToken, mockDefIndex, mockQuality) + + expect(getStorageValue).toHaveBeenCalledWith(expect.stringContaining(mockSku), null) + expect(result).toEqual(mockCachedData) + }) + + test('fetchPrice fetches new data when cache is expired', async () => { + const expiredCache: ItemPriceData = { ...mockCachedData, update: new Date(Date.now() - 2 * mockTtl) }; + (getStorageValue as jest.Mock).mockResolvedValue(expiredCache); + (priceUsingPricesTF as jest.Mock).mockResolvedValue(mockPriceResponse) + + const result = await fetchPrice(mockToken, mockDefIndex, mockQuality) + + expect(priceUsingPricesTF).toHaveBeenCalledWith(mockToken, mockDefIndex, mockQuality) + expect(setStorageValue).toHaveBeenCalled() + expect(result.metal).not.toBe(mockCachedData.metal) + expect(result.metal).toBe(mockPriceResponse.metal) + }) + + test('fetchPrice rejects with 401 when no token provided', async () => { + await expect(fetchPrice('', mockDefIndex, mockQuality)).rejects.toBe(401) + }) + + test('fetchPrice handles pricing API errors', async () => { + const testError = 500; + (priceUsingPricesTF as jest.Mock).mockRejectedValue(testError); + (getStorageValue as jest.Mock).mockResolvedValue(null) + + await expect(fetchPrice(mockToken, mockDefIndex, mockQuality)).rejects.toBe(testError) + }) + + test('fetchKeyPrice uses correct parameters', async () => { + (getStorageValue as jest.Mock).mockResolvedValue(null); + (priceUsingPricesTF as jest.Mock).mockResolvedValue(mockKeyPriceResponse) + + const result = await fetchKeyPrice(mockToken) + + expect(priceUsingPricesTF).toHaveBeenCalledWith(mockToken, defindex_key, 6) + expect(result.keys).toBe(0) // A key cannot cost a key :P + expect(result.metal).toBe(mockKeyPriceResponse.metal) + }) + + test('ItemPriceData.toString() returns formatted string', () => { + const data = new ItemPriceData() + data.sku = mockSku + data.update = mockDate + data.ttl = mockTtl + data.keys = 1 + data.metal = 10.66 + data.scmPrice = 2.68 + + const result = data.toString() + expect(result).toContain(`Price for ${mockSku}`) + expect(result).toContain(`"keys":${data.keys}`) + expect(result).toContain(`"metal":${data.metal}`) + expect(result).toContain(`"scmPrice":${data.scmPrice}`) + }) +})