# 五.补充功能(页面测试)
前言
前端测试需要用到工具,以及测试相关工具用法,测试相关场景
监听测试用例运行,每次修改文件会自动重新跑测试用例,不用每次手动跑
yarn run test:unit --watch
1
# 1.unit
测试 props 传值
- Test1.vue
<template>
<h1>{{ msg }}</h1>
</template>
1
2
3
2
3
{
props: {
msg: String;
}
}
1
2
3
4
5
2
3
4
5
test1.spec.js
const msg = "new message";
const wrapper = shallowMount(Test1, {
propsData: { msg },
});
expect(wrapper.text()).to.include(msg);
1
2
3
4
5
2
3
4
5
测试点击事件
Test2.vue
<template>
<span id="count">{{ count }}</span>
<button @click="increment">点击</button>
<template></template>
</template>
1
2
3
4
5
2
3
4
5
{
data() {
return { count: 10};
},
methods: {
increment() {
this.count++;
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
test2.spec.js
let wrapper = shallowMount(Test2);
wrapper.setData({ count: 10 });
expect(wrapper.find("span").text()).to.be.equal("10");
wrapper.find("button").trigger("click");
expect(wrapper.find("span").text()).to.be.equal("11");
1
2
3
4
5
2
3
4
5
测试自定义方法
Test3.vue
<template>
<Child @show="show"></Child>
<p id="content" v-if="flag">{{ name }}</p>
</template>
1
2
3
4
2
3
4
props:{
fn:{}
},
methods:{
clickMe(){
this.fn('123')
this.fn('456')
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
test3.spec.js
let wrapper = shallowMount(Test3);
expect(wrapper.find("#content").exists()).to.be.false;
wrapper.find(Child).vm.$emit("show");
expect(wrapper.find("#content").exists()).to.be.true;
1
2
3
4
2
3
4
测试子组件触发父组件方法
Child.vue
<template>
<button @click="clickMe">click</button>
</tempalte>
1
2
3
2
3
import Child from "./Child.vue";
export default {
data() {
return {name: "javascript", flag: false };
},
methods: {
show() {
this.flag = true;
}
},
components: {
Child
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
child.spec.js
let callback = sinon.spy();
let wrapper = shallowMount(Child, {
propsData: { fn: callback },
});
wrapper.find("button").trigger("click");
expect(callback.getCall(0).args[0]).to.be.equal("123");
expect(callback.getCall(1).args[0]).to.be.equal("456");
expect(callback.callCount).to.be.equal(2);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
测试 axios
Test4.vue
<template>
<span >{{user}}</span>
</tempalte>
1
2
3
2
3
{
data(){
return {user:''}
},
mounted(){
axios.get('/user').then((res)=>{
this.user = res.data.user;
}).catch(err=>{
console.log(err);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
test4.spec.js
beforeEach(() => {
moxios.install();
});
afterEach(() => {
moxios.uninstall();
});
it("测试axios", (done) => {
let wrapper = shallowMount(Test4);
moxios.stubRequest("/user", {
status: 200,
response: { user: "jw" },
});
moxios.wait(() => {
expect(wrapper.text()).to.include("jw");
done();
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
测试 vuex
Store.vue
<template>
<div>
<span>{{ this.$store.state.username }}</span>
<button @click="clickMe">点击</button>
</div>
</template>
<script>
// 测试vuex 从两个方向 测试ui 测试功能
import { mapState, mapActions } from "vuex";
export default {
computed: {
...mapState(["username"]),
},
methods: {
...mapActions(["set_username"]),
clickMe() {
this["set_username"]("jw");
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
store.js
export default {
state: {
username: "zfpx",
},
mutations: {
set_username(state, username) {
state.username = username;
},
},
actions: {
set_username({ commit }, username) {
commit("set_username", username);
},
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import config from "./store";
import Vuex from "vuex";
Vue.use(Vuex);
let store = new Vuex.Store(config);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
store.spec.js
import { shallowMount, createLocalVue } from "@vue/test-utils";
import Vuex from "vuex";
import Store from "@/components/Store.vue";
let localVue = createLocalVue();
localVue.use(Vuex); //防止用例之间的污染
let state;
let store;
let actions;
let callback = jest.fn();
describe("测试vuex 能否在页面中使用", () => {
state = { username: "jw" };
actions = {
set_username: callback,
};
beforeEach(() => {
state = { username: "jw" };
store = new Vuex.Store({
state,
actions,
});
});
it("state能否正常显示到页面中", () => {
let wrapper = shallowMount(Store, {
localVue,
store,
});
expect(wrapper.text()).toContain("jw");
});
it("点击按钮时action能否正常触发", () => {
let wrapper = shallowMount(Store, {
localVue, //提供测试的构造函数vue
store,
});
wrapper.find("button").trigger("click");
expect(callback).toHaveBeenCalled();
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
将 store 中的部分内容放到 main.js 中可以改造得更简洁
import { createLocalVue } from "@vue/test-utils";
import Vuex from "vuex";
import config from "@/store";
let localVue = createLocalVue();
localVue.use(Vuex); //防止用例之间的污染
describe("测试vuex 能否在页面中使用", () => {
let store;
beforeEach(() => {
store = new Vuex.Store(config);
});
it("state能否正常显示到页面中", () => {
expect(store.state.username).toBe("zfpx");
jest.useFakeTimers(); //创建一个模拟的定时器,会把异步代码立刻返回
store.dispatch("set_username", "newName");
jest.runAllTimers(); //把timer执行
expect(store.state.username).toBe("newName");
jest.useRealTimers();
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2.e2e
# 3.场景问题
- 全屏场景
- 边界场景
- 浏览器窗口变化
- 页面缩放