clock menu more-arrow no yes mobile

Filed under:

Prototypes for usability testing with VueJS

A block of implied code beside a mocked design artboard featuring a set of empty form inputs with a mouse pointer hovering over one of the inputs Ramla Mahmood

At Vox Product, we’re always building new features into Chorus, our suite of media publishing tools. Many of these begin as requests from our users. We’ll research proposals that seem to have merit, design some mock-ups to understand their strengths and weaknesses, and finally build and release the finished features as improvements to our Chorus applications.

During this process, we usually engage in usability testing by presenting static mocks to our users. While this is helpful, the static imagery leaves a lot of ambiguity. This prompted us to develop a more robust process for usability testing with new designs. In this post we’ll share how we’ve tested with static mocks, and how we’re now using VueJS to take our testing to the next level.

How our teams process new features

During the new feature cycle, we’ll use different methods to determine what a feature needs at different stages of its development. In the early days, we’ll document in writing what we want that feature to do. Then, we’ll create a static design to establish what we want the feature’s interface to look like. After that, engineers will turn that static design into real, working code, and integrate it into our systems.

This gradual process helps ensure that we’re creating a meaningful solution; at each stage, we can go through multiple cycles of feedback and review, and iterate on our work until it’s ready.

When that process is challenging

There’s a tricky balance to be had in the middle of this new-feature process. Static designs are exciting to see, but they’re not interactive. More importantly, those designs are limited in what they convey during usability testing, since a person can’t fully navigate through a static design. Without being able to click or tap through a fully realized experience, users can’t predict what errors they might trigger, or alternate pathways or experiences they might prefer.

If we want to give our users something more interactive to test, you’d think it’d make sense to just build it. But the engineering process has its own overhead: the work needs to be tested, reviewed, and revised, and Quality Assurance (QA) and Visual QA (VQA) testing exposes unanticipated edge cases and visual/accessibility bugs, too.

What if we could start prototyping much earlier?

Imagine that a front-end engineer was involved from the beginning, creating a usable, navigable prototype of the user experience while the designer is iterating on their static design.

For the Chorus Video team, we’ve found this approach to be incredibly effective. We’d like to tell you how we built something we call a “prototype scaffold” to support these functional prototypes.

How our prototype scaffold is built with VueJS

The Chorus Video application’s front-end is built with the VueJS framework. It uses vue-router to manage what components display at any given URL path. For the purpose of developing functional prototypes that designers, users, and stakeholders can experience for themselves, we must make these features available—with limited scope—in the production environment.

Scary thought: this means that the prototypes (or “components-under-construction”) need to be merged to master and deployed to production while still incomplete.

To get comfortable with that idea and build something useful, we had to answer a few important questions.

1. As we deploy, how do we keep track of all of the prototypes and the conditionals that pop up as we iterate? And how do we prevent a mess of tech debt throughout our application?

First, we created a component directory in our file structure called “prototypes.” This ensures that such components stay separate in our codebase from the components that are not prototypes.

a directory structure featuring a top-level directory named “components” with a sub-directory named “prototypes”. The “prototypes” directory is highlighted and is displaying its’ content: a file named “prototype-wrapper.vue”

Within this directory is the prototype-wrapper.vue component. This file is the anchor of the scaffold, and will need to remain here for all future prototype work. The file looks like this:

All prototyped components will need to be registered to this wrapper.

2. How do we ensure that prototyped components are only accessed by the users who should see them?

Prototyped features will be accessed through a URL parameter: ?test= where the value will be the prototyped component’s registry name.

For example, let’s say we want to setup a prototype of a new feature: an “export button”.

a directory structure featuring a top-level directory named “components” with a sub-directory named “prototypes”. The “prototypes” directory is displaying its’ content, 2 files. The first file is highlighted and is named “export-button.vue”.

When this component is created, it is created as components/prototypes/export-button.vue and will be registered in the prototype-wrapper.vue with a component name of ExportButton. The prototype-wrapper.vue file then looks like this:

From this we can insert the prototype-wrapper component itself wherever the Export button prototype is meant to display.

Here, inside of a non-prototyped component projects.vue, we are explicitly stating that there’s a component registered that is indeed a prototype. This is an important reference from the standpoint of the developer experience as this work gets into production—all engineers who encounter this code need to know that this component is under construction.

We also need to be explicit about the circumstances that allow this prototype to be visible. Look closely at the prototype-wrapper component insertion:

the testName prop is pulling the value of the ?test= URL parameter (by seeking this.$route.query.test), but this will only display if the ?test= parameter is ExportButton (v-if=”this.$route.query.test === ‘ExportButton’”). Which is to say, if a User accesses the given page via a URL without the valid ?test=ExportButton parameter, the prototype will not load.

3. When more than one feature is being iterated-on simultaneously (more than one prototype), how do we allow them to exist at the same time?

In the previous example we assumed a single export-button.vue component would be visible at the appropriate URL with the ?test=ExportButton parameter. If we add another prototyped feature for testing, we follow the same procedure. For example, if we wanted to also test a component named “Bulk Publish,” we would add the prototype component to the “prototypes” directory:

a directory structure featuring a top-level directory named “components” with a sub-directory named “prototypes”. The “prototypes” directory is displaying its’ content, 3 files. The first file is highlighted and is named “bulk-publish.vue”.

Then register the bulk-publish.vue component inside the prototype wrapper (alongside the Export Button):

Register the prototype-wrapper.vue component to the page view where you’d want the Bulk Publish feature prototype to display, while explicitly naming the test parameter BulkPublish:

Now both prototypes exist in the application’s code and are obviously prototypes. Passing the prototyped component’s registry name to the prototype-wrapper as the testName prop tells the application which prototype should mount in the given instance. With this setup, both prototyped components can exist at their expected URLs when their respective test parameters are in place.

4. How can we ensure that a functional prototype does not update any production data?

When we build prototypes specifically for testing and iteration within the “prototypes” directory, we follow a standard operating procedure. We also expect that a prototyped component will not run any functions that update data. Any functions within a prototyped component that suggest they will “Update,” “Save,” “Submit,” or “Send” some data need to be built purposely benign.

Graduation

Once design and usability testing is complete, we expect a prototyped component to graduate, becoming fully functional and integrated into our application. When we reach this phase, the prototyped component is moved out of the “prototypes” directory and integrated directly into the rest of the application as part of its’ development (and if a prototyped feature is canceled, the component can easily be deleted).

Using this prototype scaffold, we can safely build and deploy prototyped versions of features directly into our application, making it quick and easy to perform usability tests and collect feedback. These functional prototypes allow us to bridge the gap between static designs and complete features, resulting in a better workflow for our internal team and better experiences for our users.