Xetera / ghost-cursor

🖱️ Generate human-like mouse movements with puppeteer or on any 2D plane
MIT License
1.09k stars 118 forks source link

it works! but the pointer is not visible #34

Closed zeke closed 3 years ago

zeke commented 3 years ago

Hi @Xetera, @Niek, @kbourro, @garyanikin, and everyone else who's worked on this nifty little package.

I just gave this a try, and the clicking works, but I don't actually see a visible mouse pointer. I can see hover states, and clicking the link does indeed navigate to a new page, but no 🐁👀

Am I doing something wrong?

My code

import puppeteer from 'puppeteer'
import { createCursor } from 'ghost-cursor'
const url = 'https://github.com/nodejs/node/discussions'

async function main () {
  const browser = await puppeteer.launch({ headless: false, defaultViewport: null })
  const pages = await browser.pages()
  const page = pages[0]
  await page.goto(url)
  const selector = 'a[href="/nodejs/node/discussions/36430"]'
  await page.waitForSelector(selector)
  const cursor = createCursor(page)
  // await cursor.click(selector)
  await cursor.move(selector)
  await cursor.click()
  setTimeout(async () => {
    await browser.close()
  }, 3000)
}

main()

My environment

$ node --version
v16.3.0

$ npm ls puppeteer
discussions-translation-screencast@ /Users/z/Desktop/discussions-translation-screencast
└── puppeteer@10.1.0

$ uname -a
Darwin Zekes-MacBook-Pro.local 19.6.0 Darwin Kernel Version 19.6.0: Mon Apr 12 20:57:45 PDT 2021; root:xnu-6153.141.28.1~1/RELEASE_X86_64 x86_64
Niek commented 3 years ago

If you want a cursor, use installMouseHelper. See https://github.com/Xetera/ghost-cursor/issues/13#issuecomment-780440923

zeke commented 3 years ago

Ah thanks. Seem like this should be documented, eh? I'd be happy to open a PR for that if you're open to it.

zeke commented 3 years ago

Also the code shared in #13 doesn't seem to work for me:

Code

import * as puppeteer from 'puppeteer'
import { createCursor, getRandomPagePoint, installMouseHelper } from 'ghost-cursor'

(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  const cursor = createCursor(page, await getRandomPagePoint(page), true)
  await installMouseHelper(page) // this shows the trace
  page.goto('https://www.example.com/')
  await cursor.click('element', { waitForClick: 10000, waitForSelector: 1000, paddingPercentage: 20 })
})()

Error

$ node index.js
file:///Users/z/Desktop/discussions-translation-screencast/index.js:2
import { createCursor, installMouseHelper } from 'ghost-cursor'
                       ^^^^^^^^^^^^^^^^^^
SyntaxError: Named export 'installMouseHelper' not found. The requested module 'ghost-cursor' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'ghost-cursor';
const { createCursor, installMouseHelper } = pkg;
Niek commented 3 years ago

Yes we badly need some proper docs, see issue #13 - if you want to do a PR, please!

The example I linked in TS code, for ES code you need to use the require() format.

zeke commented 3 years ago

This works for me:

import { createCursor } from 'ghost-cursor'

But this does not:

import { createCursor, installMouseHelper } from 'ghost-cursor'

Nor does this:

import { createCursor } from 'ghost-cursor'
const { installMouseHelper } = require('ghost-cursor')
zeke commented 3 years ago

@Niek any thoughts on the above? Again I'd be happy to submit some docs for this once I get it working.

Niek commented 3 years ago

@zeke Are you using TS, JS with CJS or JS with ES6 imports?

The code in https://github.com/Xetera/ghost-cursor/issues/34#issuecomment-873129584 works in TS, and the following works in JS with CJS imports:

const { createCursor, getRandomPagePoint, installMouseHelper } = require('ghost-cursor');
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  const cursor = createCursor(page, await getRandomPagePoint(page), true)
  await installMouseHelper(page) // this shows the trace
  page.goto('https://www.example.com/')
  await cursor.click('element', { waitForClick: 10000, waitForSelector: 1000, paddingPercentage: 20 })
})()
zeke commented 3 years ago

I figured out why this wasn't working. The mouse helper uses page.evaluateOnNewDocument() to create the cursor DOM element and attach to the window. So if installMouseHelper() is called after a page is loaded, nothing will happen.

The workaround is to call installMouseHelper() before navigating to the page with page.goto().

Here's a typescript example that is now working for me:

import puppeteer from 'puppeteer'
import { createCursor, installMouseHelper } from 'ghost-cursor'
const url = 'https://github.com/nodejs/node/discussions'

async function main () {
  const browser = await puppeteer.launch({ headless: false, defaultViewport: null })
  const pages = await browser.pages()
  const page = pages[0]
  await installMouseHelper(page)
  await page.goto(url)
  const selector = 'a[href="/nodejs/node/discussions/36430"]'
  await page.waitForSelector(selector)
  const cursor = createCursor(page)
  await cursor.move(selector)
  await cursor.click()
  setTimeout(async () => { await browser.close() }, 5000)
}

main()

To get this running:

npx ts-node example.ts

And I can now see the "cursor":

Screen Shot 2021-07-14 at 1 33 10 PM