Skip to content

Instantly share code, notes, and snippets.

@mstraughan86
Created April 7, 2018 04:54
Show Gist options
  • Save mstraughan86/254576f58df3c95df978d07c7242a1fb to your computer and use it in GitHub Desktop.
Save mstraughan86/254576f58df3c95df978d07c7242a1fb to your computer and use it in GitHub Desktop.
Experiments with Nightmare.js and Configuration-Driven-Development
const Nightmare = require('nightmare');
let webDriver;
const nightmareConfiguration = {
show: false,
openDevTools: false
};
const promiseSeries_withCombinedResults = (array, initial, ...args) => {
const combinedResults = [];
return array
.reduce((chain, promise)=>{
return chain
.then(result => promise(result, ...args))
.then(result => {
combinedResults.push(result);
Promise.resolve(result);
})
}, Promise.resolve(initial))
.then(()=>Promise.resolve(combinedResults));
};
const actionMap = (func, array) =>{
const promises = array.map(obj => {
return action.bind(null, func(obj))
});
return promiseSeries_withCombinedResults(promises)
};
/* param:
const exampleAction = {
url: '',
wait: '',
evaluate: ()=>{},
after: ([result, thiss])=>Promise.resolve(result)
};
*/
const action = act => {
return webDriver
.goto(act.url)
.wait(act.wait)
.evaluate(act.evaluate)
.then(result=>[result, act]) // pass itself into after() for recursion
.then(act.after)
.catch(err => {console.log(err)});
};
const terminate = () => {
return new Promise((resolve, reject) => {
webDriver
.end()
.then(function () {
console.log('Closed WebDriver.');
return resolve();
})
})
};
const initialize = value => {
console.log('Opened WebDriver.');
webDriver = Nightmare(nightmareConfiguration);
return Promise.resolve(value);
};
const EXAMPLE_IMDB_getAllEpisodeUrls = url => {
return {
url: url,
wait: 'img.poster',
evaluate: ()=>{
return {
collection: [...document.querySelectorAll('.list_item')].map(obj=>obj.querySelector('a').href),
next: (document.querySelector('#load_next_episodes')) ? document.querySelector('#load_next_episodes').href : false
}
},
after: ([result, thiss])=>{
if (result.next) {
thiss.url = result.next;
return webAction(thiss)
.then(results=>Promise.resolve(result.collection.concat(results)));
}
else return result.collection;
}
};
};
const EXAMPLE_IMDB_getEpisodeData = url => {
return {
url: url,
wait: '.poster img',
evaluate: ()=>{
return {
show: document.querySelector('.titleParent a').textContent.trim(),
title: document.querySelector('.title_wrapper h1').textContent.trim(),
duration: document.querySelector('.title_wrapper time').textContent.trim(),
genres: [...document.querySelectorAll('.title_wrapper a span')].map(i=>i.textContent.trim()),
aired: document.querySelector('.title_wrapper a meta').getAttribute('content'),
season: document.querySelector('.bp_heading').textContent.split('|')[0].trim().split(' ')[1],
episode: document.querySelector('.bp_heading').textContent.split('|')[1].trim().split(' ')[1],
description: document.querySelector('.summary_text').textContent.trim()
};
},
after: ([result, thiss])=>Promise.resolve(result)
};
};
/* Usage example:
return initialize()
.then(action.bind(null, EXAMPLE_IMDB_getAllEpisodeUrls(IMDB_targetUrl)))
.then(actionMap.bind(null, EXAMPLE_IMDB_getEpisodeData))
.then(terminate)
.catch();
*/
/*
Actions
get accounts shallow (shallow single page lookup)
get accounts deep (go through to each page and get it. maybe even a modal for additional information)
get account information by account
get account transaction records by date range
get account transaction records all
open an account
change account type
*/
module.exports = {
actionMap,
action,
terminate,
initialize
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment