Ardor JS & Vue
VueJS in our Ardor SPA
In the
pages
folder you can find the top level components, the ones that are directly called by router-links
. The rest of the components are found under the components
folder and namespaced according to the object they refer to. Global functions and bits of code are found under the mixins
folder, even though they are not always proper Vue mixins. The I18n is in the locale
folder. The store is also namespaced according to objects. Each object has a
constant.js
file containing the constants, an index.js
files containing all actions, getters, and mutation, and a service.js
file containing the api methods and routes for the object. Some of them also have an initialState.js
when necessary. We order component options following the guidelines of the Vue style guide: https://vuejs.org/v2/style-guide/#Component-instance-options-order-recommended
We order element attributes following the guidelines of the Vue style guide: https://vuejs.org/v2/style-guide/#Element-attribute-order-recommended. We place all HTML tags under part 8. Other attributes. Inside these we put the props first. We differentiate bound attributes (with v-on or the ':' shorthand) which come first from the ones that are not bound. So the general order should look like this:
- All Vue attributes from points 1 to 7 from the Vue style guide
- Props
- Unspecified bound attributes
- Unspecified unbound attributes
- Vue event attributes (v-on, shorthand @)
- Vue content attributes (v-text, v-html)
el-button(
v-if="showButton"
id="offerCardSubmissionButton"
:loading="offersLoading"
:class="flavor"
:disabled="buttonDisabled"
role="button"
@click="loadOffers"
)
We order imports as follow and by alphabetical order:
- Components imports
- Mixins imports
- Vuex import (mapActions, mapGetters, mapState, etc...)
- Other imports
import DocumentUpload from '@/components/inputs/DocumentUpload'
import InsurerSelect from '@/components/inputs/InsurerSelect'
import { handlers } from '@/mixins/handlers'
import { required } from '@/mixins/validationRules'
import { mapActions, mapState, } from 'vuex'
We name boolean attributes that will determine whether or not a modal is visible like this:
<function>ModalVisible
in components with one modal where the object can be inferred from context.<function><Object>ModalVisible
when there is more than one modal in the component or if the object is different from the one the component refers tovisible
when the component itself is nothing but one modal
We rename the imported attributes and functions in mapState and mapActions if they are not directly related to the object the component refers to like this:
<object><Attribute>
for an attribute<function><Object>
for a function
We try to reuse components as much as possible and therefore extract a form field into a separate component whenever it is used more than once. We use the element ui native validator rules to validate our forms.
We use the vue plugin of eslint set at the 'recommended' level to lint our code. To lint automatically just run
npm run lint
. Install the atom package and activate lint on save in the setting to automatically lint the file at every save.

We test our Vue apps according to the front-end testing pyramid, except for the snapshot testing (checking that UI doesn't change unexpectedly) which we don't do here. For unit testing, we need to test the store (getters, mutations and actions) as well as the components. We only test the store parts and components that contain some kind of logic.
For the store testing, we check if the state is being correctly updated (for mutations), if the returned value is correct (for getters), or if a mutation or another action is being called with the right arguments (for actions).
For the components testing, it is best practice not to focus testing on line-based coverage but rather on the public interface. This means we provide the component with some input (user action, props, store) and check the output (rendered output, events, function calls), treating the internal logic as a black box. The benefit of working this way is that tests don't have to be updated every time we change a component, as long as the output stays the same. To provide input and check the output, we fake a store, giving the component only the state attributes, getters and actions that it needs.
For unit testing, we use Vue-test-utils and Jest, as Jest is a very complete library that includes a test runner, an assertion library, mocking, snapshot testing etc. To run the unit tests, run
jest test/unit/*
, Jest will pick up all the files that end with .spec.js
.For end-to-end testing we use Cypress, which comes with an integrated assertion library and also gives us the possibility to watch our tests live in the browser, which is very useful for debugging and writing tests. To run the tests in the browser, run
node_modules/.bin/cypress open
. To run the tests in the terminal, type cypress run --spec testfile
. The objective is to test the main integrations between components and store, as we are already testing the correct functioning of both of these apart. To do this, we start by visiting the the desired url and then do the required actions, which is very easy using Cypress's API commands. We then check if the state has been updated accordingly.
To fake an API back-end, it is worth having a look at json-server which is easy to implement and very powerful.
When we're working with
element-ui
, we can't use the built-in select()
andsetSelected()
that Cypress and Vue-test-utils provide because the el-select
element doesn't include an HTML select,
which means we have to select an option by index. It is currently not possible to stub an API call dynamically in function of the body you're sending the API endpoint. Cypress is working on implementing this among other things: https://github.com/cypress-io/cypress/issues/687.
Javascript testing 2018
Unit testing store
Components testing
E2E testing
- Testing Vue app with Cypress: https://www.cypress.io/blog/2017/11/28/testing-vue-web-application-with-vuex-data-store-and-rest-backend/#
- Network request (stubbing etc.): https://docs.cypress.io/guides/guides/network-requests.html#Testing-Strategies
General
Last modified 4yr ago