How can I interact with the user inside a CasperJS/PhantomJS script? - phantomjs

Imagine a script like
system = require "system"
system.stdout.write "What's your name? "
name = system.stdin.readLine()
system.stdout.writeLine "Hello, #{name}"
To be run via
casperjs name.coffee
I'd like to be able to interact with the user in the terminal used to run the script, but I get stuck in the readLine() call.

As GarethOwen pointed out, it is indeed possible.
Here is a very basic CasperJS implementation of the Unix command cat:
var system = require('system'),
casper = require('casper').create();
while (!system.stdin.atEnd()) {
var line = system.stdin.readLine();
casper.log(line);
}
casper.exit();
Note that this module is mostly implemented in C++:
https://github.com/ariya/phantomjs/blob/master/src/system.h
And that stdin / stdout / stderr are instances of the PhantomJs class File :
https://github.com/ariya/phantomjs/blob/master/src/filesystem.h

According to the documentation, phantomJS can communicate with standard input. See this example:
https://github.com/ariya/phantomjs/blob/master/examples/stdin-stdout-stderr.js
Documentation regarding inter-process communication is here:
https://github.com/ariya/phantomjs/wiki/Inter-Process-Communication
But I've never tried it myself.

Related

Karate CLI Testing - Execute Command within context of another Command

