Unit testing my Auto Maintenance Log app
by bfarrell on Mar 2, 2025
To get started, I decided to write a test for my Auto Maintenance Log app, as it has a few different locations users can update data of various formats.
Preparing
The first step was to break out the bit of logic I was using for validation into its own function. That way I could import it into my Vitest test file.
I pass the Item
I am currently working with to this function that returns the applicable input values with the whitespace trimmed. The outlier here was the shop
value, which is an optional select field in the input form. I also import the Item
type that I use throughout the project.
src/utils/trimInput/trimInput.ts
import { Item } from "../../types"
export const trimInput = (item: Item) => {
const trimmedInput = {
...item,
cost: item.cost.trim(),
description: item.description.trim(),
shop: item.shop || "none",
mileage: item.mileage.trim(),
memo: item.memo.trim(),
}
return trimmedInput
}
Testing
The two cases I test for are if the trimInput
function properly removes whitespace and if the optional select field shop
value is set to "none" if the user doesn't select a shop.
Side note: here, I import the testItem
variable. The main reason I included it in it's own file was so that when writing my expected outputs, I could "spread" it and only test for the specific inputs that the user has control over. This allows me to cleanly maintain the "type" that TypeScript expects.
Here is the testItem
that has the values I am checking against. You can see the extra whitespace and empty shop
value.
src/utils/trimInput/testItem.ts
export const testItem = {
id: '123',
date: '2025-03-02',
cost: ' 100 ',
vehicle: 'Car',
description: ' Description here ',
shop: '',
mileage: ' 1200 ',
memo: ' Note here ',
};
Here is the test, expecting the values to have the whitespace removed and shop set to "none" by my trimInput
function I included above.
src/utils/trimInput/trimInput.test.ts
import { expect, it, describe } from 'vitest'
import { trimInput } from './trimInput'
import { testItem } from './testItem'
describe('trimInput', () => {
it('should trim all string fields and set shop to "none" if empty', () => {
const inputItem = testItem;
const expectedOutput = {
...testItem,
cost: '100',
description: 'Description here',
shop: 'none',
mileage: '1200',
memo: 'Note here'
}
const result = trimInput(inputItem)
expect(result).toEqual(expectedOutput)
})
it('should not change other fields if they are already trimmed', () => {
const inputItem = {
...testItem,
cost: '100',
description: 'Description here',
shop: 'Shop A',
mileage: '1200',
memo: 'Note here'
}
const expectedOutput = { ...inputItem }
const result = trimInput(inputItem)
expect(result).toEqual(expectedOutput)
})
})
Conclusion
Although this test is a simple one, it has already proven useful. It required me to think about where else this input type was taking place in my app. For example, when editing items. I realized that I had overlooked adding the trimInput
validation, which allowed whitespace when editing items in. To solve this, since I have trimInput
as a reusable utility function, I was able to easily add it to the function that handles saving items.