I successfully created a script using phantomjs-node in local and I would like to host on OpenShift.
The thing is when I run my script hosted, I had this strange error:
phantom stderr: execvp(): No such file or directory phantomjs-node:
You don't have 'phantomjs' installed
But as you can see, I put the dependancies in the package.json file:
"dependencies": {
"express": "~3.4.4",
"phantom": "*",
"phantomjs": "*"
},
Any suggestions?
Edit:
This is how I initialize the phantomjs script:
var options = {
port: 16000,
hostname: "127.2.149.1",
path: "/phantom_path/"
}
phantom.create(function(ph) {
visitUrl(ph, 0, 0);
}, options);
The error message You don't have 'phantomjs' installed is an internal error from the phantomjs-node module. I ran into this error myself, and I managed to fix it like this:
var phantom = require('phantom');
var options = {
path: '/usr/local/bin/'
};
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open("http://www.google.com", function (status) {
console.log("opened google? ", status);
page.evaluate(function () { return document.title; }, function (result) {
console.log('Page title is ' + result);
ph.exit();
});
});
});
}, options);
Notice the options being passed to the phantom.create() method. The path option should be the full path to the directory that contains your phantomjs binary.
Phantomjs-node is looking for Phantomjs on the PATH of your Open Shift environment and cannot find it. Look for a way to add Phantomjs on this PATH.
Related
I'm looking for an approach to accessing assets in the /assets/ folder that is used to build the content in a component when prerendering an application. I'm using Angular 14 and the #nguniversal/express-engine package. I can't seem to get static assets to be read in the app when running npm run prerender.
I've seen the discussion at #858 however as the last comment points out this won't work when prerendering.
I have a minimal example of what I mean here:
https://stackblitz.com/edit/angular-ivy-dxb32y?file=src%2Fapp%2Fapp.service.ts
You see my service turns the path into an absolute URL:
public getContents(path: string): Observable<string> {
if (isPlatformServer(this.platformId) && path.includes('./')) {
path = `http://localhost:4200/${path.replace('./', '')}`
}
return this.http.get(path, {
observe: 'body',
responseType: 'text',
});
}
And the ssr:dev command serves this content correctly.
However, under prerender I get the following error:
⠸ Prerendering 1 route(s) to C:\Users\***\preloading\dist\preloading\browser...ERROR HttpErrorResponse {
headers: HttpHeaders {
normalizedNames: Map(0) {},
lazyUpdate: null,
headers: Map(0) {}
},
status: 0,
statusText: 'Unknown Error',
url: 'http://localhost:4200/assets/file.txt',
ok: false,
name: 'HttpErrorResponse',
message: 'Http failure response for http://localhost:4200/assets/file.txt: 0 Unknown Error',
I've tried a few things, such as:
Turning the relative URLs into absolute URLs (https://github.com/angular/universal/issues/858) however this doesn't work during prerender
Using fs to read the static assets however these node modules can't be found during the prerender stage:
if (isPlatformServer(this.platformId) && path.includes('./')) {
import("fs")
path = `http://localhost:4200/${path.replace('./', '')}`
}
Gives:
✔ Browser application bundle generation complete.
⠦ Generating server application bundles (phase: sealing)...
./src/app/app.service.ts:14:8-20 - Error: Module not found: Error: Can't resolve 'fs' in 'C:\Users\***\preloading\src\app'
Error: src/app/app.service.ts:12:14 - error TS2307: Cannot find module 'fs' or its corresponding type declarations.
12 import("fs")
Any other ideas at all about what I can do?
So I managed to crack this using the relatively hacky solution of running both ng serve and npm run prerender using a node script:
https://stackblitz.com/edit/angular-ivy-uy7wy9?file=prerender.js
var error = false;
function sleep(miliseconds) {
console.log(`Sleeping for ${miliseconds} ms`);
if (miliseconds == 0)
return Promise.resolve();
return new Promise(resolve => setTimeout(() => resolve(), miliseconds))
}
async function run() {
try {
console.log("Running Angular server");
var proc = require('child_process').spawn('ng', ['serve']);
await sleep(20000)
console.log("Running prerender");
var prerender = require('child_process').spawn('npm', ['run', 'prerender']);
var prerenderTimeoutSeconds = 120;
var timeoutObject;
var timeoutResolve;
var timeoutReject;
var timeout = new Promise((resolve, reject) => {
timeoutResolve = resolve;
timeoutReject = reject;
timeoutObject = setTimeout(() => {
console.log('Timed out, killing prerender');
try {
prerender.kill("SIGKILL")
reject(Error("Timed out running prerender"))
} catch (e) {
console.error(e)
reject(Error('Cannot kill prerender'));
}
}, prerenderTimeoutSeconds * 1000)
});
prerender.stdout.on('data', (data) => {
console.log(`prerender stdout: ${data}`);
});
prerender.stderr.on('data', (data) => {
console.error(`prerender stderr: ${data}`);
});
prerender.on('close', (code) => {
clearTimeout(timeoutObject);
console.log(`prerender exited with code ${code}`)
if (code === 0) {
timeoutResolve()
} else {
timeoutReject(Error(`prerender exited with code ${code}`));
}
});
await timeout
} catch (err) {
console.error(err);
console.error(err.stack);
error = true;
} finally {
if (proc) {
console.log("Killing Angular server");
var angularKilled = proc.kill("SIGKILL")
console.log(`kill -9 on Angular success [${angularKilled}]`)
}
}
}
(async () => await run())();
if (error) {
throw new Error("Exception during execution")
}
I am currently trying to write a gulp task that allows me to serve development code up through a node webserver and use browser sync to reload the page. In doing so i'm attempting to use the events with nodemon, so for example when start event occurs, I want my gulp to log what its starting. Currently the events for gulp nodemon are not firing at all. No error is being thrown and the web server is starting. I'm not sure what I am doing wrong.
gulp.task('serve-dev', ['inject'], function(){
var isDev = true;
var nodeOptions = {
script: config.nodeServer,
delayTime: 1,
env: {
'PORT': port,
'NODE_ENV': isDev ? 'dev': 'build'
},
watch: ['server.js']
};
$.nodemon(nodeOptions)
.on('start', function(){
log('*** nodemon started');
// startBroswerSync();
})
.on('restart', function (ev){
log('*** nodemon restarted');
log('files changed on restart:\n' + ev);
})
.on('crash', function(){
log('Server Crashed for some reason');
})
.on('exit', function(){
log('Server Ended Cleanly');
})
Here is my config File:
module.exports = function() {
var client = './src/';
var temp = './.tmp/';
var server = './server.js';
var config = {
// Location of index.html
index: client + 'index.html',
// Temp folder
temp: temp,
// All of the js files to load
js: [
client + '**/*.module.js',
client + '**/*.js',
'!' + client + '**/*.spec.js'
],
// Root Folder of App(Where to find index.html etc...)
client: client,
// Where to find build Sass and CSS files
css: [temp + '*css', client + 'css/*.css'],
// All Js to Vet
alljs: [
'./src/**/*.js',
'./*js'
],
// Path to Node Server
server: server,
//Sass to Compile
sass: ['src/scss/*.scss'],
// Bower and NPM Locations
bower: {
json: require('./bower.json'),
directory: './bower_components/',
ignorePath: '../..'
},
// Node Settings
defaultPort: 7203,
nodeServer: './server.js'
};
config.getWiredepDefaultOptions = function() {
var options = {
bowerJson: config.bower.json,
directory: config.bower.directory,
ignorePath: config.bower.ignorePath
};
return options;
};
return config;
};
Completely Unrelated answer, log method was not functioning properly, thus no log statements....sorry
I am trying to run karma tests from gulp task and I am getting this error:
Error: 1
at formatError (C:\Users\Tim\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:161:10)
at Gulp.<anonymous> (C:\Users\Tim\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:187:15)
at Gulp.emit (events.js:95:17)
at Gulp.Orchestrator._emitTaskDone (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\index.js:264:8)
at C:\path\to\project\node_modules\gulp\node_modules\orchestrator\index.js:275:23
at finish (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\lib\runTask.js:21:8)
at cb (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\lib\runTask.js:29:3)
at removeAllListeners (C:\path\to\project\node_modules\karma\lib\server.js:216:7)
at Server.<anonymous> (C:\path\to\project\node_modules\karma\lib\server.js:227:9)
at Server.g (events.js:180:16)
My system is Windows 7, nodejs version is v0.10.32, gulp version:
[10:26:52] CLI version 3.8.8
[10:26:52] Local version 3.8.9
Also, the same error I am getting on Ubuntu 12.04 LTS while on newer Ubuntu (not sure what version) and mac os it is seems to be working ok. What can cause this error?
Update 5/11/2016: Before writing comment about the fact that accepted answer hide errors, please, see first two comments to that particular accepted answer. Use it only if know what you are doing. Related info: https://github.com/karma-runner/gulp-karma/pull/15
How are you running your tests with Gulp? I came up against this issue recently on OSX, running node v0.11.14 and gulp 3.8.10, whenever there were failing tests.
Changing from the recommended:
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done);
});
To:
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function() {
done();
});
});
...got rid of this error.
Seems to be down to how gulp handles error messages when an error is signalled in a callback. See Improve error messages on exit for more information.
None of these solutions worked correctly for me using gulp 3.9.1 and karma 1.1.1. Adding a reference to gulp-util npm install --save-dev gulp-util and updating the task to the below fix the error output very nicely, while maintaining exit status correctly.
var gutil = require('gulp-util');
gulp.task('test', function (done) {
new Server({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(err){
if(err === 0){
done();
} else {
done(new gutil.PluginError('karma', {
message: 'Karma Tests failed'
}));
}
}).start();
});
Below is a code snippet from gulp patterns on using Karma. It's a bit similar, but also uses the newer method how to start the karma.
/**
* Start the tests using karma.
* #param {boolean} singleRun - True means run once and end (CI), or keep running (dev)
* #param {Function} done - Callback to fire when karma is done
* #return {undefined}
*/
function startTests(singleRun, done) {
var child;
var excludeFiles = [];
var fork = require('child_process').fork;
var KarmaServer = require('karma').Server;
var serverSpecs = config.serverIntegrationSpecs;
if (args.startServers) {
log('Starting servers');
var savedEnv = process.env;
savedEnv.NODE_ENV = 'dev';
savedEnv.PORT = 8888;
child = fork(config.nodeServer);
} else {
if (serverSpecs && serverSpecs.length) {
excludeFiles = serverSpecs;
}
}
var server = new KarmaServer({
configFile: __dirname + '/karma.conf.js',
exclude: excludeFiles,
singleRun: singleRun
}, karmaCompleted);
server.start();
////////////////
function karmaCompleted(karmaResult) {
log('Karma completed');
if (child) {
log('shutting down the child process');
child.kill();
}
if (karmaResult === 1) {
done('karma: tests failed with code ' + karmaResult);
} else {
done();
}
}
}
What worked for me and gave a nice formatted error message is to provide an Error instance to the done callback.
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(result) {
if (result > 0) {
return done(new Error(`Karma exited with status code ${result}`));
}
done();
});
});
If you want to return with an error code, and want to see Karma's error output but not Gulp's (probably unrelated) stack trace:
gulp.task('test', function() {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(karmaExitStatus) {
if (karmaExitStatus) {
process.exit(1);
}
});
});
Not sure about Ubuntu, but I was getting a similar error on Windows, and installing one version back fixed it right away like this:
npm install -g gulp#3.8.8
npm install gulp#3.8.8
this is gulp's way of telling your tests have failed and that karma exited with a return code of 1. Why you would want to call done yourself and not pass the error as a message baffles me.
The right way to solve this according to Karma's documentation and https://github.com/pkozlowski-opensource, is to rely on Karma's watch mechanism rather than Gulp's:
gulp.task('tdd', function (done) {
karma.start({
configFile: __dirname + '/karma.conf.js'
}, done);
});
Note the omission of singleRun: true.
#McDamon's workaround will work for gulp.watch, but you don't want to swallow exit codes like that when running on a CI server.
Gulp is also reworking how they handle exit codes in scenarios just like this one. See https://github.com/gulpjs/gulp/issues/71 and the other dozen or so related issues.
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: false
}, done);
});
passing singleRun: false argument will prevent the process from returning a value different of 0 (which would signify an error and exit gulp).
Run with singleRun: true if you only launching your test from a command line, not part of a continuous integration suite.
In case anyone else comes here, do not use the accepted solution. It will hide failed tests. If you need a quick solution to modify your gulp test task, you can use the solution found in this comment in this github thread.
gulp.src(src)
// pipeline...
.on('error', function (error) {
console.error('' + error);
});
This error is so common but although I searched a lot of similar questions I did not found a solution to my problem. I installed the module with no problems using "npm install db".
The "server.js" is in the same folder as"node_moludes" and NPM created a "db" folder inside "node_moludes" with all the content.
All NPM commands return success (install, link, list etc), I even added the module to my "package.json" and it also installs with no problem just using "npm install -d".
Despite it all, when I run the server, Nodejs can't find the 'db' module... any help?
nodejs version: 0.10.26
npm version: 1.4.3
server.js
var http = require('http'),
url = require('url'),
db = require('db');
var send = function(response, data){
response.writeHead(200, {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin': '*'
});
response.end(JSON.stringify({data: data}));
};
http.createServer(function (request, response) {
var query = url.parse(request.url, true).query;
if(query.set) {
db.set(query.set, query.val || '');
send(response, true);
} else if (query.get) {
db.get(query.get, function(data){
send(response, data);
});
} else send(response, query);
}).listen(80);
package.json
{
"name": "xxxxx",
"version": "0.0.1",
"author": "rafaelcastrocouto",
"repository": "git://github.com/rafaelcastrocouto/xxxxx",
"dependencies": {
"db": ">= 1.00.x"
},
"engine": "node >= 0.10.x"
}
It appears the db module was setup without following some Node.js norms. It doesn't contain an index.* file or specify a "main" setting in its package.json to direct Node otherwise.
You should be able to reference the main file within the package directly:
var db = require('db/db');
I'm trying to execute a basic app that uses RequireJS (2.1.8), WireJS (0.10.2) and PhantomJS (1.9.2):
When running the app using PhantomJS (this is my goal), WireJS fails to load (see error below).
When running the app using Chrome, it completes properly.
Please help to point out the missing part for WireJS to run properly under PhantomJS.
Following are my app files.
1) app.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SaphirJS.core</title>
<script data-main="app" src="../../../target/deps/require-0.0.1/2.1.8/require.js"> </script>
</head>
<body>
</body>
</html>
2) app.js
"use strict";
require.config({
baseUrl: ".",
packages: [
{ name: 'wire', location: '../../../target/deps/wire-0.0.1/0.10.2', main: 'wire' },
{ name: 'when', location: '../../../target/deps/when-0.0.1/2.4.1', main: 'when' },
{ name: 'meld', location: '../../../target/deps/meld-0.0.1/1.3.0', main: 'meld' }
]
});
require(["wire!wireContext"], function(wireContext) {
alert(wireContext.message);
});
3) wireContext.js
define({
message: "Hello World!"
});
4) phantom-runner.js
(function() {
'use strict';
var args = require('system').args,
timeoutRef = undefined,
timeLimit = 10000;
// arg[0]: scriptName, args[1...]: arguments
if (args.length !== 2) {
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite]');
phantom.exit(1);
}
var url = args[1],
page = require('webpage').create();
// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onInitialized = function() {
timeoutRef = setTimeout(function(){
console.error('Test Run Failed. Timeout Exceeded. Took longer than '+ timeLimit / 1000 +' seconds.');
phantom.exit(1);
}, timeLimit);
};
page.onAlert = function(message) {
clearTimeout(timeoutRef);
phantom.exit(0);
};
page.open(url, function(status) {
if (status !== 'success') {
console.error('Unable to access network: ' + status);
phantom.exit(1);
}
});
})();
5) The error when running the app under PhantomJS
TypeError: 'undefined' is not a function (evaluating 'Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty)')
<path-to-deps>/wire-0.0.1/0.10.2/lib/object.js:13
<path-to-deps>/require-0.0.1/2.1.8/require.js:1635
<path-to-deps>/require-0.0.1/2.1.8/require.js:871
<path-to-deps>/require-0.0.1/2.1.8/require.js:1142
<path-to-deps>/require-0.0.1/2.1.8/require.js:779
<path-to-deps>/require-0.0.1/2.1.8/require.js:1169 in callGetModule
<path-to-deps>/require-0.0.1/2.1.8/require.js:1529
<path-to-deps>/require-0.0.1/2.1.8/require.js:1656
Error: Load timeout for modules: wire!wireContext_unnormalized2
http://requirejs.org/docs/errors.html#timeout
<path-to-deps>/require-0.0.1/2.1.8/require.js:138 in defaultOnError
<path-to-deps>/require-0.0.1/2.1.8/require.js:536 in onError
<path-to-deps>/require-0.0.1/2.1.8/require.js:691 in checkLoaded
<path-to-deps>/require-0.0.1/2.1.8/require.js:710
Test Run Failed. Timeout Exceeded. Took longer than 10 seconds.
You are right, Younes. PhantomJS doesn't support Function.prototype.bind for some reason.
You can polyfill Function.prototype.bind by using either cujoJS/poly or kriskowal/es5-shim.
As mentioned in the comments to the question, the origin of this problem is the fact that PhantomJS doesn't implement 'Function.prototype.bind()' function.
As suggested by the people from PhantomJS and WireJS, the problem would be fixed using an ES5 polyfill. The implementation suggested by MDN didn't help as it is a partial implementation of the specs. The implementation included in CujoJS/PolyJS has solved my problem. Now, WireJS is happy with PhantomJS.
Hereinafter is the new version of app.js
"use strict";
require.config({
baseUrl: ".",
packages: [
{ name: 'wire', location: '../../../target/deps/wire-0.0.1/0.10.2', main: 'wire' },
{ name: 'when', location: '../../../target/deps/when-0.0.1/2.4.1', main: 'when' },
{ name: 'meld', location: '../../../target/deps/meld-0.0.1/1.3.0', main: 'meld' },
{ name: 'poly', location: '../../../target/deps/poly-0.0.1/0.5.2', main: 'poly' }
]
});
require(["poly/function", "wire!appWireContext"], function(poly, wireContext) {
alert(wireContext.message);
});
Cheers