Apollo refetchQueries unit test with vue testing library - vue.js

I am new to graphql and apollo. I have a useMutation query which on completion perform a refetchQueries operation of 2 other queries. How to write a unit for refetchQueries specific, so that if I remove the refetchQueries code my test should fail.
I am using vitest, vite, vue3, apollo, graphql, vue-testing-library and msw for mocking.
Note: The queries which I want to perform in refetchQueries will reflect data change in some other component and will not be visible in the current component, so the assertion which I am looking something like this:
expect(getQuery1).toHaveBeenCalled()
Is it possible to perform this assertion?

Related

How to test Vue "Services" mounted to root, accessed via Vue.prototype

First, I'd like to explain that I have a Vue component repository that is responsible for displaying data retrieved from an http service. Rather than the component itself managing the same data retrieval per instance and spamming the client with network requests, I've managed to find a solution which allows another component to be mounted to the root directly (which I've dubbed as a "Service" due to its similarity to Angular) to manage the data those components need instead. This works great and other components can access it via Vue.prototype (via this.$TestService.value). It has some caveats but for the most part it accomplishes exactly what I needed. This may be uncommon, but those that use Vuex are using a similar methodology and I don't want to use the store paradigm.
I've made a very simple Vue JsFiddle to show this in action...
https://jsfiddle.net/spronkets/8v31tcfd/18
Now, to the point... I'm using #testing-library/vue, #vue/test-utils, and Jest to test the components and get test coverage and now I get errors anytime I run the tests due to the service not existing on the Vue.prototype during the test execution. I don't want to mock out the functionality of the "Service" layer, so does anyone have a solution to test these root-mounted components? I've tried manually exporting the services (unmounted and mounted) and including them in the mock section as well as importing the files directly into the test files but the "Service" is always undefined when the component is trying to retrieve the value and ONLY during test execution...
I've also created a simple repository modelled after the Vue component repository I am working with below...
https://github.com/kcrossman/VueServiceExample
To get started, clone the repo and follow the README.md included in the repo. Thanks!
I would go against using the real service if it is asyncronous, but if you just want to register it to be available you can follow the mock instructions but instead of mocking with an object just import the real service. Although after seeing your TestService implementation you will need to separate the real service from the service registration and export it to be able to register it in local vue.
You need to create and prepare your custom Vue instance in your tests in order to use any custom functionalities in your unit tests (like stores, routers, and anything else). (You can use your real modules with the custom instance, don't have to mock anything.)
In your case you should create a new Vue instance with "createLocalVue" function from '#vue/test-utils' and apply your custom prototype functionalities on that. After that you can write proper test cases accessing that custom features as well.
Update:
For those that might be referring to this in the future, Vue Plugins might be a better solution for this kind of functionality.
I stumbled along this issue in GitHub and that led me to the fix I made below:
https://github.com/testing-library/vue-testing-library/issues/113
Specifically, this comment by user nikravi:
ok, I found the fix. The trick was to add
import Vue from "vue";
import Vuetify from "vuetify";
Vue.use(Vuetify);
and then the render() works without warnings.
After I manually imported Vue and set Vue.prototype.$TestService = TestService directly in the unit test, it got passed that error. Personally, I think this is pretty silly, but it worked.
After this worked, I also found that you can access the Vue instance directly within the render callback (from #testing-library/vue), so I finished on this code instead of importing Vue:
render(TestComponent, {}, vue => {
vue.prototype.$TestService = TestService;
});
I've included all the commits to solve my issue in the repo I posted previously:
https://github.com/kcrossman/VueServiceExample
Some of the tests were malformed but once I made those changes, the tests started to work and I updated some other files to be a bit nicer for people to refer to.

Cypress tagged hooks with mocha

I have been building ui automation frameworks with Cypress for some time, but always using the Cypress-Cucumber-Preprocessor.
Now I need to build one without cucumber, just plain ol' mocha, but I found a problem. Seems like I can't use tagged hooks to execute code for specific tests (scenarios in Cucumber)
The scenario is basically this. I have a spec file with several tests. I have a "before" hook that seeds test data to a Mongo db, and eventually I might need to add a hook or hooks to execute something (whatever) before a specific test.
With Cucumber you have a way to tag a given scenario (#tag) and then you can create a hook that will be executed ONLY before or after that specific scenario
#tag
Scenario: Tagged scenario
Given condition
When I do this
Then I should see that
before({tag : '#tag'}, () => {
code
})
I haven't found a way to do this with mocha in Cypress... Anyone has found a way?
thx
You can use BeforeEach or Before, that does predominantly the same thing in Mocha.

Is it possible to create mock api on this cypress to prevent the actual api call

We have an vue js application which contains the component, On this component, there is an api call to update database records. We are doing unit test for this component.
Is it possible to create mock api on this cypress to prevent the actual api call? So database will not be modified during the unit test and can keep actual data as it is on database.
You can mock it indeed. For example this mocks a server and a specific API-call:
cy.server()
cy.route('POST', '**/oauth/v2/token', 'fixture:/oauth/agent-token.json')
More information about route is available on the cypress site: https://docs.cypress.io/api/commands/route.html
To make sure every request is mocked, use the force404 option with cy.server:
cy.server({force404: true})
cy.route('**/user/jake', {user:{name:'Jake'})
cy.visit('/')
// your test code here
Then any XHR request to /user/jake will work, but /user/jane and /login for example, will 404

In Jest how to dynamically generate tests based on the API call response

I want to generate tests on the fly by getting the json including array of data from an API indicating what should I do in each test and how many tests I need to do.
I tried to put the fetch part in "beforeAll" but anyway it is not working because jest wants all tests (it) at execution time.

Ember -- component integration async tests aren't waiting until async calls are returned

I'm having a hard time testing async functionality in component integration tests. Input kicks off an async call to an endpoint, and when it returns, I send an action. I'm trying to test that the action sends the correct data.
I've tried putting my assertion in the wait() helper, but the assertion gets hit before the (dependent upon async) action is called.
Here's a twiddle showing that problem: https://ember-twiddle.com/79f9a80c639b642e538803ac64a1cf9d?openFiles=tests.integration.components.test-comp-test.js%2Ctemplates.components.test-comp.hbs
How can I correctly code my async component integration tests?
There are two things that fails your test:
Firstly, never make use of setTimeout (window.setTimeout) to schedule some future work with Ember. Make use the Ember way of doing it; I mean Ember.run.later. For the same thing that happened to me with acceptance tests; please see the following question and look through comments on the answer. The reason is that; Ember's test helpers really cannot handle setTimeout as we expect it.
You have a problem within the test itself; in the action handler you have written in test you need to change the name attribute instead of returning a promise.
Anyway please see the following twiddle I have updated. Testing in general with Ember is kind of a pain; since I believe there is not a proper comprehensive documentation. Good luck!