Unit testing and simulating input



  • I am using vue-test-utils.
    I have a form with a q-input of type textarea:

    https://github.com/maxant/kafka-data-consistency/blob/master/ui/claims.js#L83

                           <q-input
                                id="claims-form-description"
                                class="col-8"
                                v-model="form.description"
                                type="textarea"
                                float-label="Description"
                                rows="4"
                                @blur="blurDescription"
                                :error="$v.form.description.$error"
                            />
    

    I want to make my unit test enter data, if possible. I guess I could just set the value into the model.
    Then I want to simulate a blur, so that the “blurDescription” function is called:

    methods: {
        blurDescription() {
            this.$v.form.description.$touch()
        },
    

    I should then be able to check that $v is updated, so that I can test that the validation works. But I cannot get the blur to work. I’ve tried the following:

    wrapper.find("#claims-form-description.q-input-area").trigger("blur")
    wrapper.find("#claims-form-description").trigger("blur")
    

    Neither causes my blur method to be called. What is the correct way to do this?

    Also, are there any utility functions provided by quasar which hide quasar internal stuff, so that I can e.g. programatically click on buttons or enter text into inputs?



  • Hi - are you using v1? and if so are you using the @quasar/testing app-extension?



  • nope, version 2 @nothingismagick



  • Version 2 isn’t out yet - so I guess you are from the future. With v1 I meant @quasar/cli v1.0.0-beta



  • haha @nothingismagick 🙂

    I guess I meant 0.17.8

    Not using cli.
    I had a quick look at this yesterday: https://github.com/quasarframework/quasar-testing
    But couldn’t see anything that would help me enter text into a q-input or bluring it. Basically I don’t want to have to know that a q-unit contains divs and text areas and stuff like that. I just want to find my element by ID, and be able to call methods on that object like “click()”, “setValue(…)”, “blur()”, etc. Is that possible or on a roadmap?



  • @nothingismagick I noticed that I can use the “ref” attribute and then access that ref like this:

    wrapper.find("#claims-form-description").vnode.componentInstance.$refs
    

    And that ref has some interesting stuff on it, e.g. an input (I’m testing with a q-input), and that in turn has a “click” and “blur” method:

    wrapper.find("#claims-form-description").vnode.componentInstance.$refs.input.click()
    

    Or perhaps even better:

    wrapper.vm.$refs.other.blur()
    

    But they don’t seem to do anything. Should they do something? Is there any docs about this stuff?



  • I’ve made progress.
    I had a number of problems:

    • using lazy-rules, which requires focus and blur to be programatically executed, which in turn doesnt work when the debug window is open
    • setting a value in the data is not enough to get validation to be executed, you need to use a setTimeout(f, 0)
    • vue-test-utils wrapper has a method called “setValue” - that doesnt work with q-input 😞

    I’ve got a working example. I’ll tidy it up and post it here tomorrow.



  • A further problem was that jsdelivr.net only has vue-test-utils version 1.0.0-beta.11, which has a date of 11th Jan 2018?!?!

    NPM is already at version 1.0.0-beta.29. So I switched to unpkg.com:

    <script src="https://unpkg.com/@vue/test-utils@1.0.0-beta.29/dist/vue-test-utils.umd.js"></script>
    

    Now the wrapper which I get when I select the q-input finally has a setValue function, and things are working MUCH better.

    I still have to mess around with focusing the element, but that makes sense, because I’m using lazy rules. wrapper.find(...).trigger("focus") doesn’t seem to work on a q-input but I can use native Javascript which works find. Maybe because I appended the wrapper.element to a div in my browser while running the tests. Note: I’m not following the docs here, and I’m running the tests in the browser using QUnit so that I can interact with the widgets if I need to, if a test isn’t working the way I expect it to.

    The focus and blur process required in the test is complicated but lazy-rules just works that way, so I have no other choice:

    • rules are not validated until the field is focused
    • rules are not validated the first time until the field loses focus
    • rules are continuously validated after returning to the field

    In order to get the validation to fire after blurring the first time I had to do a “nextTick”, i.e. await on a setTimeout(..., 0). I guess quasar/vue are waiting for some messages in the queue to be processed by the event loop. See the link to my example code below for more details.

    Once you understand that and program the test to expect that behaviour, the test works quite well.

    An example is here:

    https://github.com/maxant/kafka-data-consistency/blob/14f62badf13188ed153ae38de00aa9dc2042f27c/ui/claims.spec.js

    If you check that project out and serve https://github.com/maxant/kafka-data-consistency/blob/14f62badf13188ed153ae38de00aa9dc2042f27c/ui/tests.html using a simple web server like nodes http-server, you can see all the tests running in the browser, and you can see the components 🙂

    So, summary:

    • wrapper.setValue(...) from vue-test-utils works fine with a q-input.
    • same for q-btns
    • if you use lazy-rules then expect to have to focus and blur the q-input
    • wrapper.find(...).trigger("blur") or “focus” doesnt work => instead use native calls
    • that might only work if the component is appended and actually visible in the browser… not sure
    • my original question was whether quasar provided any utility functions to help test widgets, but I don’t currently believe any extra stuff is required - vue-test-utils suffices

    Thanks for the help!
    Ant