最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vue.js - Electron + Mocha + WDIO unable to mock ipcMain calls - Stack Overflow

programmeradmin5浏览0评论

Update: Created Minimal reproducible example on GitHub.

I'm having an issue with mocking ipcMain in wdio + electron + mocha. I have a running electron app that I'm trying to e2e test, but I'm unable to intercept / replace ipcMain message responses.

I may not actually need to replace the ipcMain responses if I can otherwise pass the value I want, but I think mocking out ipcMain is the way to go. I don't seem to have access to the Main thread objects to mock them, is that true?

Here's the relevant part of my app, which is written in Vue:

<template>
        <div class="plugin__output" v-if="outputMessage">
            {{ outputMessage }}
        </div>
</template>

<script start lang="ts">
import { ref, defineComponent, Ref, computed } from "vue"

declare const electronAPI: {
    sendMessage: (message: string) => Promise<string>
}

export default defineComponent({
    name: "PathChecker",
    setup() {
        const outputMessage: Ref<string> = ref("")

        async function checkIsAvailable(): Promise<void> {
            const response = await electronAPI.sendMessage(
                "plugin:PathChecker:availability"
            )
            if (response === "true") {
                outputMessage.value = ""
                return
            }
            outputMessage.value = `Plugin disabled: ${response}`
        }

        async function handleClick(): Promise<void> {
            outputMessage.value = ""
            const response = await electronAPI.sendMessage(
                "plugin:PathChecker:performCheck"
            )

            // The actual app does other stuff here, this is for the demo
            outputMessage.value = response;
        }

        // Check if this plugin is available at creation time.
        checkIsAvailable()

        return {
            outputMessage,
        }
    },
})
</script>

I've written the following test:

import { browser, expect } from "@wdio/globals"

describe('MyComponent', () => {
    it("Should have an disabled button if plugin:PathChecker:availability returns anything but 'true'", async () => {
        // Attempt to return "mocked" instead of "true".
        // This mock is never called.
        const ipcMock = await browser.electron.mock("ipcMain", "handle", "mocked")
        const pluginPathChecker = browser.$(".plugin--path-checker")
        await expect(
            await pluginPathChecker.$(".plugin__header__button").isEnabled()
        ).toBeFalsy()
        expect(ipcMock).toHaveBeenCalledTimes(1);
    })
});

However, the browser.electron.mock call doesn't seem to do anything at all. My best guess is that I'm mocking it too late - the component has already run checkIsAvailable() by the time my test is running.

I've also tried adding this instead of the mock method at the start of my test, but with no effect.

await browser.electron.execute((electron) => {
            electron.ipcMain.removeHandler("message")
            electron.ipcMain.handle("message", async () => "mocked")
        })

Let me know if there's anything else I can provide to clarify or help!

[Update 2025-01-30] I spent another hour hacking away at this and I think I know better what my actual questions are:

  • When using wdio + electron, is there a way to access variables on the main process?
  • or, is there a way to mock/fake ipc calls between the main process and the render process?
  • or, is there a way to mock out functions on my vue component before rendering it?

I think solving any of these (or maybe there's another way!) will get me to what I want, which is to control the information that the vue component receives from the main process

Note that this question is similar to this question, but with different context. A solution to this one might solve that one as well.

发布评论

评论列表(0)

  1. 暂无评论