What are ways to play a sound in PhantomJS/CasperJS? - phantomjs

I've been searching the web for more than 3 hours now looking for relevant ways to play an audio file but unfortunately I can't find anything useful. I have a CasperJS that's automating some tasks and I wanted it to play an audio file (e.g. beep.wav) after it completes all the tasks. I wonder if it's possible.
casper.run(function(casper) {
fs.write( saveDir, JSON.stringify(content, null, ' '), 'w');
// play an audio file before exiting....
casper.exit();
});

You need to use Child Process Module to run your script, to play the music.
I created pl.sh script to play the music:
#!/bin/bash
mplayer "/music/downloads2/Technoboy - Into Deep.oga"
exit 0
Then I created CasperJS script:
var casper = require('casper').create();
casper
.start('http://domu-test-2/node/12', function(){
var childProcess;
try {
childProcess = require("child_process")
} catch(e){
console.log(e, "(error)")
}
if (childProcess){
childProcess.execFile("/bin/bash", ["./pl.sh"], null, function(err, stdout, stderr){
console.log("execFileSTDOUT: "+stdout);
console.log("execFileSTDERR:",stderr);
});
console.log("Shell commands executed")
} else {
console.log("Unable to require child process (error)")
}
this.wait(10000)// need to wait to play the sound
})
.run();
And then PhantomJS script:
var page = require('webpage').create();
page.open('http://domu-test-2/node/12', function() {
var childProcess;
try {
childProcess = require("child_process")
} catch(e){
console.log(e, "(error)")
}
if (childProcess){
childProcess.execFile("/bin/bash", ["./pl.sh"], null, function(err, stdout, stderr){
console.log("execFileSTDOUT: "+stdout);
console.log("execFileSTDERR:",stderr);
});
console.log("Shell commands executed")
} else {
console.log("Unable to require child process (error)")
}
setTimeout(phantom.exit,10000)// need to wait to play the sound
});

Related

WebdriverIO: How to run file-uploading AutoIt .exe script

I am using WebdriverIO to run a file-uploading .exe created with AutoIt.
I am running the script inside a browser.execute command. The file needs to run from the local drive and execute wd in Chrome browser.
Here is the code :
this.open("https://smallpdf.com/word-to-pdf");
this.SubmitClick("//div[#class='l0v3m7-3 hIetmU']");
this.BrowserSleep(2000);
scr.runAutoItScript('C:\\test\\desktopApp\\autoit', 'fileUpload.exe')
//scr have the child process:
const { execFile } = require('child_process').execFile;
module.exports = {
runAutoItScript(pathToScript, scriptName) {
console.info(`\n> Started execution of ${pathToScript} / ${scriptName} ...`);
execFile(`${pathToScript}/${scriptName}`, (error, stdout, stderr) => {
if (error) {
throw error;
} else {
console.info(`\n> Finished execution of ${scriptName}! | Output: ${stdout}`);
}
});
}
}
I remember doing something like this in the past and I used NodeJS's child_process.execFile command. The documentation is heavy on child_process, so read carefully.
You should end up with something along the lines of:
const execFile = require('child_process').execFile;
let runAutoItScript = function(pathToScript, scriptName) {
console.info(`\n> Started execution of ${scriptName} ...`);
execFile(`${pathToScript}/${scriptName}`, (error, stdout, stderr) => {
if (error) {
throw error;
} else {
// > do something with the script output <
console.info(`\n> Finished execution of ${scriptName}! | Output: ${stdout}`);
}
});
}
runAutoItScript('/this/is/a/valid/path', 'AwesomeScript.exe');
Next step would be to minify it and make it run inside browser.execute call.
You can find a lot of child_process examples online, just leverage the resources available to run the simplest script. Develop from there.

Mediastream Recording API. ondataavailable is not triggered

