Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  refactor: make content script injection and event handler attachments idempotent
  refactor: refactor restart vs. cleanup logic
  feat: adds togglable waitForNavigation on navigation attempts.
  refactor: fixes some debug statements
  refactor: replaces css selector library. Closes #5
  feat: sets the viewport before the goto command. Closes #10
  feat: adds the headless true/false option. Closes #9
  fix: fixes not loading of options. Closes #11
  • Loading branch information
tnolet committed Aug 21, 2018
2 parents f024cad + 5ff27cb commit bd76ef7
Show file tree
Hide file tree
Showing 11 changed files with 339 additions and 75 deletions.
26 changes: 19 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
},
"homepage": "https://github.com/checkly/puppeteer-recorder#readme",
"dependencies": {
"css-selector-generator": "^1.0.2",
"debug": "^3.1.0",
"@medv/finder": "^1.1.0",
"vue": "^2.5.17",
"vue-clipboard2": "^0.2.1",
"vue-highlightjs": "^1.3.3"
Expand Down
79 changes: 47 additions & 32 deletions src/background/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class RecordingController {
port.onMessage.addListener(msg => {
if (msg.action && msg.action === 'start') this.start()
if (msg.action && msg.action === 'stop') this.stop()
if (msg.action && msg.action === 'restart') this.restart()
if (msg.action && msg.action === 'cleanUp') this.cleanUp()
if (msg.action && msg.action === 'pause') this.pause()
if (msg.action && msg.action === 'unpause') this.unPause()
})
Expand All @@ -23,30 +23,35 @@ class RecordingController {

start () {
console.debug('start recording')
this._badgeState = 'rec'
this.cleanUp(() => {
this._badgeState = 'rec'

if (!this._scriptInjected) {
// if (!this._scriptInjected) {
chrome.tabs.executeScript({file: 'content-script.js'})
this._scriptInjected = true
}

chrome.tabs.query({active: true, currentWindow: true}, tabs => {
chrome.tabs.sendMessage(tabs[0].id, { control: 'get-current-url' }, response => {
if (response) this.recordCurrentUrl(response.href)
// this._scriptInjected = true
// }

chrome.tabs.query({active: true, currentWindow: true}, tabs => {
chrome.tabs.sendMessage(tabs[0].id, { control: 'get-viewport-size' }, response => {
if (response) this.recordCurrentViewportSize(response.value)
})
chrome.tabs.sendMessage(tabs[0].id, { control: 'get-current-url' }, response => {
if (response) this.recordCurrentUrl(response.href)
})
})
})

this._boundedMessageHandler = this.handleMessage.bind(this)
this._boundedNavigationHandler = this.handleNavigation.bind(this)
this._boundedWaitHandler = this.handleWait.bind(this)
this._boundedMessageHandler = this.handleMessage.bind(this)
this._boundedNavigationHandler = this.handleNavigation.bind(this)
this._boundedWaitHandler = this.handleWait.bind(this)

chrome.runtime.onMessage.addListener(this._boundedMessageHandler)
chrome.webNavigation.onCompleted.addListener(this._boundedNavigationHandler)
chrome.webNavigation.onBeforeNavigate.addListener(this._boundedWaitHandler)
chrome.runtime.onMessage.addListener(this._boundedMessageHandler)
chrome.webNavigation.onCompleted.addListener(this._boundedNavigationHandler)
chrome.webNavigation.onBeforeNavigate.addListener(this._boundedWaitHandler)

chrome.browserAction.setIcon({ path: './images/icon-green.png' })
chrome.browserAction.setBadgeText({ text: this._badgeState })
chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' })
chrome.browserAction.setIcon({ path: './images/icon-green.png' })
chrome.browserAction.setBadgeText({ text: this._badgeState })
chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' })
})
}

stop () {
Expand All @@ -62,16 +67,7 @@ class RecordingController {
chrome.browserAction.setBadgeBackgroundColor({color: '#45C8F1'})

chrome.storage.local.set({ recording: this._recording }, () => {
console.debug('_recording stored')
})
}

restart () {
console.debug('restart')
this._recording = []
chrome.browserAction.setBadgeText({ text: '' })
chrome.storage.local.remove('_recording', () => {
console.debug('stored _recording cleared')
console.debug('recording stored')
})
}

Expand All @@ -89,18 +85,36 @@ class RecordingController {
this._isPaused = false
}

cleanUp (cb) {
console.debug('cleanup')
this._recording = []
chrome.browserAction.setBadgeText({ text: '' })
chrome.storage.local.remove('recording', () => {
console.debug('stored recording cleared')
if (cb) cb()
})
}

recordCurrentUrl (href) {
this.handleMessage({ selector: undefined, value: undefined, action: 'goto*', href })
}

recordCurrentViewportSize (value) {
this.handleMessage({ selector: undefined, value, action: 'viewport*' })
}

recordNavigation () {
this.handleMessage({ selector: undefined, value: undefined, action: 'navigation*' })
}

handleMessage (msg) {
console.debug('receiving message', msg)
if (msg.control) return this.handleControlMessage(msg)

if (!this._isPaused) {
this._recording.push(msg)
chrome.storage.local.set({ recording: this._recording }, () => {
console.debug('stored _recording updated')
console.debug('stored recording updated')
})
}
}
Expand All @@ -109,10 +123,11 @@ class RecordingController {
if (msg.control === 'event-recorder-started') chrome.browserAction.setBadgeText({ text: this._badgeState })
}

handleNavigation ({ url, frameId }) {
console.debug(`current frame ${frameId} with url ${url}`)
handleNavigation ({ frameId }) {
console.debug('frameId is:', frameId)
if (frameId === 0) {
chrome.tabs.executeScript({file: 'content-script.js'})
this.recordNavigation()
}
}

Expand Down
27 changes: 18 additions & 9 deletions src/content-scripts/index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import eventsToRecord from './events-to-record'
import elementsToBindTo from './elements-to-bind-to'
import Selector from 'css-selector-generator'

const selector = new Selector()
import finder from '@medv/finder'

class EventRecorder {
start () {
const elements = document.querySelectorAll(elementsToBindTo.join(','))

for (let i = 0; i < elements.length; i++) {
for (let j = 0; j < eventsToRecord.length; j++) {
elements[i].addEventListener(eventsToRecord[j], recordEvent)
}
}
addAllListeners(elements)

chrome.runtime.onMessage.addListener((msg, sender, resp) => {
if (msg.control && msg.control === 'get-current-url') {
resp({ href: window.location.href })
}

if (msg.control && msg.control === 'get-viewport-size') {
resp({ value: { width: window.innerWidth, height: window.innerHeight } })
}
})
const msg = { control: 'event-recorder-started' }
sendMessage(msg)
console.debug('Puppeteer Recorder in-page EventRecorder started')
}
}

function addAllListeners (elements) {
for (let i = 0; i < elements.length; i++) {
for (let j = 0; j < eventsToRecord.length; j++) {
if (!elements[i].getAttribute('data-pptr-rec')) {
elements[i].addEventListener(eventsToRecord[j], recordEvent, false)
elements[i].setAttribute('data-pptr-rec', 'on')
}
}
}
}

function recordEvent (e) {
const msg = {
selector: selector.getSelector(e.target),
selector: finder(e.target, { seedMinLength: 5, optimizedMinLength: 10 }),
value: e.target.value,
action: e.type,
keyCode: e.keyCode ? e.keyCode : null,
Expand Down
31 changes: 26 additions & 5 deletions src/options/components/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,24 @@
Code Generator settings
</h4>
<div class="settings-block-main">
<label>
<input id="options-code-wrapAsync" type="checkbox" v-model="options.code.wrapAsync" @change="save">
wrap code in async function
</label>
<div class="settings-group">
<label>
<input id="options-code-wrapAsync" type="checkbox" v-model="options.code.wrapAsync" @change="save">
wrap code in async function
</label>
</div>
<div class="settings-group">
<label>
<input id="options-code-headless" type="checkbox" v-model="options.code.headless" @change="save">
set <code>headless</code> in puppeteer launch options
</label>
</div>
<div class="settings-group">
<label>
<input id="options-code-waitForNavigation" type="checkbox" v-model="options.code.waitForNavigation" @change="save">
add <code>waitForNavigation</code> lines on navigation
</label>
</div>
</div>
</div>
</div>
Expand All @@ -33,7 +47,9 @@
<script>
const defaults = {
code: {
wrapAsync: true
wrapAsync: true,
headless: true,
waitForNavigation: true
}
}
Expand Down Expand Up @@ -128,6 +144,11 @@
.settings-block-main {
padding: $spacer 0;
margin-bottom: $spacer;
.settings-group {
margin-bottom: $spacer;
display: block;
}
}
}
}
Expand Down
Loading

0 comments on commit bd76ef7

Please sign in to comment.