<template>
<h1>This is Component #1</h1>
</template>
<script>
export default {
name: "Component1",
created() {
console.log(`${this.options.name} has been created!`);
},
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
<template>
<h1>This is Component #2</h1>
</template>
<script>
export default {
name: "Component2",
created() {
console.log(`${this.options.name} has been created!`);
},
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
const createdMixin = {
created() {
console.log(`${this.options.name} has been created!`);
}
};
<template>
...
</template>
<script>
export default {
name: "ComponentName",
mixins: [nameOfMixin]
};
</script>
<template>
<h1>This is Component #1</h1>
</template>
<script>
import {createdMixin} from './mixins';
export default {
name: "Component1",
mixins: [createdMixin]
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
<template>
<h1>This is Component #2</h1>
</template>
<script>
import {createdMixin} from './mixins';
export default {
name: "Component2",
mixins: [createdMixin]
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
export const helloWorldMixin = {
data() {
return {
reversedGreeting: '!dlrow olleH',
}
},
computed: {
getGreeting() {
return this.reversedGreeting.split("").reverse().join("");
}
}
}
export const createdMixin = {
created() {
console.log(`${this.options.name} has been created!`);
}
}
mixins.js
<template>
<h1>This is Component #1</h1>
<p>{{getGreeting}}</p>
</template>
<script>
import {helloWorldMixin, createdMixin} from './mixins';
export default {
name: "Component1",
mixins: [helloWorldMixin, createdMixin]
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
<template>
<h1>This is Component #2</h1>
<p>{{getGreeting}}</p>
</template>
<script>
import {helloWorldMixin, createdMixin} from './mixins';
export default {
name: "Component2",
mixins: [helloWorldMixin, createdMixin]
...
};
</script>
<style lang="css">
<!-- Styles-->
</style>
Component1.vue
Component2.vue
const greetingMixin = {
data() {
return {
greeting: 'Hello World!',
}
}
}
Vue.component('greeting-component', {
mixins: [greetingMixin],
data() {
return {
greeting: 'Good Morning!',
}
},
created() {
console.log(this.greeting); // 'Good Morning!'
}
});
const greetingMixin = {
methods: {
greetingMethod() {
console.log('Hello World!');
}
},
components: {
'greeting-component': ComponentA
}
}
Vue.component('greeting-component', {
mixins: [greetingMixin],
methods: {
greetingMethod() {
console.log('Good Morning!');
}
},
components: {
'greeting-component': ComponentB
}
});
const greetingMixin = {
created() {
console.log('Hello World!');
}
}
Vue.component('greeting-component', {
mixins: [greetingMixin],
created() {
console.log('Good Morning!');
}
});
// 'Hello World!'
// 'Good Morning!'
Vue.mixin({ });
{{ property | nameOfFilter }}
v-bind:src="property | nameOfFilter"
<template>
...
</template>
<script>
export default {
name: "ComponentName",
filters: {
nameOfFilter(value) {
return ...
}
}
};
</script>
filters: {
nameOfFilter(value) {
return ...
}
}
<template>
<div>
{{ greeting }}
{{ greeting | reverseString }}
</div>
</template>
<script>
export default {
name: "GreetingComponent",
data() {
return {
greeting: 'Hello World!';
}
},
filters: {
reverseString(originalValue) {
return originalValue.split("").reverse().join("");
},
}
};
</script>
<style lang="css">
<!-- Styles-->
</style>
{{ property | nameOfFilter(arg1, arg2) }}
filters: {
nameOfFilter(value, arg1, arg2) {
return ...
}
}
{{ property | filter1 | filter 2 | filter 3 }}
Vue.filter('name-of-filter', function() {});
new Calculator()
describe('Calculator', () => { it('sums 2 and 2 to 4', () => {
...
});
it('subtracts 5 and 3 to 2', () => {
... }); });
describe('Calculator', () => { describe('sum()', () => { it('sums 2 and 2 to 4', () => {
... }); });
describe('subtract()', () => {
it('subtracts 5 and 3 to 2', () => {
... }); }); });
describe('Calculator', () => { it('sums 2 and 2 to 4', () => {
const calc = new Calculator();
expect(calc.sum(2,2)).toEqual(4);
});
it('subtracts 5 and 3 to 2', () => {
const calc = new Calculator(); expect(calc.subtract(5,3)).toEqual(2); }); });
expect(...).toEqual(...);
describe('Calculator', () => { it('sums 2 and 2 to 4', () => {
const calc = new Calculator(); const sumResult = calc.sum(2,2); expect(sumResult).toEqual(4); });
});
<template>
<div id="app">
<section class="todoapp">
<header class="header">
<h1 class="title">todos</h1>
<input class="new-todo"
placeholder="What needs to be done?"
v-model="newTodo"
@keyup.enter="addTodo">
</header>
<section class="main">
<ul class="todo-list">
<li class="todo"
v-for="(todo, index) in todos"
:key="index">
<div class="view">
<label>{{ todo }}</label>
<button class="destroy" @click="removeTodo(todo)"></button>
</div>
</li>
</ul>
</section>
</section>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
todos: [],
newTodo: ''
}
},
methods: {
addTodo() {
if (this.newTodo !== '') {
this.todos.push(this.newTodo);
this.newTodo = '';
}
},
removeTodo(todo) {
this.todos.splice(this.todos.indexOf(todo), 1);
}
}
};
</script>
App.vue
describe('App.vue', () => {
it('should render correct initial content', () => {
...
});
});
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
// ...
});
});
App.spec.js
import Vue from "vue";
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
const Constructor = Vue.extend(App);
});
});
App.spec.js
import Vue from "vue";
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
const Constructor = Vue.extend(App);
const vm = new Constructor().$mount();
});
});
App.spec.js
import Vue from "vue";
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
const Constructor = Vue.extend(App);
const vm = new Constructor().$mount();
expect(vm.$el.querySelector(".title").textContent).toBe("todos");
expect(vm.$el.querySelector(".new-todo").placeholder).toBe(
"What needs to be done?"
);
});
});
App.spec.js
describe('App.vue', () => { it('should render correct initial content', () => {
...
});
it('should set correct default data', () => {
...
});
});
import Vue from "vue";
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
// ...
});
it("should set correct default data", () => {
const initialData = App.data();
});
});
App.spec.js
import Vue from "vue";
import App from "./App";
describe("App", () => {
it("should render correct initial content", () => {
// ...
});
it("should set correct default data", () => {
const initialData = App.data();
expect(initialData.todos).toEqual([]);
expect(initialData.newTodo).toEqual("");
});
});
App.spec.js
const wrapper = mount(Component);
import { mount } from "@vue/test-utils";
const vm = wrapper.vm;
const html = wrapper.html();
const button = wrapper.find('button');
const propValue = wrapper.props('propKey');
wrapper.trigger('click');
wrapper.setMethods({});
mount()
shallowMount()
import { mount, shallowMount } from "@vue/test-utils";
import { mount } from "@vue/test-utils";
shallowMount()
import Vue from "vue";
import App from "./App";
describe("App.vue", () => {
it("should render correct initial content", () => {
const Constructor = Vue.extend(App);
const vm = new Constructor().$mount();
expect(vm.$el.querySelector(".title").textContent).toBe("todos");
expect(vm.$el.querySelector(".new-todo").placeholder).toBe(
"What needs to be done?"
);
});
it("should set correct default data", () => {
const initialData = App.data();
expect(initialData.todos).toEqual([]);
expect(initialData.newTodo).toEqual("");
});
});
App.spec.js
npm install @vue/test-utils --save-dev
import App from "./App";
import { shallowMount } from "@vue/test-utils";
describe("App.vue", () => {
it("should render correct initial content", () => {
...
});
it("should set correct default data", () => {
...
});
});
App.spec.js
import App from "./App";
import { shallowMount } from "@vue/test-utils";
describe("App.vue", () => {
let wrapper = shallowMount(App);
it("should render correct initial content", () => {
...
});
it("should set correct default data", () => {
...
});
});
App.spec.js
import App from "./App";
import { shallowMount } from "@vue/test-utils";
describe("App.vue", () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(App);
});
it("should render correct initial content", () => {
...
});
it("should set correct default data", () => {
...
});
});
import App from "./App";
import { shallowMount } from "@vue/test-utils";
describe("App.vue", () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(App);
});
it("should render correct initial content", () => {
expect(wrapper.find(".title").text()).toBe("todos");
expect(wrapper.find(".new-todo").element.placeholder).toBe(
"What needs to be done?"
);
});
it("should set correct default data", () => {
...
});
});
App.spec.js
import App from "./App";
import { shallowMount } from "@vue/test-utils";
describe("App.vue", () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(App);
});
it("should render correct initial content", () => {
expect(wrapper.find(".title").text()).toBe("todos");
expect(wrapper.find(".new-todo").element.placeholder).toBe(
"What needs to be done?"
);
});
it("should set correct default data", () => {
expect(wrapper.vm.todos).toEqual([]);
expect(wrapper.vm.newTodo).toEqual("");
});
});
App.spec.js
describe("App.vue", () => {
it("should render correct initial content", () => {
...
});
it("should set correct default data", () => {
...
});
describe("the user populates the text input field", () => {
...
});
});
describe("App.vue", () => {
...
describe("the user populates the text input field", () => {
it("should update the 'newTodo' data property", () => {
...
});
});
});
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
it("should update the 'newTodo' data property", () => {
const inputField = wrapper.find(".new-todo");
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
it("should update the 'newTodo' data property", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
it("should update the 'newTodo' data property", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
expect(wrapper.vm.newTodo).toEqual("New Todo");
});
});
});
App.spec.js
describe("App.vue", () => {
...
describe("the user populates the text input field and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
...
});
});
});
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
const inputField = wrapper.find(".new-todo");
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
inputField.trigger("keyup.enter");
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
inputField.trigger("keyup.enter");
expect(wrapper.vm.todos).toEqual(["New Todo"]);
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
it("should update the 'newTodo' data property", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
expect(wrapper.vm.newTodo).toEqual("New Todo");
});
});
describe("the user populates the text input field and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
const inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
inputField.trigger("keyup.enter");
expect(wrapper.vm.todos).toEqual(["New Todo"]);
});
});
});
App.spec.js
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
let inputField;
beforeEach(() => {
inputField = wrapper.find(".new-todo");
inputField.element.value = "New Todo";
inputField.trigger("input");
});
it("should update the 'newTodo' data property", () => {
expect(wrapper.vm.newTodo).toEqual("New Todo");
});
describe("and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
inputField.trigger("keyup.enter");
expect(wrapper.vm.todos).toEqual(["New Todo"]);
});
});
});
});
App.spec.js
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0
}).format(number);
new Intl.NumberFormat().format(number);
<template>
<div id="app">
<section class="todoapp">
...
<li class="todo"
v-for="(todo, key) in todos"
:key="key">
<div class="view">
<label>{{ todo }}</label>
<button class="destroy" @click="removeTodo(todo)"></button>
</div>
</li>
...
</section>
<footer class="footer">
<button @click="removeAllTodos" class="clear-completed">
Remove all
</button>
</footer>
</div>
</template>
<script>
export default {
...
methods: {
...,
removeTodo(todo) {
this.todos.splice(this.todos.indexOf(todo), 1);
},
removeAllTodos() {
this.todos = [];
}
}
};
</script>
App.vue
import App from "./App";
describe("App", () => {
// ...
describe("the user populates the text input field", () => {
// ...
it("should update the 'newTodo' data property", () => {
// ...
});
describe("and presses Enter", () => {
it("should add a new todo to the 'todos' array", () => {
// ...
});
});
describe("and presses Enter and then removes the todo item", () => {
it("should have the new todo removed from the 'todos' array", () => {
// Trigger keyup.enter on inputField to submit todo
// Then find the Remove icon and trigger a click
});
});
});
describe("the user clicks the 'Remove all' label", () => {
it("should remove all todos from the 'todos' data property", () => {
// Quickly update the todos array with wrapper.setData({})
// Find the Remove all button and trigger a click
});
});
});
App.spec.js
Solution 👀