I am trying to record media using the mediaRecorder API. Here is my code (just the relevant part). I expect to get a console log in saveChunks but it appears that the ondataavailable event is never triggered.I am able to see the video in the video element.
recordedChunks = [];
navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(function(stream) {
myVideoMedia = document.getElementById("vid1");
myVideoMedia.srcObject = stream;
myVideoMedia.onloadedmetadata = function(e) {
myVideoMedia.play();
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = saveChunks;
mediaRecorder.start();
console.log(mediaRecorder);
};
})
function saveChunks(event) {
console.log("Data recorded...");
//...
};
}
The console log of mediaRecorder.state is 'recording'
I did try by passing a timeslice of 1000 to start() and its working now! If no timeslice is passed, the function is called once at the end.

CasperJS can not trigger twitter infinite scroll

I am trying to get some information from twitter using CasperJS. And I'm stuck with infinite scroll. The thing is that even using jquery to scroll the page down nothings seems to work. Neither scrolling, neither triggering the exact event on window (smth like uiNearTheBottom) doesn't seem to help.
Interesting thing - all of these attempts work when injecting JS code via js console in FF & Chrome.
Here's the example code :
casper.thenEvaluate(function(){
$(window).trigger('uiNearTheBottom');
});
or
casper.thenEvaluate(function(){
document.body.scrollTop = document.body.scrollHeight;
});
If casper.scrollToBottom() fails you or casper.scroll_to_bottom(), then the one below will serve you:
this.page.scrollPosition = { top: this.page.scrollPosition["top"] +
document.body.scrollHeight, left: 0 };
A working example:
casper.start(url, function () {
this.wait(10000, function () {
this.page.scrollPosition = { top: this.page.scrollPosition["top"] + document.body.scrollHeight, left: 0 };
if (this.visible("div.load-more")) {
this.echo("I am here");
}
})});
It uses the underlying PhantomJS scroll found here
CasperJs is based on PhantomJS and as per below discussion no window object exist for the headless browser.
You can check the discussion here
On Twitter you can use:
casper.scrollToBottom();
casper.wait(1000, function () {
casper.capture("loadedContent.png");
});
But if you include jQuery... , the above code won't work!
var casper = require('casper').create({
clientScripts: [
'jquery-1.11.0.min.js'
]
});
The script injection blocks Twitter's infinite scroll from loading content. On BoingBoing.net, CasperJS scrollToBottom() works with jQuery without blocking. It really depends on the site.
However, you can inject jQuery after the content has loaded.
casper.scrollToBottom();
casper.wait(1000, function () {
casper.capture("loadedContent.png");
// Inject client-side jQuery library
casper.options.clientScripts.push("jquery.js");
// And use like so...
var height = casper.evaluate(function () {
return $(document).height();
});
});
I have adopted this from a previous answer
var iterations = 5; //amount of pages to go through
var timeToWait = 2000; //time to wait in milliseconds
var last;
var list = [];
for (i = 0; i <= iterations; i++) {
list.push(i);
}
//evaluate this in the browser context and pass the timer back to casperjs
casper.thenEvaluate(function(iters, waitTime) {
window.x = 0;
var intervalID = setInterval(function() {
console.log("Using setInternal " + window.x);
window.scrollTo(0, document.body.scrollHeight);
if (++window.x === iters) {
window.clearInterval(intervalID);
}
}, waitTime);
}, iterations, timeToWait);
casper.each(list, function(self, i) {
self.wait(timeToWait, function() {
last = i;
this.echo('Using this.wait ' + i);
});
});
casper.waitFor(function() {
return (last === list[list.length - 1] && iterations === this.getGlobal('x'));
}, function() {
this.echo('All done.')
});
Essentially what happens is I enter the page context, scroll to the bottom, and then wait 2 seconds for the content to load. Obviously I would have liked to use repeated applications of casper.scrollToBottom() or something more sophisticated, but the loading time wasn't allowing me to make this happen.

Handling leaf node in sencha

