Тестирование компонентов svelte с помощью svelte/store
При тестировании компонентов svelte с помощью jest & @testing-library/svelte состояние распределяется между тестами, его можно удалить после каждого теста, поэтому у меня есть больше изолированных модульных тестов.
магазин / тема
import { writable } from "svelte/store";
export const LOCAL_STORAGE_KEY = "current:theme";
export const THEMES = {
DARK: "dark",
LIGHT: "light"
};
export const MATCH_DARK_THEME = "(prefers-color-scheme: dark)";
export const IS_USER_PREFERNCE_DARK =
window.matchMedia && window.matchMedia(MATCH_DARK_THEME).matches;
export const DEFAULT_THEME =
localStorage.getItem(LOCAL_STORAGE_KEY) || IS_USER_PREFERNCE_DARK
? THEMES.DARK
: THEMES.LIGHT;
export const theme = writable(DEFAULT_THEME);
поскольку нет DI, хранилище используется совместно между тестами, я мог бы сбросить значение по умолчанию в beforeEach, но пытаясь увидеть, есть ли лучшее решение.
ThemeSwitcher.spec.js
it("should be change body class on click", async () => {
const { container } = render(ThemeSwitcher);
expect(container.className).toEqual("theme-light");
await fireEvent.click(getButton(container));
expect(container.className).toEqual("theme-dark");
});
it("should render the sun if in light mode", async () => {
const { getByText } = render(ThemeSwitcher);
//default should be light mode but returns dark.
const sun = getByText("Light theme on: Sun");
expect(sun).toBeTruthy();
});
1 ответ
Я предпочитаю обернуть svelte store в общий класс для удобства использования.
это мое
Store.ts
import { writable, get, Writable } from "svelte/store"
/** Callback to inform of a value updates. */
export declare type Subscriber<T> = (value: T) => void
/** Unsubscribes from value updates. */
export declare type Unsubscriber = () => void
/** Callback to update a value. */
export declare type Updater<T> = (value: T) => T
/** Cleanup logic callback. */
export declare type Invalidator<T> = (value?: T) => void
class Store<T> implements Writable<T> {
private intialValue: T
private wrappee: Writable<T>
// implements Writable
subscribe: (run: Subscriber<T>, invalidate?: Invalidator<T>) => Unsubscriber
set: (value: T) => void
update: (updater: Updater<T>) => void
constructor(value: T) {
this.intialValue = value
const _store = writable(value)
const { subscribe, set, update } = _store
this.subscribe = subscribe
this.set = set
this.update = update
this.wrappee = _store
}
get() {
return get(this.wrappee)
}
reset() {
this.set(this.intialValue)
}
refresh() {
this.set(this.get())
}
}
Вы можете расширить общий класс Store, чтобы создать свой новый магазин подобным образом.
arrayStringStore.ts
export default class ArrayStringStore extends Store<string[]> {
constructor(arr: string[] = []) {
super(arr)
}
// easy to add more convenience method
add(item: string) {
this.update(arr => [...arr, item])
}
}
Например: у меня есть экземпляр ArrayStringStore, который
exampleStore
const exampleStore = new ArrayStringStore()
Вы можете легко сбросить значение этого хранилища перед каждым тестовым примером с помощью
в вашем тестовом файле.
beforeEach(() => {
exampleStore.reset()
})
Примечание: вы можете получить стоимость магазина с помощью
exampleStore.get()
, не нужноimport { get } from svelte/store
в каждом файле.