I'm currently testing a CLI app written by a developer in my team - specifically this command:
./mycli init
After entering this command, it responds with this:
Enter endpoint:
As suggested, I need to provide the target URL, then hit enter.
I'll then be asked 2 more questions which require input.
For example, let's say I have this:
* def listener =
"""
function(line) {
if (line.contains('Enter endpoint')) {
//input the answer
}
}
"""
* def initCmd = karate.fork({ args: ['sh','mycli','init'], listener: listener })
* print initCmd.sysOut
(NB: This snippet was inspired by fork-listener.feature and this interesting thread with jbang team https://github.com/karatelabs/karate/issues/1191)
Karate is working really well for all the other tests I need to do for this CLI - is there something I can put in the IF statement for this particular use case?

Code coverage in SimpleTest

Is there any way to generate code coverage report when using SimpleTest similar to PHPUnit.
I have read the documentation of SimpleTest on their website but can not find a clear way on how to do it!
I came across this website that says
we can add require_once (dirname(__FILE__).'/coverage.php')
to the intended file and it should generate the report, but it did not work!
If there is a helpful website on how to generate code coverage, please share it here.
Thanks alot.
I could not get it to work in the officially supported way either, but here is something I got working that I was able to hack together by examining their code. This works for v1.1.7 of SimpleTest, not their master code. At the time of this writing v1.1.7 is the latest release, and works with new versions of PHP 7, even though it is an old release.
First off you have to make sure you have Xdebug installed, configured, and working. On my system there is both a CLI and Apache version of the php.ini file that have to be configured properly depending on if I am trying to use PHP through Apache or just directly from the terminal. There are alternatives to Xdebug, but most people us Xdebug.
Then, you have to make the PHP_CodeCoverage library accessible from your code. I recommend adding it to your project as a composer package.
Now you just have to manually use that library to capture code coverage and generate a report. How exactly you do that will depend on how you run your tests. Personally, I run my tests on the terminal, and I have a bootstrap file that php runs before it starts the script. At the end of the bootstrap file, I include the SimpleTest autorun file so it will automatically run the tests in any test classes that get included like so:
require_once __DIR__.'/vendor/simpletest/simpletest/autorun.php';
Somewhere inside your bootstrap file you will need to create a filter, whitelist the directories and files you want to get reported, create a coverage object and pass in the filter to the constructor, start coverage, and create and register a shutdown function that will change the way SimpleTest executes the tests to make sure it also stops the coverage and generates the coverage report. Your bootstrap file might look something like this:
<?php
require __DIR__.'/vendor/autoload.php';
$filter = new \SebastianBergmann\CodeCoverage\Filter();
$filter->addDirectoryToWhitelist(__DIR__."/src/");
$coverage = new \SebastianBergmann\CodeCoverage\CodeCoverage(null, $filter);
$coverage->start('<name of test>');
function shutdownWithCoverage($coverage)
{
$autorun = function_exists('\run_local_tests'); // provided by simpletest
if ($autorun) {
$result = \run_local_tests(); // this actually runs the tests
}
$coverage->stop();
$writer = new \SebastianBergmann\CodeCoverage\Report\Html\Facade;
$writer->process($coverage, __DIR__.'/tmp/code-coverage-report');
if ($autorun) {
// prevent tests from running twice:
exit($result ? 0 : 1);
}
}
register_shutdown_function('\shutdownWithCoverage', $coverage);
require_once __DIR__.'/vendor/simpletest/simpletest/autorun.php';
It took me some time to figure out, as - to put it mildly - the documentation for this feature is not really complete.
Once you have your test suite up and running, just include these lines before the lines that are actually running it:
require_once ('simpletest/extensions/coverage/coverage.php');
require_once ('simpletest/extensions/coverage/coverage_reporter.php');
$coverage = new CodeCoverage();
$coverage->log = 'coverage/log.sqlite'; // This folder should exist
$coverage->includes = ['.*\.php$']; // Modify these as you wish
$coverage->excludes = ['simpletest.*']; // Or it is even better to use a setting file
$coverage->maxDirectoryDepth = '1';
$coverage->resetLog();
$coverage->startCoverage();
Then run your tests, for instance:
$test = new ProjectTests(); //It is an extension of the class TestSuite
$test->run(new HtmlReporter());
Finally generate your reports
$coverage->stopCoverage();
$coverage->writeUntouched();
$handler = new CoverageDataHandler($coverage->log);
$report = new CoverageReporter();
$report->reportDir = 'coverage/report'; // This folder should exist
$report->title = 'Code Coverage Report';
$report->coverage = $handler->read();
$report->untouched = $handler->readUntouchedFiles();
$report->summaryFile = $report->reportDir . '/index.html';
And that's it. Based on your setup, you might need to make some small adjustment to make it work. For instance, if you are using the autorun.php from simpletest, that might be a bit more tricky.

How to detect browser in Elm

How do I detect the browser from Elm?
Specifically I want to be able to tell if the web app is running on a tablet (Safari on iPad, etc.) or not.
You can use Html.programWithFlags to pass information from Javascript to Elm on initialization.
Assuming you can infer browser from user agent, you could do something like this:
type alias Flags =
{ userAgent : String }
Your init would look like this:
init : Flags -> ( Model, Cmd Msg )
init flags =
...
main =
programWithFlags { init = init, ... }
And from Javascript, you would pass the flags in like this:
var app = Elm.Main.fullscreen({
userAgent: navigator.userAgent
});
Side note: User agent may not be enough to fully detect browser. You can see this StackOverflow answer which provides more reliable detection. Either way, the end result is that you would send some kind of flag along to the Elm app on init.
More info on Flags can be found here.
You can use elm-vendor package.
http://package.elm-lang.org/packages/coreytrampe/elm-vendor/latest

IntelliJ and xDebug - xdebug.file_link_format

I've searched much time about IntelliJ IDEA 12 and the xdebug.file_link_format configuration value.
I found nothing which works...
Using protocols like "idea", "intellij", "txmt", or other protocols doesn't work.
I found nothing about a plugin which register the IntelliJ protocol...
Is it possible to use the xdebug file links with IntelliJ IDEA or PhpStorm?
Yes and No.
No -- there is no proper built-in support for this. Watch this ticket for details: http://youtrack.jetbrains.com/issue/IDEA-65879
Yes -- you may find some workaround, at very least the aforementioned ticket has recipes for Mac OS (using AppleScript) or via Remote Call etc.
Update: as of PhpStorm 8 you may use:
xdebug.file_link_format = "phpstorm://open?file=%f&line=%l"
Not out of the box, but it is possible to get the links to work. I have this working with Windows 7, Firefox and PhpStorm 10 - in this example, I'm using the protocol phpstorm://, but this will work regardless of the name.
create a custom protocol handler: Any executable will do, here I have modified a WScript from https://pla.nette.org/en/how-open-files-in-ide-from-debugger . Save as run-editor.js :
// note: edit the path, with backslashes escaped
var editor = '"c:\\Program Files (x86)\\JetBrains\\PhpStorm 143.434\\bin\\PhpStorm.exe" nosplash --line %line% "%file%"';
var url = WScript.Arguments(0);
var match = /^phpstorm:\/\/open\/\?file=(.+)&line=(\d+)$/.exec(url);
if (match) {
var file = decodeURIComponent(match[1]).replace(/\+/g, ' ');
var command = editor.replace(/%line%/g, match[2]).replace(/%file%/g, file);
var shell = new ActiveXObject("WScript.Shell");
shell.Exec(command.replace(/\\/g, '\\\\'));
}
create the protocol in registry: create the following as editor.reg and import to Registry. Note that you again need to double-escape the path to the above file, and set it to wherever yours is saved:
REGEDIT4
[HKEY_CLASSES_ROOT\phpstorm]
#="URL:phpstorm Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\phpstorm\shell\open\command]
#="wscript \"C:\\path\\to\\run-editor.js\" \"%1\""
enable the protocol in Firefox:
in about:config, create a "logical value" named
network.protocol-handler.expose.phpstorm and set it to false
open one such link in Firefox, e.g. phpstorm://open?file=somefile.html&line=123 - it should open in PhpStorm.
Per the comment from #gapple, this will make Xdebug link to the file/link in PhpStorm:
xdebug.file_link_format = "phpstorm://open?file=%f&line=%l"
I tested this in PhpStorm 10 on Mac and it works great.
You need to ad to the php.ini file in the [xdebug] section the following line:
xdebug.file_link_format = "phpstorm://open?file=%f&line=%l"
Then restart your web server (Apache for me on Mac)
The REST API is probably the best option now:
http://localhost:63342/api/file%f:%l
Wrapping in a javascript protocol and AJAX request allows the permission approval to be saved so you don't have to approve every time you click:
javascript: var r = new XMLHttpRequest; r.open('get', 'http://localhost:63342/api/file%f:%l');r.send()
API specs:
https://www.develar.org/idea-rest-api/

Google Apps Script ScriptDb permissions issue

I am having an issue trying to query the ScriptDb of a resource file in Google Apps Script. I create a script file (file1), add it as a resource to another script file (file2). I call file1 from file2 to return a handle to its ScriptDb. This works fine. I then try to query the ScriptDb but have a permissions error returned.
Both files owned by same user and in same google environment
See code below:
file 1:
function getMyDb() {
return ScriptDb.getMyDb;
}
file 2 (references file1):
function getDataFromFile1() {
var db = file1.getMyDb(); // This works
var result = db.query({..............}); // This results in a permissions error!
}
I am at a loss to understand why I can access file1 and get back a handle on the ScriptDb, but then am not able to query it, due to an permissions issue.
I have tried to force file1 to require re-authorization, but have not yet been successful. I tried adding a new function and running it, so any suggestions there would be gratefully received.
Thanks in advance
Chris
There appears to be an error in file1/line2. It says "return ScriptDb.getMyDb;" but it should say "return ScriptDb.getMyDb();"
If you leave out the ()s then when you call file1 as a library, file1.getMyDb() will return a function which you store in var db. Then the line var result = db.query({..............}) results in an error because there is no method "query" in the function.
Is that what's causing your error?
I have figured out what the problem was, a misunderstanding on my part regarding authorisation. I was thinking of it in terms of file permissions, when in fact that problem was that my code was not authorised to run the DbScript service. As my code calls a different file and receives back a pointer to a ScriptDb database it is not using the ScriptDb service, so then when it calls the db.query() it invokes the ScriptDb service, for which it is not authorised.
To resolve this I just had to create a dummy function and make a ScriptDb.getMyDb() call, which triggered authorisation for the service. The code then worked fine.
Thanks for the input though.
Chris