segment-boneyard / nightmare

A high-level browser automation library.
https://open.segment.com
19.54k stars 1.08k forks source link

Unable to use Nightmare.js in an electron app #1637

Open ahsanaasim opened 3 years ago

ahsanaasim commented 3 years ago

I am using Nightmare.js inside an electron app with the webpack. But when I try to use Nightmare.js I am getting the following error

TypeError: window.Main.nightmare(...).goto is not a function
    at Function.eval [as loginUser] (NightmareUtils.ts?fe62:9)
    at handleSayHello (index.tsx?6a78:13)
    at HTMLUnknownElement.callCallback (react-dom.development.js?6ac8:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?6ac8:3994)
    at invokeGuardedCallback (react-dom.development.js?6ac8:4056)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?6ac8:4070)
    at executeDispatch (react-dom.development.js?6ac8:8243)
    at processDispatchQueueItemsInOrder (react-dom.development.js?6ac8:8275)
    at processDispatchQueue (react-dom.development.js?6ac8:8288)
    at dispatchEventsForPlugins (react-dom.development.js?6ac8:8299)

Here is how I am using Nightmare.js

export class NightmareUtils {
    static loginUser = (username: string, password: string, onDone: () => void) => {
        window.Main.sendMessage("Login")

        // console.log(window.Main.nightmare())

        try {
            window.Main.nightmare()
                .goto("https://www.linkedin.com/login")
                .wait(`body`)
                .type(`input[name="session_key"]`, username)
                .type(`input[name="session_password"]`, password)
                .click(`button[class='btn__primary--large from__button--floating']`)
                .wait(`body`)
                // .wait(20000)
                .then(() => {
                    onDone()
                })
                .catch((e) => {
                    console.log(e)
                })
        } catch (e: any) {
            console.log(e)
        }

    }
}

I am using webpack to preload the following code brige.ts

// @ts-nocheck
import { contextBridge, ipcRenderer } from 'electron'
import Nightmare from 'nightmare'

export const api = {
  /**
   * Here you can expose functions to the renderer process
   * so they can interact with the main (electron) side
   * without security problems.
   *
   * The function below can accessed using `window.Main.sayHello`
   */

  sendMessage: (message: string) => {
    ipcRenderer.send('message', message)
  },

  /**
   * Provide an easier way to listen to events
   */
  on: (channel: string, callback: Function) => {
    ipcRenderer.on(channel, (_, data) => callback(data))
  },

  nightmare: () => { 
    return new Nightmare({
      show: true
    }) 
  }
}

contextBridge.exposeInMainWorld('Main', api)

I posted a question in StackOverflow as well. But didn't get any response. https://stackoverflow.com/questions/68271424/unable-to-use-nightmare-js

ahsanaasim commented 3 years ago

I have changed the bright.ts file to something like this

// @ts-nocheck
import { contextBridge, ipcRenderer } from 'electron'
import Nightmare from 'nightmare';
// const Nightmare = require('nightmare')
const nightmare = new Nightmare({ electronPath: require('electron'), show: true });

export const api = {
  /**
   * Here you can expose functions to the renderer process
   * so they can interact with the main (electron) side
   * without security problems.
   *
   * The function below can accessed using `window.Main.sayHello`
   */

  sendMessage: (message: string) => {
    ipcRenderer.send('message', message)
  },

  /**
   * Provide an easier way to listen to events
   */
  on: (channel: string, callback: Function) => {
    ipcRenderer.on(channel, (_, data) => callback(data))
  },

  nightmare: (): Nightmare => { 
    // { electronPath: require('electron'), show: true }

    console.log(nightmare)
    return nightmare
  }
}

contextBridge.exposeInMainWorld('Main', api)

And when I call, console.log(window.Main.nightmare()) I can see an interesting thing... window.Main.nightmare() is not returning everything from nightmarejs.

I have explained the whole thing in this video https://www.loom.com/share/e0fac6e0bcdc4291968e6d03f0f0b9cc