I am creating a nested list using sencha.
Now on tap i get a list it goes on till i get to the leaf node.
Now what i want is, on clicking a leaf node, i want to generate an event which enables me to open a file.
Not sure how to do that.
my nested list code is
Ext.define("InfoImage.view.nestedList", {
extend:'Ext.NestedList',
xtype:'nestedList',
id:'nestedList',
config:{
fullscreen:'true',
title:'Nested List',
xtype:'nestedList',
displayField : 'text',
html:'Nested List on its way!!!',
store:'nestedListStore'
//itemTpl:'{text}'
}
});
Thanks in advance.
I think, your require PhoneGap here.
File System Access is not available with Sencha Touch. So, you need to use phonegap's File API to access and read the file stored on the system.
Check out the File API Documentation,
FILE API : An API to read, write and navigate file system hierarchies.
Sample e.g from Phonegap,
...
...
// PhoneGap is ready
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getFile("readme.txt", {create: true}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.file(gotFile, fail);
}
function gotFile(file){
readDataUrl(file);
readAsText(file);
}
function readDataUrl(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("Read as data URL");
console.log(evt.target.result);
};
reader.readAsDataURL(file);
}
function readAsText(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("Read as text");
console.log(evt.target.result);
};
reader.readAsText(file);
}
...
...
Hope that helps you!
I found the solution using the event: "onleafitemtap" provided by the nested list.

Can I use Ext's loader to load non-ext scripts/object dynamically?

In my ExtJS 4.0.7 app I have some 3rd party javascripts that I need to dynamically load to render certain panel contents (some fancy charting/visualization widgets).
I run in to the age-old problem that the script doesn't finish loading before I try to use it. I thought ExtJS might have an elegant solution for this (much like the class loader: Ext.Loader).
I've looked at both Ext.Loader and Ext.ComponentLoader, but neither seem to provide what I'm looking for. Do I have to just "roll my own" and setup a timer to wait for a marker variable to exist?
Here's an example of how it's done in ExtJS 4.1.x:
Ext.Loader.loadScript({
url: '...', // URL of script
scope: this, // scope of callbacks
onLoad: function() { // callback fn when script is loaded
// ...
},
onError: function() { // callback fn if load fails
// ...
}
});
I've looked at both Ext.Loader and Ext.ComponentLoader, but neither
seem to provide what I'm looking for
Really looks like it's true. The only thing that can help you here, I think, is Loader's injectScriptElement method (which, however, is private):
var onError = function() {
// run this code on error
};
var onLoad = function() {
// run this code when script is loaded
};
Ext.Loader.injectScriptElement('/path/to/file.js', onLoad, onError);
Seems like this method would do what you want (here is example). But the only problem is that , ... you know, the method is marked as private.
This is exactly what newest Ext.Loader.loadScript from Ext.4-1 can be used for.
See http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Loader-method-loadScript
For all you googlers out there, I ended up rolling my own by borrowing some Ext code:
var injectScriptElement = function(id, url, onLoad, onError, scope) {
var script = document.createElement('script'),
documentHead = typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
cleanupScriptElement = function(script) {
script.id = id;
script.onload = null;
script.onreadystatechange = null;
script.onerror = null;
return this;
},
onLoadFn = function() {
cleanupScriptElement(script);
onLoad.call(scope);
},
onErrorFn = function() {
cleanupScriptElement(script);
onError.call(scope);
};
// if the script is already loaded, don't load it again
if (document.getElementById(id) !== null) {
onLoadFn();
return;
}
script.type = 'text/javascript';
script.src = url;
script.onload = onLoadFn;
script.onerror = onErrorFn;
script.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
onLoadFn();
}
};
documentHead.appendChild(script);
return script;
}
var error = function() {
console.log('error occurred');
}
var init = function() {
console.log('should not get run till the script is fully loaded');
}
injectScriptElement('myScriptElem', 'http://www.example.com/script.js', init, error, this);
From looking at the source it seems to me that you could do it in a bit of a hackish way. Try using Ext.Loader.setPath() to map a bogus namespace to your third party javascript files, and then use Ext.Loader.require() to try to load them. It doesn't look like ExtJS actually checks if required class is defined in the file included.