I have a function called getTodaysHours() in my controller that I would like to test. I was wondering if I can mock the JSON data below in my unit testing spec?
describe('vendor controller', () => {
let vm;
beforeEach(angular.mock.module('thcmaps-ui'));
beforeEach(inject(($controller) => {
vm = $controller('VendorController');
vm.data = {"_id":"56b54f9368e685ca04aa0b87","lat_lon":"33.713018,-117.841101",...}
}));
it('should state store hours for today', () => {
console.log(vm.data);
expect(1).toEqual(1);
});
});
vendor.controller
export class VendorController {
constructor($rootScope, data, event, toastr, moment, _, distanceService, vendorDataService, userDataService, stateManagerService) {
'ngInject';
//deps
this.$rootScope = $rootScope;
this.toastr = toastr;
this._ = _;
this.userDataService = userDataService;
this.vendorDataService = vendorDataService;
this.stateManagerService = stateManagerService;
this.event = event;
//bootstrap
data.isDeepLink = true;
this.data = data;
this.data.last_update = moment(this.data.updated_at).format('MM/DD/YY h:mm A');
this.data.distance = distanceService.getDistance(this.data.loc.lng, this.data.loc.lat);
this.data.todaysHours = this.getTodaysHours();
this.data.rating_num = Math.floor(data.rating);
this.hasReviewed = (userDataService.user.reviewed[data._id]) ? true : false;
this.isGrid = false;
this.isSearching = false;
this.hideIntro = true;
this.menuCollapsed = true;
this.filterMenuCollapsed = true;
this.selectedCategory = 'All';
this.todaysHours = '';
this.type = '';
this.searchString = '';
this.reviewScore = 0;
this.today = new Date().getDay();
this.vendorDataService.currentVendor = data;
//load marker onto map
$rootScope.$broadcast(event.ui.vendor.pageLoad, data);
//get menu
vendorDataService.getVendorMenu(data._id)
.then((res)=> {
this.data.menu = res.menu;
this.menuContainer = this.data.menu;
this.totalResults = this.getTotalResults();
this.availableMenuCategories = this.getAvailableMenuCategories();
})
.catch(() => {
this.toastr.error('Whoops, Something went wrong! We were not able to load the menu.', 'Error');
});
}
//get todays hours
getTodaysHours() {
let today = this.data.hours[new Date().getDay()];
return (today.opening_time || '9:00am') + ' - ' + (today.closing_time || '5:00pm');
}
}
When I tried to log vm.data I'm getting
Error: [$injector:unpr] Unknown provider: dataProvider <- data <- VendorController
TypeError: undefined is not an object (evaluating 'vm.data')
Mocking JSON data should work with $provide constant, after the mocking of your module.
let data = {"_id":"56b54f9368e685ca04aa0b87",
"lat_lon":"33.713018,-117.841101",...}
beforeEach(angular.mock.module('thcmaps-ui',
($provide) => {
$provide.constant('data', new data);
}));
To be honest I just tried it out with functions, not with JSON data, but it should work the same way.
Related
I am trying to read some data from 2 different tables and parse a CSV file before rendering an ejs file.
I can get the data from both tables and from the CSV file but I seem to be unable to return the result.
Pretty sure this is a problem with the way I handle async execution but I fail to see what I am doing wrong.
I've spent the last 2 days reading about this (including the threads around here) and browsing but somehow the answer still escapes me.
First file - usercms.js
app.get('/userscms', function(req, res)
{
existingUsers.getExistingUsers()
.then(function(appUsers)
{
//global users array
//I can display these in my ejs file
globalAppUsers = appUsers;
})
.then(existingUsersAttributesQlik.getExistingUsersAttributesQlik())
.then(function(usersQlikAttributes)
{
//global user attributes array
//undefined data
globalUsersQlikAttributes = usersQlikAttributes;
})
.then(existingSuppliers.parseSuppliersCSV())
.then(function(supplierData)
{
//the result I am expecting
//this prints undefined
console.log(supplierData);
}).then(function()
{
res.render('userscms.ejs',
{
users: globalAppUsers,
attributes: globalUsersQlikAttributes
});
});
});
Second function - getxistingUsers.js (identical to the getExistingUsersAttributesQlik, except for the query)
var userData = [];
var appUsers = [];
(function (exports)
{
exports.getExistingUsers = function ()
{
return promisemysql.createConnection(dbconfig.development).then(function(conn)
{
var result = conn.query("SELECT id, username, firstName, lastName, email, phone, lastLogin, isAdmin, isValid, isPhoneValid, accountCreationDateTime FROM Users");
conn.end();
return result;
}).then(function(rows)
{
return rows;
}).then(function(rows)
{
if (rows.length)
{
userData = [];
appUsers = [];
rows.forEach(function (elem)
{
userData.push(_.toArray(elem));
});
for (i = 0; i < userData.length; i++)
{
var appUser = new appUserModel.AppUser(
userData[i][0],
userData[i][1],
userData[i][2],
userData[i][3],
userData[i][4],
userData[i][5],
userData[i][6],
userData[i][7],
userData[i][8],
userData[i][9],
userData[i][10]);
appUsers.push(_.toArray(appUser));
}
return appUsers;
}
else
{
console.log("NOPE");
return null;
}
}).then(function(appUsers)
{
console.log(appUsers);
return appUsers;
});
};
})(typeof exports === 'undefined' ? this['getExistingUsers'] = {} : exports);
Third file - parseSuppliersCSV.js
var supplierData = [];
var suppliersData = [];
var csvCount = 0;
(function (exports)
{
exports.parseSuppliersCSV = function ()
{
return new Promise(function(resolve, reject)
{
var fileStream = fs.createReadStream("myCSV.csv");
var parser = fastCsv();
csvCount = 0;
supplierData = [];
suppliersData = [];
fileStream
.on("readable", function ()
{
var data;
while ((data = fileStream.read()) !== null)
{
parser.write(data);
}
})
.on("end", function ()
{
parser.end();
});
parser
.on("readable", function ()
{
var data;
while ((data = parser.read()) !== null)
{
if(csvCount >= 1)
{
csvCount++;
var arrayOfStrings = data[0].split(';');
var supplier = new supplierModel.Supplier(arrayOfStrings[0],arrayOfStrings[1]);
suppliersData.push(_.toArray(supplier));
}
else
{
csvCount++;
}
}
})
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return suppliersData;
});
});
};
})(typeof exports === 'undefined' ? this['parseSuppliersCSV'] = {} : exports);
Any ideas what I am doing wrong? Am I approaching this the wrong way?
I'll take a guess here and assume the promise you created should resolve to something...instead of returning a value.
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return resolve(suppliersData);
});
I am implementing a controller for a content picker in Umbraco 7, where I need to change the start node to match a specific content node. However wen I load up the page with the content picker I receive an error saying:
"Cannot read property 'config' of undefined"
In relation to this piece of code:
$scope.model.config.StartNodeId = 1083;
if ($scope.model.config.StartNodeId) {
options.startNodeId = $scope.model.config.StartNodeId;
}
My entire controller:
angular.module("umbraco").controller("UIOMatic.FieldEditors.Pickers.ContentController",
function ($scope, $routeParams, $http, dialogService, entityResource, iconHelper) {
function init() {
if (!$scope.setting) {
$scope.setting = {};
}
var val = parseInt($scope.property.value);
if (!isNaN(val) && angular.isNumber(val) && val > 0) {
$scope.showQuery = false;
entityResource.getById(val, "Document").then(function (item) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.node = item;
});
}
$scope.openContentPicker = function () {
var d = dialogService.treePicker({
section: "content",
treeAlias: "content",
multiPicker: false,
callback: populate
});
};
$scope.model.config.StartNodeId = 1083;
if ($scope.model.config.StartNodeId) {
options.startNodeId = $scope.model.config.StartNodeId;
}
$scope.clear = function () {
$scope.id = undefined;
$scope.node = undefined;
$scope.property.value = undefined;
};
function populate(item) {
$scope.clear();
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.node = item;
$scope.id = item.id;
$scope.property.value = item.id;
}
};
if ($scope.valuesLoaded) {
init();
} else {
var unsubscribe = $scope.$on('valuesLoaded', function () {
init();
unsubscribe();
});
}
});
I tried changing the start node ID to 1083, which is what I want, and I can open the content picker just fine, but it won't allow me to save my changes. It also allows for multi-picking, which I have set to false in my config object.
This is the documentation of the content picker from the author:
http://uiomatic.readthedocs.io/en/stable/02.DefaultEditorViews/#content-picker
I think You should initialize $scope.model before assigning value to its object.
use
$scope.model = {}
I have the following code:
var Promise = require('bluebird');
Promise.longStackTraces();
var path = require('path');
var fs = Promise.promisifyAll(require('fs-extra'));
var clone = require('nodegit').Clone.clone;
var tar = require('tar-fs');
var zlib = require('zlib');
var gzip = zlib.createGzip();
var globAsync = Promise.promisify(require('glob'));
module.exports = Archive;
function Archive(pkg) {
var self = this;
var tmp_dir_name = '.tmp';
var code_dir_name = 'code';
var files_dir_name = 'files';
var output_dir_name = 'archives';
var coverall_docs_dir_name = 'coverall_documents';
// the archive's name (no extension):
self.name = pkg.name;
self.recipient_name = pkg.recipient_name;
// path to letter.tex:
self.tex_letter_path = path.resolve(pkg.files.letter);
// path to resume.tex:
self.tex_resume_path = path.resolve(pkg.files.resume);
// path to merged.pdf (letter.pdf + resume.pdf):
self.pdf_package_path = path.resolve(pkg.compiled_files.package);
// temp dir where the archive is assembled:
self.tmp_path = path.resolve(tmp_dir_name, pkg.name);
// path to final archive:
self.output_path = path.resolve(output_dir_name, self.name + '.tar.gz');
// where to copy files to be added to the archive:
self.files_path = path.resolve(tmp_dir_name, self.name, files_dir_name);
// where the tex files are within the archive:
self.coverall_docs_path = path.resolve(self.files_path, code_dir_name, coverall_docs_dir_name);
}
Archive.prototype.make = Promise.method(function() {
var self = this;
return self._prepareFilesDir()
.then(self._copyFiles.bind(self))
.then(self._writeArchive.bind(self))
.then(self._delTmpDir.bind(self));
});
// ********************************
// * Private functions
// ********************************
Archive.prototype._prepareFilesDir = function() {
var self = this;
return fs.emptyDirAsync(self.tmp_path);
};
Archive.prototype._copyFiles = function() {
var self = this;
var sources = {
tex_letter_path: path.resolve(self.tex_letter_path, '..'),
tex_resume_path: path.resolve(self.tex_resume_path, '..'),
tex_letter_shared_path: path.resolve(self.tex_letter_path, '../../shared'),
pdf_package_path: self.pdf_package_path
};
var destinations = {
letter_path: path.resolve(self.coverall_docs_path, 'coverletters', self.recipient_name.toLowerCase()),
resume_path: path.resolve(self.coverall_docs_path, 'resume'),
letter_shared_path: path.resolve(self.coverall_docs_path, 'coverletters/shared'),
pdf_package_path: path.resolve(self.files_path, 'pdf', self.recipient_name.toLowerCase() + '.pdf'),
coverall_repo_path: path.resolve(self.files_path, 'code/coverall')
};
var filters = {
tex: function(filename) {
var contains_dot = /\./gm;
var hidden = /\/\./gm;
var cls_or_tex_file = /\.(cls|tex)$/gm;
var is_a_dir = !contains_dot.test(filename);
var is_not_hidden = (contains_dot.test(filename) && !hidden.test(filename));
var is_cls_or_tex = cls_or_tex_file.test(filename);
// it doesn't contain a dot or it isn't a hidden file or it is a cls/tex file
var is_allowed = is_a_dir || is_not_hidden || is_cls_or_tex;
return is_allowed;
},
pdf: /[^\.].*\.pdf/
};
var copyLetter = function() {
return fs.copyAsync(sources.tex_letter_path, destinations.letter_path, { filter: filters.tex });
};
function copyShared() {
return fs.copyAsync(sources.tex_letter_shared_path, destinations.letter_shared_path, { filter: filters.tex });
}
function copyResume() {
return fs.copyAsync(sources.tex_resume_path, destinations.resume_path, { filter: filters.tex });
}
function copyPdf() {
return fs.copyAsync(sources.pdf_package_path, destinations.pdf_package_path, { filter: filters.pdf });
}
function copyJs() {
return clone('https://github.com/coaxial/coverall.git', destinations.coverall_repo_path);
}
return Promise.all([
copyLetter(),
copyShared(),
copyResume(),
copyPdf(),
copyJs()
]);
};
Archive.prototype._writeArchive = function() {
var self = this;
var archive_dir_path = path.resolve(self.output_path, '..');
var tarPromise = function() {
return new Promise(function(resolve, reject) {
tar.pack(self.files_path)
.pipe(gzip)
.pipe(fs.createWriteStream(self.output_path))
.on('error', reject)
.on('finish', resolve);
});
};
return fs.ensureDirAsync(archive_dir_path)
.then(tarPromise);
};
Archive.prototype._delTmpDir = function() {
var self = this;
return fs.removeAsync(self.tmp_path);
};
and I am testing it with:
/*eslint-env mocha */
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var expect = chai.expect;
var Promise = require('bluebird');
Promise.longStackTraces();
var Archive = require('../lib/archive');
var path = require('path');
var fs = Promise.promisifyAll(require('fs-extra'));
var globAsync = Promise.promisify(require('glob'));
var tar = require('tar-fs');
var zlib = Promise.promisifyAll(require('zlib'));
var _ = require('lodash');
chai.use(chaiAsPromised);
describe.only('Archive', function() {
var pkg;
beforeEach(function() {
pkg = {
name: 'test_0790feebb1',
recipient_name: 'Test',
files: {
letter: '../coverall_documents/coverletters/test/letter.tex',
resume: '../coverall_documents/resume/resume.tex'
},
compiled_files: {
package: '../coverall_documents/coverletters/test/test.pdf'
}
};
});
// after(function() {
// return Promise.all([
// 'archives/test*',
// 'test/.tmp'
// ].map(function(glob_pattern) {
// return globAsync(glob_pattern)
// .each(function(filename) {
// // make every file writeable so the git packfiles can be removed
// return fs.chmodAsync(filename, '755')
// .then(function() { fs.removeAsync(filename); });
// })
// }));
// });
describe('#make', function() {
it('creates an archive', function() {
var modified_pkg = _.cloneDeep(pkg);
modified_pkg.name = 'test_0000000001';
var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');
var test_archive = new Archive(modified_pkg);
return test_archive.make()
.then(function() { return fs.statAsync(archive_location); })
.then(function(file) { return expect(file).to.exist; })
.catch(function(e) { return expect(e).to.not.exist; });
});
it('creates a gzip compressed archive', function() {
var modified_pkg = _.cloneDeep(pkg);
modified_pkg.name = 'test_0000000002';
var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');
var test_archive = new Archive(modified_pkg);
// inspired from https://github.com/mafintosh/gunzip-maybe/blob/master/index.js#L6-L11
var isGzipped = function(data) {
var GZIP_MAGIC_BYTES = [0x1f, 0x8b];
var DEFLATE_COMPRESSION_METHOD = 0x08;
var buffer = data[1];
if (buffer[0] !== GZIP_MAGIC_BYTES[0] && buffer[1] !== GZIP_MAGIC_BYTES[1]) return false;
if (buffer[2] !== DEFLATE_COMPRESSION_METHOD) return false;
return true;
};
return test_archive.make()
.then(function() { return fs.openAsync(archive_location, 'r'); })
.then(function(fd) {
var buffer = new Buffer(10);
var buffer_offset = 0;
var buffer_length = 10;
var file_position = 0;
return fs.readAsync(fd, buffer, buffer_offset, buffer_length, file_position);
})
.then(function(data) { console.log('data', data); return data; })
.then(function(data) { return expect(isGzipped(data)).to.be.true; })
});
it('has the correct directory structure', function() {
var modified_pkg = _.cloneDeep(pkg);
modified_pkg.name = 'test_0000000003';
var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');
var test_archive = new Archive(modified_pkg);
var tmp_extract_path = path.resolve('test/.tmp');
var tarPromise = function(archive_path) {
return new Promise(function(resolve, reject) {
fs.createReadStream(archive_path)
.pipe(zlib.Unzip())
.pipe(tar.extract(tmp_extract_path))
.on('error', reject)
.on('finish', resolve);
})
};
var verifyDir = function() {
return Promise.all([
'code',
'pdf',
'code/coverall',
'code/coverall_documents',
'code/coverall_documents/coverletters',
'code/coverall_documents/coverletters/test',
'code/coverall_documents/coverletters/shared',
'code/coverall_documents/resume',
'code/coverall_documents/coverletters'
].map(function(subpath) {
return expect(fs.statAsync(path.resolve(tmp_extract_path, subpath)))
.to.be.fulfilled;
}))
};
return test_archive.make()
.then(function() { return tarPromise(archive_location); })
.then(function() { return verifyDir(); });
});
it('removes the temporary dir', function() {
var modified_pkg = _.cloneDeep(pkg);
modified_pkg.name = 'test_0000000004';
var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');
var test_archive = new Archive(modified_pkg);
var tmp_dir = path.resolve('.tmp');
return test_archive.make()
.then(function() { return expect(fs.statAsync(tmp_dir)).to.be.rejected; });
});
});
});
Which results in:
$ mocha test
Archive
#make
✓ creates an archive (644ms)
1) creates a gzip compressed archive
2) has the correct directory structure
3) removes the temporary dir
1 passing (2s)
3 failing
1) Archive #make creates a gzip compressed archive:
Uncaught Error: write after end
at writeAfterEnd (_stream_writable.js:167:12)
at Gzip.Writable.write (_stream_writable.js:214:5)
at ondata (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:574:20)
at readableAddChunk (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:198:16)
at Readable.push (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:162:10)
at Pack._encode (node_modules/tar-fs/node_modules/tar-stream/pack.js:154:17)
at Pack.entry (node_modules/tar-fs/node_modules/tar-stream/pack.js:100:10)
at onstat (node_modules/tar-fs/index.js:108:19)
at node_modules/tar-fs/index.js:40:9
at FSReqWrap.oncomplete (fs.js:95:15)
2) Archive #make has the correct directory structure:
AssertionError: expected false to be true
at Context.<anonymous> (test/archive_spec.js:96:10)
3) Archive #make removes the temporary dir:
Uncaught Error: write after end
at writeAfterEnd (_stream_writable.js:167:12)
at Gzip.Writable.write (_stream_writable.js:214:5)
at ondata (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:574:20)
at readableAddChunk (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:198:16)
at Readable.push (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:162:10)
at Pack._encode (node_modules/tar-fs/node_modules/tar-stream/pack.js:154:17)
at Pack.entry (node_modules/tar-fs/node_modules/tar-stream/pack.js:100:10)
at onstat (node_modules/tar-fs/index.js:108:19)
at node_modules/tar-fs/index.js:40:9
at FSReqWrap.oncomplete (fs.js:95:15)
I suspected a race condition so I commented out the after block to see if it would make any difference but it doesn't.
I do not understand what the Uncaught Error: write after end is about nor why the stacktrace is unusable, even though I am using Promise.longStackTraces(). What is causing this error?
My tests look overly complicated for what they are doing and I am repeating code several times when instantiating the different test_archive objects. How could I refactor them?
You're trying to re-use the same gzip instance, which won't work. This also explains why the first test works just fine.
So move your var gzip = zlib.createGzip(); line to right inside your Archive.prototype._writeArchive function.
I want to be able to call simultaneously something like this in javascript:
classInstance.room.get('criteria');
classInstance.room('criteria').remove('criteria');
classInstance.room().update('criteria');
I have seen implemented something similar at shouldjs
should(10).be.a.Number();
(10).should.be.a.Number();
Updated
I have the following code:
function connectToDatabase() {
var server = orientDB(dbConfig.server);
var db = server.use(dbConfig.database);
db.on("endQuery", function onDbEndQuery() {
db.server.close();
});
return db;
}
var DbSet = function DbSet(name) {
return {
list: function list(where, select, order) {
where = where || true;
select = _.isString(select) || _.isArray(select) ? select : '*';
order = _.isString(order) || _.isArray(order) ? order : 'rid';
return connectToDatabase()
.select(select)
.from(name)
.where(where)
.order(order)
.all();
},
get: function get(where, select) {
where = where || true;
select = _.isString(select) || _.isArray(select) ? select : '*';
return connectToDatabase()
.select(select)
.from(name)
.where(where)
.all()
.then(function onResults(results) {
if (results.length > 1) {
throw new Error('multiple results');
}
return results[0];
});
},
create: function create(record) {
return connectToDatabase()
.insert()
.into(name)
.set(record)
.one();
},
update: function update(where, changes) {
where = where || true;
return connectToDatabase()
.update(name)
.set(changes)
.where(where)
.scalar();
},
remove: function remove(where) {
where = where || true;
return connectToDatabase()
.delete('VERTEX', name)
.where(where)
.scalar();
}
};
};
var db = function getDb() {
return {
room: new DbSet('Room'),
invitation: new DbSet('Invitation'),
participant: new DbSet('Participant'),
};
};
module.exports = db();
And I want to change the code be able to execute the following code:
var db=require('path/to/database');
var room = db.room.get({name:'room 1'});
var sameRoom = db.room({name:'room 1'}).get();
db.room.create({name:'second room'});
db.room({name:'second room'}).create();
//same for methods list and delete
var room = db.room.list({status:'active'});
var sameRooms = db.room({status:'active'}).list();
db.room.update({name:'second room'},{status:'inactive'});
db.room({name:'second room'}).update({status:'inactive'});
I want to be able to execute the same code for Invitation and Participant too.
We need more information as to what those functions do, but this code presents those features.
Klass = function () {};
Klass.prototype.room = function () {
....
return {
get: function () {...},
remove: function () {...},
update: function () {...}
}
};
Klass.prototype.room.get = function () {...};
classInstance = new Klass();
How can I get the latest page data (HTML & Javascript varaibles) from PhantomJS
e.g page.refresh() or something?
I have an Interval, than checks a variable (on the page) every 200ms. However, this variable and the page content, isn't shown to have changed over time. (even though I know it has)
So I need an efficient way to check the value of a JS variable every 200ms or so,
then once I've discovered that variable has changed value, I want to request the latest page HTML.
How can I do this?
var Error = function (description) {
this.description = description;
return this;
};
var DTO = function (status, content, error) {
this.status = status;
this.content = content;
this.error = error;
return this;
};
function outputAndExit(dto) {
console.log(JSON.stringify(dto));
phantom.exit();
}
//For any uncaught exception, just log it out for .NET to capture
window.onerror = function (errorMsg, url, lineNumber) {
var description = 'window.onerror caught an error: ' +
'errorMsg: ' + errorMsg +
'url: ' + url +
'lineNumber: ' + lineNumber;
outputAndExit(new DTO(false, null, new Error(description)));
};
var GetDynamicPageResult__ = function () {
var obj = new GetDynamicPageResult();
obj.initialize();
return obj;
};
var GetDynamicPageResult = function () {
var self = this;
this.initialize = function () {
this.error = null;
this.isContentReadyForCrawler = false;
this.ticker = null;
this.tickerInterval = 150;
this.tickerElapsed = 0;
this.url = '';
this.loadDependencies();
this.processArgs();
this.openPage();
};
this.loadDependencies = function () {
this.system = require('system'),
this.page = require('webpage').create(),
this.page.injectJs('jquery-1.10.2.min');
this.fs = require('fs');
};
this.processArgs = function () {
if (this.system.args.length == 0) {
outputAndExit(new DTO(false, null, new Error('No arguments given')));
}
//system.args[0] Was the name of this script
this.url = this.system.args[1];
};
this.updateIsContentReadyForCrawler = function () {
var updateIsContentReadyForCrawler = self.page.evaluate(function () {
self.isContentReadyForCrawler = window.isContentReadyForCrawler;
});
};
this.openPage = function () {
self.page.open(this.url, function (status) { //NB: status = 'success' || 'fail'
if (status !== 'success') {
outputAndExit(new DTO(false, null, new Error('page.open received a non-success status')));
}
self.initTicker();
});
};
this.initTicker = function () {
this.ticker = setInterval(self.handleTick, self.tickerInterval);
};
this.handleTick = function () {
self.tickerElapsed += self.tickerInterval;
self.updateIsContentReadyForCrawler();
if (self.isContentReadyForCrawler) {
clearInterval(self.ticker);
var content = self.page.content;
self.finish(true, content, null);
} else {
var tooMuchTimeElapsed = self.tickerElapsed > 7000;
if (tooMuchTimeElapsed) {
clearInterval(self.ticker);
self.finish(false, null, new Error('Too much time elapsed'));
}
}
};
this.finish = function (status, content, error) {
content = content || '';
error = error || {};
outputAndExit(new DTO(status, content, error));
};
};
/**********************************************************************************/
/***************************** Helpers *****************************/
/**********************************************************************************/
var Utility__ = function () {
var obj = new Utility();
obj.initialize();
return obj;
};
var Utility = function () {
var self = this;
this.initialize = function () {
};
this.isEmpty = function (obj) {
var isEmpty = false;
(obj == undefined || obj == null) && (isEmpty = true);
return isEmpty;
};
this.isStringEmpty = function (str) {
var isEmpty = false;
isEmpty(str) && (isEmpty = true);
(isEmpty == false && $.trim(str) == '') && (isEmpty = true);
return isEmpty;
};
};
var getDynamicPageResult = new GetDynamicPageResult__();
I think you are almost there: you need to be using page.evaluate(), but currently only use it to get window.isContentReadyForCrawler. You need to use page.evaluate() to grab the latest HTML too.
I'm going to shamelessly paste in code from another answer (https://stackoverflow.com/a/12044474/841830):
var html = page.evaluate(function () {
var root = document.getElementsByTagName("html")[0];
var html = root ? root.outerHTML : document.body.innerHTML;
return html;
});