Caleb Bergman
Caleb Bergman

Reputation: 858

Jest testing Vue Single File Components with Ionic Capacitor plugin imports

GitHub repo of the issue.

I'm building an Ionic app using Vue and Capacitor. I'm setting up unit tests using vue-test-utils + Jest. Jest unit tests are failing trying to import Capacitor plugins into Vue Single File Components.

The Vue app was created using Vue CLI 3 (v3.4.0). CLI options included unit testing using Jest. I'm new to unit testing altogether. I've naively tried mocking the @capacitor/core module prior to importing the Vue component; this didn't help.

jest.config.js (Vue CLI default)

module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": "vue-jest",
    ".+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$":
      "jest-transform-stub",
    "^.+\\.jsx?$": "babel-jest"
  },
  transformIgnorePatterns: ["/node_modules/"],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1"
  },
  snapshotSerializers: ["jest-serializer-vue"],
  testMatch: [
    "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
  ],
  testURL: "http://localhost/",
  watchPlugins: [
    "jest-watch-typeahead/filename",
    "jest-watch-typeahead/testname"
  ]
};

MyComponent.vue

<template>...</template>
<script>
import { Plugins } from '@capacitor/core'
const { Filesystem } = Plugins
...
</script>

MyComponent.spec.js

import { shallowMount } from "@vue/test-utils";
import Component from "@/components/MyComponent.vue";
...

I expect the test to run without issue. Instead, I get the following error message when Jest tries to import the component on line 2 of the spec file:

TypeError: Cannot destructure property `Filesystem` of 'undefined' or 'null'.

      35 | <script>
      36 | import { Plugins } from '@capacitor/core'
    > 37 | const { Filesystem } = Plugins

Plugins is undefined on line 36, thusly line 37 complains when it attempts to destructure Filesystem from it.

In a browser, however, the Filesystem object is as follows:

{
  "config": {
     "name": "Filesystem",
     "platforms": ["web"]
  },
  "loaded": false,
  "listeners": {}, 
  "windowListeners":{},
  "DEFAULT_DIRECTORY": "DATA",
  "DB_VERSION": 1,
  "DB_NAME": "Disc",
  "_writeCmds": ["add","put","delete"]
}

I don't know where the issue lies. I don't know if I should be doing something different with Jest, I don't know if I shouldn't be importing Capacitor plugins directly in Vue SFCs like I've seen in some examples, or...šŸ¤·ā€ā™‚ļø.

Upvotes: 0

Views: 937

Answers (2)

Caleb Bergman
Caleb Bergman

Reputation: 858

Per @jcesarmobile's comment on the OP, updating @capacitor/core from version 1.0.0 to 1.1.0 resolved the issue entirely.

Fix: make capacitor compatible with commonjs

Upvotes: 0

Caleb Bergman
Caleb Bergman

Reputation: 858

EDIT

Although this made the test past, upgrading the @capacitor/core package to v1.1.0 (released just hours ago) resolved the issue, too.


Following the Jest docs on mocking Node modules - specifically scoped modules - I created a __mocks__ folder under root, created a directory underneath it named @capacitor and created a file underneath that called core.js. So I ended up with a structure like:

.
ā”œā”€__mocks__
ā”‚ ā””ā”€ @capacitor
ā”‚    ā””ā”€ core.js

Inside of core.js I export the pieces that are imported by the Vue components I'm testing (currently only Plugins and Plugins.Filesystem):

// core.js
module.exports = {
  Plugins: {
    Filesystem: {}
  }
}

With those in place the Jest test passes with flying green colors.

Upvotes: 0

Related Questions