admin管理员组文章数量:1024624
Using vue-test-utils to test the ponent using pinia, I need to modify the value of the state stored in pinia, but I have tried many methods to no avail. The original ponent and store files are as follows.
// HelloWorld.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { useTestStore } from "@/stores/test";
import { mapState } from "pinia";
export default {
name: "HelloWorld",
puted: {
...mapState(useTestStore, ["title"]),
},
};
</script>
// @/stores/test.js
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return { title: "hhhhh" };
},
});
The following methods have been tried.
- Import the store used within the ponent to the test code and make changes directly, but the changes cannot affect the ponent.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
import { useTestStore } from "@/stores/test";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
},
});
const store = useTestStore();
store.title = "xxxxx";
console.log(wrapper.text()) //"hhhhh";
});
- Using the initialState in an attempt to overwrite the contents of the original store, but again without any effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia({ initialState: { title: "xxxxx" } })],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Modify the TestingPinia object passed to global.plugins in the test code, but again has no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const pinia = createTestingPinia();
pinia.state.value.title = "xxxxx";
const wrapper = mount(HelloWorld, {
global: {
plugins: [pinia],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Use global.mocks to mock the states used in the ponent, but this only works for the states passed in with setup() in the ponent, while the ones passed in with mapState() have no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
mocks: { title: "xxxxx" },
},
});
console.log(wrapper.text()) //"hhhhh"
});
Using vue-test-utils to test the ponent using pinia, I need to modify the value of the state stored in pinia, but I have tried many methods to no avail. The original ponent and store files are as follows.
// HelloWorld.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { useTestStore } from "@/stores/test";
import { mapState } from "pinia";
export default {
name: "HelloWorld",
puted: {
...mapState(useTestStore, ["title"]),
},
};
</script>
// @/stores/test.js
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return { title: "hhhhh" };
},
});
The following methods have been tried.
- Import the store used within the ponent to the test code and make changes directly, but the changes cannot affect the ponent.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
import { useTestStore } from "@/stores/test";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
},
});
const store = useTestStore();
store.title = "xxxxx";
console.log(wrapper.text()) //"hhhhh";
});
- Using the initialState in an attempt to overwrite the contents of the original store, but again without any effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia({ initialState: { title: "xxxxx" } })],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Modify the TestingPinia object passed to global.plugins in the test code, but again has no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const pinia = createTestingPinia();
pinia.state.value.title = "xxxxx";
const wrapper = mount(HelloWorld, {
global: {
plugins: [pinia],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Use global.mocks to mock the states used in the ponent, but this only works for the states passed in with setup() in the ponent, while the ones passed in with mapState() have no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
mocks: { title: "xxxxx" },
},
});
console.log(wrapper.text()) //"hhhhh"
});
Share
Improve this question
asked Mar 9, 2022 at 4:11
Red PandaRed Panda
511 silver badge3 bronze badges
4 Answers
Reset to default 2This has been resolved using jest.mock()
.
import { mount } from "@vue/test-utils";
import { createPinia } from "pinia";
import HelloWorld from "@/ponents/HelloWorld.vue";
jest.mock("@/stores/test", () => {
const { defineStore } = require("pinia");
const useTestStore = defineStore("test", { state: () => ({ title: "xxxxx" }) });
return { useTestStore };
});
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: { plugins: [createPinia()] },
});
expect(wrapper.text()).toBe("xxxxx");
});
For sake of saving future me many hours of trouble, there is a non-obvious thing in play here - the event loop. Vue reactivity relies on the event loop running to trigger the cascade of state changes.
When you mount/shallowMount/render a ponent with vue-test-utils, there is no event loop running automatically. You have to trigger it manually for the reactivity to fire, e.g.
await ponent.vm.$nextTick;
If you don't want to mess around with ticks, you have to mock the store state/getters/etc. (which the docs strongly lean toward, without explaining the necessity). Here OP mocked the whole store.
See also: Vue-test-utils: using $nextTick multiple times in a single test
Thanks to Red Panda for this topic. I use "testing-library", and "vue-testing-library" instead of "vue-test-utils" and "jest", but the problem is the same - couldn't change pinia initial data of the store. I finally found a solution for this issue without mocking the function. When you $patch data, you just need to await for it. Somehow it helps. My code looks like this and it totally works:
Popup.test.js
import { render, screen } from '@testing-library/vue'
import { createTestingPinia } from '@pinia/testing'
import { popup } from '@/store1/popup/index'
import Popup from '../../ponents/Popup/index.vue'
describe('Popup ponent', () => {
test('displays popup with group ponent', async () => {
render(Popup, {
global: { plugins: [createTestingPinia()] }
})
const store = popup()
await store.$patch({ popupData: 'new name' })
screen.debug()
})
})
OR you can set initialState using this scheme:
import { render, screen } from '@testing-library/vue'
import { createTestingPinia } from '@pinia/testing'
import { popup } from '@/store1/popup/index'
import Popup from '../../ponents/Popup/index.vue'
test('displays popup with no inner ponent', async () => {
const { getByTestId } = render(Popup, {
global: {
plugins: [
createTestingPinia({
initialState: {
popup: {
popupData: 'new name'
}
}
})
]
}
})
const store = popup()
screen.debug()
})
Where popup in initialState - is the imported pinia store from @/store1/popup
. You can specify any of them there the same way.
Popup.vue
<script>
import { defineAsyncComponent, markRaw } from 'vue'
import { mapState, mapActions } from 'pinia'
import { popup } from '@/store1/popup/index'
export default {
data () {
return {}
},
puted: {
...mapState(popup, ['popupData'])
},
....
I'm working on a project using Vue 3 with position API styling.
Composition API is used for both ponents and defining my store.
Here is my store
player.js
import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
export const usePlayerStore = defineStore('player',()=>{
const isMainBtnGameClicked = ref(false)
return { isMainBtnGameClicked }
})
MyComponent.vue
//import { usePlayerStore } from '...'
const playerStore = usePlayerStore()
playerStore.isMainBtnGameClicked = true
isMainBtnGameClicked from my store is updated properly.
You can also update variables from ponents by passing them by reference to the pinia store. It's working in my project.
Using vue-test-utils to test the ponent using pinia, I need to modify the value of the state stored in pinia, but I have tried many methods to no avail. The original ponent and store files are as follows.
// HelloWorld.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { useTestStore } from "@/stores/test";
import { mapState } from "pinia";
export default {
name: "HelloWorld",
puted: {
...mapState(useTestStore, ["title"]),
},
};
</script>
// @/stores/test.js
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return { title: "hhhhh" };
},
});
The following methods have been tried.
- Import the store used within the ponent to the test code and make changes directly, but the changes cannot affect the ponent.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
import { useTestStore } from "@/stores/test";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
},
});
const store = useTestStore();
store.title = "xxxxx";
console.log(wrapper.text()) //"hhhhh";
});
- Using the initialState in an attempt to overwrite the contents of the original store, but again without any effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia({ initialState: { title: "xxxxx" } })],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Modify the TestingPinia object passed to global.plugins in the test code, but again has no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const pinia = createTestingPinia();
pinia.state.value.title = "xxxxx";
const wrapper = mount(HelloWorld, {
global: {
plugins: [pinia],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Use global.mocks to mock the states used in the ponent, but this only works for the states passed in with setup() in the ponent, while the ones passed in with mapState() have no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
mocks: { title: "xxxxx" },
},
});
console.log(wrapper.text()) //"hhhhh"
});
Using vue-test-utils to test the ponent using pinia, I need to modify the value of the state stored in pinia, but I have tried many methods to no avail. The original ponent and store files are as follows.
// HelloWorld.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { useTestStore } from "@/stores/test";
import { mapState } from "pinia";
export default {
name: "HelloWorld",
puted: {
...mapState(useTestStore, ["title"]),
},
};
</script>
// @/stores/test.js
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return { title: "hhhhh" };
},
});
The following methods have been tried.
- Import the store used within the ponent to the test code and make changes directly, but the changes cannot affect the ponent.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
import { useTestStore } from "@/stores/test";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
},
});
const store = useTestStore();
store.title = "xxxxx";
console.log(wrapper.text()) //"hhhhh";
});
- Using the initialState in an attempt to overwrite the contents of the original store, but again without any effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia({ initialState: { title: "xxxxx" } })],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Modify the TestingPinia object passed to global.plugins in the test code, but again has no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const pinia = createTestingPinia();
pinia.state.value.title = "xxxxx";
const wrapper = mount(HelloWorld, {
global: {
plugins: [pinia],
},
});
console.log(wrapper.text()) //"hhhhh";
});
- Use global.mocks to mock the states used in the ponent, but this only works for the states passed in with setup() in the ponent, while the ones passed in with mapState() have no effect.
// test.spec.js
import { mount } from "@vue/test-utils";
import { createTestingPinia } from "@pinia/testing";
import HelloWorld from "@/ponents/HelloWorld.vue";
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: {
plugins: [createTestingPinia()],
mocks: { title: "xxxxx" },
},
});
console.log(wrapper.text()) //"hhhhh"
});
Share
Improve this question
asked Mar 9, 2022 at 4:11
Red PandaRed Panda
511 silver badge3 bronze badges
4 Answers
Reset to default 2This has been resolved using jest.mock()
.
import { mount } from "@vue/test-utils";
import { createPinia } from "pinia";
import HelloWorld from "@/ponents/HelloWorld.vue";
jest.mock("@/stores/test", () => {
const { defineStore } = require("pinia");
const useTestStore = defineStore("test", { state: () => ({ title: "xxxxx" }) });
return { useTestStore };
});
test("pinia in ponent test", () => {
const wrapper = mount(HelloWorld, {
global: { plugins: [createPinia()] },
});
expect(wrapper.text()).toBe("xxxxx");
});
For sake of saving future me many hours of trouble, there is a non-obvious thing in play here - the event loop. Vue reactivity relies on the event loop running to trigger the cascade of state changes.
When you mount/shallowMount/render a ponent with vue-test-utils, there is no event loop running automatically. You have to trigger it manually for the reactivity to fire, e.g.
await ponent.vm.$nextTick;
If you don't want to mess around with ticks, you have to mock the store state/getters/etc. (which the docs strongly lean toward, without explaining the necessity). Here OP mocked the whole store.
See also: Vue-test-utils: using $nextTick multiple times in a single test
Thanks to Red Panda for this topic. I use "testing-library", and "vue-testing-library" instead of "vue-test-utils" and "jest", but the problem is the same - couldn't change pinia initial data of the store. I finally found a solution for this issue without mocking the function. When you $patch data, you just need to await for it. Somehow it helps. My code looks like this and it totally works:
Popup.test.js
import { render, screen } from '@testing-library/vue'
import { createTestingPinia } from '@pinia/testing'
import { popup } from '@/store1/popup/index'
import Popup from '../../ponents/Popup/index.vue'
describe('Popup ponent', () => {
test('displays popup with group ponent', async () => {
render(Popup, {
global: { plugins: [createTestingPinia()] }
})
const store = popup()
await store.$patch({ popupData: 'new name' })
screen.debug()
})
})
OR you can set initialState using this scheme:
import { render, screen } from '@testing-library/vue'
import { createTestingPinia } from '@pinia/testing'
import { popup } from '@/store1/popup/index'
import Popup from '../../ponents/Popup/index.vue'
test('displays popup with no inner ponent', async () => {
const { getByTestId } = render(Popup, {
global: {
plugins: [
createTestingPinia({
initialState: {
popup: {
popupData: 'new name'
}
}
})
]
}
})
const store = popup()
screen.debug()
})
Where popup in initialState - is the imported pinia store from @/store1/popup
. You can specify any of them there the same way.
Popup.vue
<script>
import { defineAsyncComponent, markRaw } from 'vue'
import { mapState, mapActions } from 'pinia'
import { popup } from '@/store1/popup/index'
export default {
data () {
return {}
},
puted: {
...mapState(popup, ['popupData'])
},
....
I'm working on a project using Vue 3 with position API styling.
Composition API is used for both ponents and defining my store.
Here is my store
player.js
import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
export const usePlayerStore = defineStore('player',()=>{
const isMainBtnGameClicked = ref(false)
return { isMainBtnGameClicked }
})
MyComponent.vue
//import { usePlayerStore } from '...'
const playerStore = usePlayerStore()
playerStore.isMainBtnGameClicked = true
isMainBtnGameClicked from my store is updated properly.
You can also update variables from ponents by passing them by reference to the pinia store. It's working in my project.
本文标签:
版权声明:本文标题:javascript - How can I modify the value of state in pinia in vue3 component test and affect the component? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745611901a2159049.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论