Skip to content

Instantly share code, notes, and snippets.

@truongluu
Forked from mustafadalga/App.test.ts
Created July 23, 2024 02:31
Show Gist options
  • Save truongluu/980651a6cd8843852a11264f1a45ecf9 to your computer and use it in GitHub Desktop.
Save truongluu/980651a6cd8843852a11264f1a45ecf9 to your computer and use it in GitHub Desktop.
Mocking localstorage in vitest
import { createStore, Store } from 'vuex';
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { key, store } from "@/store";
import type { User } from "@/types/types";
import App from "@/App.vue";
import { DOMWrapper, mount, VueWrapper } from "@vue/test-utils";
import type { State } from "@/store"
const localStorageMock: Storage = (() => {
let store: Record<string, string> = {};
return {
getItem: (key: string): string => store[key] ?? null,
setItem: (key: string, value: string): void => {
store[key] = value.toString();
},
removeItem: (key: string): void => {
delete store[key];
},
clear: (): void => {
store = {};
},
key: (index: number): string | null => "",
length: Object.keys(store).length
};
})();
function createVuexStore(): Store<State> {
return createStore({
state: {
user: {}
},
getters: {
getUser: (state: State): State["user"] => state.user
},
mutations: {
restoreUser(state: State): void {
const user: string | null = localStorage.getItem("user");
if (user) {
state.user = JSON.parse(user);
}
},
}
})
}
let originalLocalStorage: Storage;
beforeAll((): void => {
originalLocalStorage = window.localStorage;
(window as any).localStorage = localStorageMock;
});
afterAll((): void => {
(window as any).localStorage = originalLocalStorage;
});
describe("App.vue", (): void => {
const user: User = {
username: 'john',
fullName: 'Jon Doe',
job: 'Software Developer',
age: 14,
followers: 100,
following: 55,
repositories: 23
};
it('sets user data in local storage', async (): Promise<void> => {
await store.commit('setUser', user);
const localStorageUser: string | null = localStorage.getItem('user');
expect(localStorageUser).toBe(JSON.stringify(user));
});
it('clears user data from local storage', async ():Promise<void> => {
await store.commit('setUser', user);
await store.commit("clearUser");
const localStorageUser: string | null = localStorage.getItem('user');
expect(localStorageUser).toBeNull();
});
it('restores user data from local storage', async ():Promise<void> => {
localStorage.setItem("user", JSON.stringify(user))
const store: Store<State> = createVuexStore();
const wrapper: VueWrapper = mount(App, {
global: {
provide: {
[key as symbol]: store
}
}
});
const button: DOMWrapper<HTMLButtonElement> = await wrapper.find("button");
await button.trigger("click");
expect(wrapper.html()).toContain(user.username);
});
});
<script setup lang="ts">
import { useStore } from "vuex";
import type { User } from "@/types/types";
import { computed } from "vue";
import { key } from "@/store";
const store = useStore(key);
const userFromStore = computed<User>(() => store.getters.getUser);
function restore(){
store.commit("restoreUser")
}
</script>
<template>
<button @click="restore">restore User from Localstorage</button>
<div id="app" class="p-10" >
{{ userFromStore }}
</div>
</template>
import { createStore } from "vuex";
import type { InjectionKey } from 'vue'
import type { Store } from 'vuex'
import type { User } from "@/types/types";
export const key: InjectionKey<Store<State>> = Symbol()
export interface State {
user: User | {}
}
export const store: Store<State> = createStore<State>({
state: {
user: {}
},
getters: {
getUser: (state: State): State["user"] => state.user
},
mutations: {
setUser(state:State, user: User): void {
state.user = user;
localStorage.setItem("user", JSON.stringify(state.user));
},
clearUser(state: State): void {
state.user = {};
localStorage.removeItem("user");
},
restoreUser(state: State): void {
const user: string | null = localStorage.getItem("user");
if (user) {
state.user = JSON.parse(user);
}
},
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment