You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+107
Original file line number
Diff line number
Diff line change
@@ -34,6 +34,9 @@ Topics already covered:
34
34
*[Mocking store for a smart component](#mocking-store-for-a-smart-component)
35
35
*[Mocking store for router](#mocking-store-for-router)
36
36
*[Mocking actions, mutations and getters](#mocking-actions-mutations-and-getters)
37
+
*[Setting up initial state in tests](#setting-up-initial-state-in-tests)
38
+
+[Using existing mutations to change initial state](#using-existing-mutations-to-change-initial-state)
39
+
+[Modifying the state directly](#modifying-the-state-directly)
37
40
-[Testing v-model](#testing-v-model)
38
41
-[Using flush-promises vs Vue.nextTick()](#using-flush-promises-vs-vuenexttick)
39
42
@@ -1313,6 +1316,110 @@ beforeEach(function () {
1313
1316
```
1314
1317
You can see full implementation (including restoring mock back to original functionality) in [test/unit/utils/store.js](./test/unit/utils/store.js) file.
1315
1318
1319
+
## Setting up initial state in tests
1320
+
Let's say we need our store to start with different initial state than is specified in application's code. E.g. a store which holds information about what is the type of current user:
1321
+
```js
1322
+
// store.js
1323
+
exportdefault {
1324
+
state: {
1325
+
isVip:false
1326
+
}
1327
+
}
1328
+
```
1329
+
The problems starts when we want to test a component which uses the flag from store to determine what should be displayed:
<!-- SIDE NOTE: check out https://vuejs.org/v2/style-guide/#v-if-v-if-else-v-else-without-key-use-with-caution to understand why both h1 tags have the key property assigned -->
1337
+
</template>
1338
+
```
1339
+
```js
1340
+
classMyComponentextendsVue {
1341
+
getisVip() {
1342
+
returnthis.$store.state.isVip; // or map it using mapState or @State decorator
1343
+
}
1344
+
}
1345
+
```
1346
+
In test, we need to change the initial state before each test. We have two options how to do that:
1347
+
### Using existing mutations to change initial state
1348
+
```js
1349
+
describe('when user is VIP', function () {
1350
+
beforeEach(function () {
1351
+
this.store=createStore();
1352
+
this.store.commit('setVip', true); // setVip mutation must exist
1353
+
});
1354
+
1355
+
it('should display warning welcome message');
1356
+
});
1357
+
1358
+
describe('when user is non-VIP', function () {
1359
+
beforeEach(function () {
1360
+
this.store=createStore();
1361
+
this.store.commit('setVip', false); // setVip mutation must exist
1362
+
});
1363
+
1364
+
it('should display generic welcome message');
1365
+
});
1366
+
```
1367
+
### Modifying the state directly
1368
+
```js
1369
+
describe('when user is VIP', function () {
1370
+
beforeEach(function () {
1371
+
this.store=createStore();
1372
+
this.store.state.isVip=true; // no mutation required
1373
+
});
1374
+
1375
+
it('should display warning welcome message');
1376
+
});
1377
+
1378
+
describe('when user is non-VIP', function () {
1379
+
beforeEach(function () {
1380
+
this.store=createStore();
1381
+
this.store.state.isVip=false; // no mutation required
1382
+
});
1383
+
1384
+
it('should display generic welcome message');
1385
+
});
1386
+
```
1387
+
There is no winner in this competition, both approaches does the work, it's up to you which one do you prefer. Few notes to consider:
1388
+
1389
+
The first approach uses existing functionality, that means if the logic in mutation changes, then you have to update the tests. It also might seem a little less readable.
1390
+
1391
+
The second approach doesn't require mutation to be defined (might be useful when an application doesn't need it, don't write a mutation only for using it in tests). Setting properties of the state works well only if you are setting primitive values. The `state` object is [reactive](https://vuejs.org/v2/guide/reactivity.html), that means if you reassign array or object in the `state`, you will disconnect the state and your component under the test:
1392
+
```js
1393
+
// !warning: this is wrong!
1394
+
describe('when user has profile loaded', function () {
it('should display full name in the welcome message', function () {
1406
+
expect(this.myComponent.find('h1').text()).to.equal('Welcome John Doe'); // fail
1407
+
});
1408
+
});
1409
+
// !warning: this is wrong!
1410
+
```
1411
+
If you try to use `firstName` or `lastName` in the template, you will only get undefined values, because these values were not reactified by the Vue. Vue cannot detect new or deleted properties, see [caveats of reactivity](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats). However you can use `Vue.set()` to fix the problem:
1412
+
```js
1413
+
beforeEach(function () {
1414
+
Vue.set(this.store.state, 'profile', {
1415
+
firstName:'John',
1416
+
lastName:'Doe',
1417
+
username:'john.doe'
1418
+
});
1419
+
});
1420
+
```
1421
+
And everything works fine again.
1422
+
1316
1423
# Testing v-model
1317
1424
Let's test a custom component with v-model support, e.g. like this one
0 commit comments