You've already forked tf2wikipricing
price update time was not properly serialized as a number like the schema was, and led to dates being stored as empty objects. UI code also did not check if date was NaN, and rendered "invalid date" instead.
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
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.getTime()
|
|
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(mockDate.toString())
|
|
expect(result).toContain(new Date(mockDate.getTime() + mockTtl).toString())
|
|
expect(result).toContain(`"keys":${data.keys}`)
|
|
expect(result).toContain(`"metal":${data.metal}`)
|
|
expect(result).toContain(`"scmPrice":${data.scmPrice}`)
|
|
})
|
|
})
|