Kill PhantomShim. (#533)

This patch kills PhantomShim, a lightweight layer that helped to
bootstrap Puppeteer API.

At this point, PhantomShim:
- passes 139 phantomJS tests
- fails 13 tests
- lacks capabilities to run 26

The failings and unsupported tests don't have any value for Puppeteer
API, so it doesn't make sense to maintain PhantomShim any longer.
This commit is contained in:
Andrey Lushnikov 2017-08-25 15:15:34 -07:00 committed by GitHub
parent 2c4dfbfd88
commit e8f8a1ad1f
216 changed files with 0 additions and 21793 deletions

View File

@ -1,7 +1,3 @@
# exclude phantomjs tests
third_party/phantomjs/
# exclude phantom_shim project
phantom_shim
# exclude all tests
test
utils/node6-transform

View File

@ -15,7 +15,6 @@ install:
script:
- 'if [ "$NODE7" = "true" ]; then yarn run lint; fi'
- 'if [ "$NODE7" = "true" ]; then yarn run coverage; fi'
- 'if [ "$NODE7" = "true" ]; then yarn run test-phantom; fi'
- 'if [ "$NODE6" = "true" ]; then yarn run node6; fi'
- 'if [ "$NODE6" = "true" ]; then yarn run test-node6; fi'
- 'if [ "$NODE6" = "true" ]; then yarn run node6-sanity; fi'

View File

@ -10,7 +10,6 @@
"scripts": {
"unit": "jasmine test/test.js",
"debug-unit": "DEBUG_TEST=true node --inspect-brk ./node_modules/.bin/jasmine test/test.js",
"test-phantom": "python third_party/phantomjs/test/run-tests.py",
"test-doclint": "jasmine utils/doclint/check_public_api/test/test.js && jasmine utils/doclint/preprocessor/test.js",
"test": "npm run lint --silent && npm run coverage && npm run test-phantom && npm run test-doclint && npm run test-node6",
"install": "node install.js",

View File

@ -1,375 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const path = require('path');
const fs = require('fs');
const deasync = require('deasync');
const removeRecursive = require('rimraf').sync;
const copyRecursive = deasync(require('ncp').ncp);
class FileSystem {
constructor() {
this.separator = path.sep;
}
/**
* @return {string}
*/
get workingDirectory() {
return process.cwd();
}
/**
* @param {string} directoryPath
*/
changeWorkingDirectory(directoryPath) {
try {
process.chdir(directoryPath);
return true;
} catch (e){
return false;
}
}
/**
* @param {string} relativePath
* @return {string}
*/
absolute(relativePath) {
relativePath = path.normalize(relativePath);
if (path.isAbsolute(relativePath))
return relativePath;
return path.resolve(path.join(process.cwd(), relativePath));
}
/**
* @param {string} filePath
* @return {boolean}
*/
exists(filePath) {
return fs.existsSync(filePath);
}
/**
* @param {string} fromPath
* @param {string} toPath
*/
copy(fromPath, toPath) {
const content = fs.readFileSync(fromPath);
fs.writeFileSync(toPath, content);
}
/**
* @param {string} fromPath
* @param {string} toPath
*/
move(fromPath, toPath) {
const content = fs.readFileSync(fromPath);
fs.writeFileSync(toPath, content);
fs.unlinkSync(fromPath);
}
/**
* @param {string} filePath
* @return {number}
*/
size(filePath) {
return fs.statSync(filePath).size;
}
/**
* @param {string} filePath
*/
touch(filePath) {
fs.closeSync(fs.openSync(filePath, 'a'));
}
/**
* @param {string} filePath
*/
remove(filePath) {
fs.unlinkSync(filePath);
}
/**
* @param {string} filePath
* @return {boolean}
*/
lastModified(filePath) {
return fs.statSync(filePath).mtime;
}
/**
* @param {string} dirPath
* @return {boolean}
*/
makeDirectory(dirPath) {
try {
fs.mkdirSync(dirPath);
return true;
} catch (e) {
return false;
}
}
/**
* @param {string} dirPath
* @return {boolean}
*/
makeTree(dirPath) {
return this.makeDirectory(dirPath);
}
/**
* @param {string} dirPath
*/
removeTree(dirPath) {
removeRecursive(dirPath);
}
/**
* @param {string} fromPath
* @param {string} toPath
*/
copyTree(fromPath, toPath) {
copyRecursive(fromPath, toPath);
}
/**
* @param {string} dirPath
* @return {!Array<string>}
*/
list(dirPath) {
return fs.readdirSync(dirPath);
}
/**
* @param {string} linkPath
* @return {string}
*/
readLink(linkPath) {
return fs.readlinkSync(linkPath);
}
/**
* @param {string} filePath
* @param {Object} data
* @param {string} mode
*/
write(filePath, data, mode) {
const fd = new FileDescriptor(filePath, mode, 'utf8');
fd.write(data);
fd.close();
}
/**
* @param {string} somePath
* @return {boolean}
*/
isAbsolute(somePath) {
return path.isAbsolute(somePath);
}
/**
* @return {string}
*/
read(filePath) {
return fs.readFileSync(filePath, 'utf8');
}
/**
* @param {string} filePath
* @return {boolean}
*/
isFile(filePath) {
return fs.existsSync(filePath) && fs.lstatSync(filePath).isFile();
}
/**
* @param {string} dirPath
* @return {boolean}
*/
isDirectory(dirPath) {
return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
}
/**
* @param {string} filePath
* @return {boolean}
*/
isLink(filePath) {
return fs.existsSync(filePath) && fs.lstatSync(filePath).isSymbolicLink();
}
/**
* @param {string} filePath
* @return {boolean}
*/
isReadable(filePath) {
try {
fs.accessSync(filePath, fs.constants.R_OK);
return true;
} catch (e) {
return false;
}
}
/**
* @param {string} filePath
* @return {boolean}
*/
isWritable(filePath) {
try {
fs.accessSync(filePath, fs.constants.W_OK);
return true;
} catch (e) {
return false;
}
}
/**
* @param {string} filePath
* @return {boolean}
*/
isExecutable(filePath) {
try {
fs.accessSync(filePath, fs.constants.X_OK);
return true;
} catch (e) {
return false;
}
}
/**
* @param {string} somePath
* @return {!Array<string>}
*/
split(somePath) {
somePath = path.normalize(somePath);
if (somePath.endsWith(path.sep))
somePath = somePath.substring(0, somePath.length - path.sep.length);
return somePath.split(path.sep);
}
/**
* @param {string} path1
* @param {string} path2
* @return {string}
*/
join(...args) {
if (args[0] === '' && args.length > 1)
args[0] = path.sep;
args = args.filter(part => typeof part === 'string');
return path.join.apply(path, args);
}
/**
* @param {string} filePath
* @param {(string|!Object)} option
* @return {!FileDescriptor}
*/
open(filePath, option) {
if (typeof option === 'string')
return new FileDescriptor(filePath, option);
return new FileDescriptor(filePath, option.mode);
}
}
const fdwrite = deasync(fs.write);
const fdread = deasync(fs.read);
class FileDescriptor {
/**
* @param {string} filePath
* @param {string} mode
*/
constructor(filePath, mode) {
this._position = 0;
this._encoding = 'utf8';
if (mode === 'rb') {
this._mode = 'r';
this._encoding = 'latin1';
} else if (mode === 'wb' || mode === 'b') {
this._mode = 'w';
this._encoding = 'latin1';
} else if (mode === 'rw+') {
this._mode = 'a+';
this._position = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0;
} else {
this._mode = mode;
}
this._fd = fs.openSync(filePath, this._mode);
}
/**
* @param {string} data
*/
write(data) {
const buffer = Buffer.from(data, this._encoding);
const written = fdwrite(this._fd, buffer, 0, buffer.length, this._position);
this._position += written;
}
getEncoding() {
return 'UTF-8';
}
/**
* @param {string} data
*/
writeLine(data) {
this.write(data + '\n');
}
/**
* @param {number=} size
* @return {string}
*/
read(size) {
let position = this._position;
if (!size) {
size = fs.fstatSync(this._fd).size;
position = 0;
}
const buffer = new Buffer(size);
const bytesRead = fdread(this._fd, buffer, 0, size, position);
this._position += bytesRead;
return buffer.toString(this._encoding);
}
flush() {
// noop.
}
/**
* @param {number} position
*/
seek(position) {
this._position = position;
}
close() {
fs.closeSync(this._fd);
}
/**
* @return {boolean}
*/
atEnd() {
}
}
module.exports = FileSystem;

View File

@ -1,142 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const url = require('url');
const VERSION = [0, 0, 1];
module.exports.version = VERSION;
/**
* @param {!Object} context
* @param {string} scriptPath
*/
module.exports.create = function(context, scriptPath) {
const phantom = {
page: {
onConsoleMessage: null,
},
/**
* @param {string} relative
* @param {string} base
* @return {string}
*/
resolveRelativeUrl: function(relative, base) {
return url.resolve(base, relative);
},
/**
* @param {string} url
* @return {string}
*/
fullyDecodeUrl: function(url) {
return decodeURI(url);
},
libraryPath: path.dirname(scriptPath),
onError: null,
/**
* @return {string}
*/
get outputEncoding() {
return 'UTF-8';
},
/**
* @param {string} value
*/
set outputEncoding(value) {
throw new Error('Phantom.outputEncoding setter is not implemented');
},
/**
* @return {boolean}
*/
get cookiesEnabled() {
return true;
},
/**
* @param {boolean} value
*/
set cookiesEnabled(value) {
throw new Error('Phantom.cookiesEnabled setter is not implemented');
},
/**
* @return {!{major: number, minor: number, patch: number}}
*/
get version() {
return {
major: VERSION[0],
minor: VERSION[1],
patch: VERSION[2],
};
},
/**
* @param {number=} code
*/
exit: function(code) {
process.exit(code);
},
/**
* @param {string} filePath
* @return {boolean}
*/
injectJs: function(filePath) {
filePath = path.resolve(phantom.libraryPath, filePath);
if (!fs.existsSync(filePath))
return false;
let code = fs.readFileSync(filePath, 'utf8');
if (code.startsWith('#!'))
code = code.substring(code.indexOf('\n'));
vm.runInContext(code, context, {
filename: filePath,
displayErrors: true
});
return true;
},
/**
* @param {string} moduleSource
* @param {string} filename
*/
loadModule: function(moduleSource, filename) {
const code = [
'(function(require, exports, module) {\n',
moduleSource,
'\n}.call({},',
'require.cache[\'' + filename + '\']._getRequire(),',
'require.cache[\'' + filename + '\'].exports,',
'require.cache[\'' + filename + '\']',
'));'
].join('');
vm.runInContext(code, context, {
filename: filename,
displayErrors: true
});
},
};
return phantom;
};

View File

@ -1,21 +0,0 @@
# PhantomShim
PhantomShim is a phantomJS script runner built atop of Puppeteer API.
### Q: Can I use PhantomShim to run my scripts?
No.
PhantomShim aims to pass PhantomJS tests rather then to be a valid PhantomJS script runner:
- PhantomShim shortcuts a lot of corners (e.g. [handling only a few keys](https://github.com/GoogleChrome/puppeteer/blob/4269f6a1bb0c2d1cc27a9ed1132017669c33a259/phantom_shim/WebPage.js#L75) that are necessary to pass tests).
- PhantomShim spawns [nested event loops](https://github.com/abbr/deasync) to emulate PhantomJS execution model. This might result in unpredictable side-effects, e.g. in [unexpected reenterability](https://github.com/GoogleChrome/puppeteer/blob/4269f6a1bb0c2d1cc27a9ed1132017669c33a259/phantom_shim/WebPage.js#L694).
### Q: What's the purpose of PhantomShim?
The goal is to prove comprehensiveness of Puppeteer API.
PhantomShim is built atop of Puppeteer API and is used to run PhantomJS tests.
Whenever PhantomShim can't implement certain capability to pass phantomJS test, Puppeteer API is improved to make it possible.
### Q: Are there plans to evolve PhantomShim into a real PhantomJS script runner?
No.
On the contrary, PhantomShim is likely to be removed from the Puppeteer repository as it passes all interesting PhantomJS tests.

View File

@ -1,118 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const readline = require('readline');
const await = require('./utilities').await;
const os = require('os');
class System {
/**
* @param {!Array<string>} args
*/
constructor(args) {
this.args = args;
this.env = {};
Object.assign(this.env, process.env);
this.stdin = new StandardInput(process.stdin);
this.stdout = new StandardOutput(process.stdout);
this.stderr = new StandardOutput(process.stderr);
this.platform = 'phantomjs';
this.pid = process.pid;
this.isSSLSupported = false;
this.os = {
architecture: os.arch(),
name: os.type(),
version: os.release()
};
}
}
class StandardInput {
/**
* @param {!Readable} readableStream
*/
constructor(readableStream) {
this._readline = readline.createInterface({
input: readableStream
});
this._lines = [];
this._closed = false;
this._readline.on('line', line => this._lines.push(line));
this._readline.on('close', () => this._closed = true);
}
/**
* @return {string}
*/
readLine() {
if (this._closed && !this._lines.length)
return '';
if (!this._lines.length) {
const linePromise = new Promise(fulfill => this._readline.once('line', fulfill));
await(linePromise);
}
return this._lines.shift();
}
/**
* @return {string}
*/
read() {
if (!this._closed) {
const closePromise = new Promise(fulfill => this._readline.once('close', fulfill));
await(closePromise);
}
const text = this._lines.join('\n');
this._lines = [];
return text;
}
close() {
this._readline.close();
}
}
class StandardOutput {
/**
* @param {!Writable} writableStream
*/
constructor(writableStream) {
this._stream = writableStream;
}
/**
* @param {string} data
*/
write(data) {
this._stream.write(data);
}
/**
* @param {string} data
*/
writeLine(data) {
this._stream.write(data + '\n');
}
flush() {
}
close() {
this._stream.end();
}
}
module.exports = System;

View File

@ -1,748 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const await = require('./utilities').await;
const EventEmitter = require('events');
const fs = require('fs');
const path = require('path');
const PageEvents = require('../lib/Page').Events;
const noop = function() { };
class WebPage {
/**
* @param {!Browser} browser
* @param {string} scriptPath
* @param {!Object=} options
*/
constructor(browser, scriptPath, options = {}) {
this._page = await(browser.newPage());
this.settings = new WebPageSettings(this._page);
options.settings = options.settings || {};
if (options.settings.userAgent)
this.settings.userAgent = options.settings.userAgent;
if (options.viewportSize)
await(this._page.setViewport(options.viewportSize));
else
await(this._page.setViewport({width: 400, height: 300}));
this.loading = false;
this.loadingProgress = 0;
this.clipRect = options.clipRect || {left: 0, top: 0, width: 0, height: 0};
this.onConsoleMessage = null;
this.onLoadFinished = null;
this.onResourceError = null;
this.onResourceReceived = null;
this._onInitialized = undefined;
this._deferEvaluate = false;
this._customHeaders = {};
this._currentFrame = this._page.mainFrame();
this.libraryPath = path.dirname(scriptPath);
this._onResourceRequestedCallback = undefined;
this._onConfirmCallback = undefined;
this._onPromptCallback = undefined;
this._onAlertCallback = undefined;
this._onError = noop;
this._pageEvents = new AsyncEmitter(this._page);
this._pageEvents.on(PageEvents.Request, request => this._onRequest(request));
this._pageEvents.on(PageEvents.Response, response => this._onResponseReceived(response));
this._pageEvents.on(PageEvents.RequestFinished, request => this._onRequestFinished(request));
this._pageEvents.on(PageEvents.RequestFailed, event => (this.onResourceError || noop).call(null, event));
this._pageEvents.on(PageEvents.Console, (...args) => this._onConsole(...args));
this._pageEvents.on(PageEvents.Confirm, message => this._onConfirm(message));
this._pageEvents.on(PageEvents.Alert, message => this._onAlert(message));
this._pageEvents.on(PageEvents.Dialog, dialog => this._onDialog(dialog));
this._pageEvents.on(PageEvents.PageError, error => (this._onError || noop).call(null, error.message, error.stack));
this.event = {
key: {
A: 65,
B: 66,
C: 67,
Home: ['Home'],
Delete: ['Delete'],
Backspace: ['Backspace'],
Cut: ['Cut'],
Paste: ['Paste']
},
modifier: {
shift: 'Shift'
}
};
}
/**
* @param {!Array<!Object>} args
*/
_onConsole(...args) {
if (!this.onConsoleMessage)
return;
const text = args.join(' ');
this.onConsoleMessage(text);
}
/**
* @return {string}
*/
currentFrameName() {
return this.frameName;
}
/**
* @return {number}
*/
childFramesCount() {
return this.framesCount;
}
/**
* @return {!Array<string>}
*/
childFramesName() {
return this.framesName;
}
/**
* @param {(string|number)} frameName
* @return {boolean}
*/
switchToChildFrame(frame) {
return this.switchToFrame(frame);
}
/**
* @return {string}
*/
get frameName() {
return this._currentFrame.name();
}
/**
* @return {number}
*/
get framesCount() {
return this._currentFrame.childFrames().length;
}
/**
* @return {!Array<string>}
*/
get framesName() {
return this._currentFrame.childFrames().map(frame => frame.name());
}
/**
* @return {string}
*/
get focusedFrameName() {
const focusedFrame = this._focusedFrame();
return focusedFrame ? focusedFrame.name() : '';
}
/**
* @return {?Frame}
*/
_focusedFrame() {
const frames = this._currentFrame.childFrames().slice();
frames.push(this._currentFrame);
const promises = frames.map(frame => frame.evaluate(() => document.hasFocus()));
const result = await(Promise.all(promises));
for (let i = 0; i < result.length; ++i) {
if (result[i])
return frames[i];
}
return null;
}
switchToFocusedFrame() {
const frame = this._focusedFrame();
this._currentFrame = frame;
}
/**
* @param {(string|number)} frameName
* @return {boolean}
*/
switchToFrame(frameName) {
let frame = null;
if (typeof frameName === 'string')
frame = this._currentFrame.childFrames().find(frame => frame.name() === frameName);
else if (typeof frameName === 'number')
frame = this._currentFrame.childFrames()[frameName];
if (!frame)
return false;
this._currentFrame = frame;
return true;
}
/**
* @return {boolean}
*/
switchToParentFrame() {
const frame = this._currentFrame.parentFrame();
if (!frame)
return false;
this._currentFrame = frame;
return true;
}
switchToMainFrame() {
this._currentFrame = this._page.mainFrame();
}
get cookies() {
return await(this._page.cookies());
}
set cookies(cookies) {
const cookies2 = await(this._page.cookies());
await(this._page.deleteCookie(...cookies2));
await(this._page.setCookie(...cookies));
}
addCookie(cookie) {
await(this._page.setCookie(cookie));
}
deleteCookie(cookieName) {
await(this._page.deleteCookie({name: cookieName}));
}
get onInitialized() {
return this._onInitialized;
}
set onInitialized(value) {
if (typeof value !== 'function')
this._onInitialized = undefined;
else
this._onInitialized = value;
}
/**
* @return {?function(!Object, !Request)}
*/
get onResourceRequested() {
return this._onResourceRequestedCallback;
}
/**
* @return {?function(!Object, !Request)} callback
*/
set onResourceRequested(callback) {
await(this._page.setRequestInterceptionEnabled(!!callback));
this._onResourceRequestedCallback = callback;
}
_onRequest(request) {
if (!this._onResourceRequestedCallback)
return;
const requestData = new RequestData(request);
const phantomRequest = new PhantomRequest();
this._onResourceRequestedCallback.call(null, requestData, phantomRequest);
if (phantomRequest._aborted) {
request.abort();
} else {
request.continue({
url: phantomRequest._url,
headers: phantomRequest._headers,
});
}
}
_onResponseReceived(response) {
if (!this.onResourceReceived)
return;
const phantomResponse = new PhantomResponse(response, false /* isResponseFinished */);
this.onResourceReceived.call(null, phantomResponse);
}
_onRequestFinished(request) {
if (!this.onResourceReceived)
return;
const phantomResponse = new PhantomResponse(request.response(), true /* isResponseFinished */);
this.onResourceReceived.call(null, phantomResponse);
}
/**
* @param {string} url
* @param {function()} callback
*/
includeJs(url, callback) {
this._page.addScriptTag(url).then(callback);
}
/**
* @return {!{width: number, height: number}}
*/
get viewportSize() {
return this._page.viewport();
}
/**
* @return {!Object}
*/
get customHeaders() {
return this._customHeaders;
}
/**
* @param {!Object} value
*/
set customHeaders(value) {
this._customHeaders = value;
await(this._page.setExtraHTTPHeaders(new Map(Object.entries(value))));
}
/**
* @param {string} filePath
*/
injectJs(filePath) {
if (!fs.existsSync(filePath))
filePath = path.resolve(this.libraryPath, filePath);
if (!fs.existsSync(filePath))
return false;
await(this._page.injectFile(filePath));
return true;
}
/**
* @return {string}
*/
get plainText() {
return await(this._page.plainText());
}
/**
* @return {string}
*/
get title() {
return await(this._page.title());
}
/**
* @return {(function()|undefined)}
*/
get onError() {
return this._onError;
}
/**
* @param {(function()|undefined)} handler
*/
set onError(handler) {
if (typeof handler !== 'function')
handler = undefined;
this._onError = handler;
}
/**
* @return {(function()|undefined)}
*/
get onConfirm() {
return this._onConfirmCallback;
}
/**
* @param {function()} handler
*/
set onConfirm(handler) {
if (typeof handler !== 'function')
handler = undefined;
this._onConfirmCallback = handler;
}
/**
* @return {(function()|undefined)}
*/
get onPrompt() {
return this._onPromptCallback;
}
/**
* @param {function()} handler
*/
set onPrompt(handler) {
if (typeof handler !== 'function')
handler = undefined;
this._onPromptCallback = handler;
}
/**
* @return {(function()|undefined)}
*/
get onAlert() {
return this._onAlertCallback;
}
/**
* @param {function()} handler
*/
set onAlert(handler) {
if (typeof handler !== 'function')
handler = undefined;
this._onAlertCallback = handler;
}
/**
* @param {!Dialog} dialog
*/
_onDialog(dialog) {
if (dialog.type === 'alert' && this._onAlertCallback) {
this._onAlertCallback.call(null, dialog.message());
await(dialog.accept());
} else if (dialog.type === 'confirm' && this._onConfirmCallback) {
const result = this._onConfirmCallback.call(null, dialog.message());
await(result ? dialog.accept() : dialog.dismiss());
} else if (dialog.type === 'prompt' && this._onPromptCallback) {
const result = this._onPromptCallback.call(null, dialog.message(), dialog.defaultValue());
await(result ? dialog.accept(result) : dialog.dismiss());
}
}
/**
* @return {string}
*/
get url() {
return await(this._page.url());
}
/**
* @param {string} html
*/
set content(html) {
await(this._page.setContent(html));
}
/**
* @param {string} selector
* @param {(string|!Array<string>)} files
*/
uploadFile(selector, files) {
if (typeof files === 'string')
await(await(this._page.$(selector)).uploadFile(files));
else
await(await(this._page.$(selector)).uploadFile(...files));
}
/**
* @param {string} eventType
* @param {!Array<*>} args
*/
sendEvent(eventType, ...args) {
if (eventType.startsWith('key'))
this._sendKeyboardEvent.apply(this, arguments);
else
this._sendMouseEvent.apply(this, arguments);
}
/**
* @param {string} eventType
* @param {string} keyOrKeys
* @param {null} nop1
* @param {null} nop2
* @param {number} modifier
*/
_sendKeyboardEvent(eventType, keyOrKeys, nop1, nop2, modifier) {
switch (eventType) {
case 'keyup':
if (typeof keyOrKeys === 'number') {
await(this._page.keyboard.up(String.fromCharCode(keyOrKeys)));
break;
}
for (const key of keyOrKeys)
await(this._page.keyboard.up(key));
break;
case 'keypress':
if (modifier & 0x04000000)
this._page.keyboard.down('Control');
if (modifier & 0x02000000)
this._page.keyboard.down('Shift');
if (keyOrKeys instanceof Array) {
this._page.keyboard.down(keyOrKeys[0]);
await(this._page.keyboard.up(keyOrKeys[0]));
} else if (typeof keyOrKeys === 'number') {
await(this._page.type(String.fromCharCode(keyOrKeys)));
} else {
await(this._page.type(keyOrKeys));
}
if (modifier & 0x02000000)
this._page.keyboard.up('Shift');
if (modifier & 0x04000000)
this._page.keyboard.up('Control');
break;
case 'keydown':
if (typeof keyOrKeys === 'number') {
await(this._page.keyboard.down(String.fromCharCode(keyOrKeys)));
break;
}
for (const key of keyOrKeys)
await(this._page.keyboard.down(key));
break;
}
}
/**
* @param {string} eventType
* @param {number} x
* @param {number} y
* @param {string|undefined} button
* @param {number|undefined} modifier
*/
_sendMouseEvent(eventType, x, y, button, modifier) {
if (modifier)
await(this._page.keyboard.down(modifier));
switch (eventType) {
case 'mousemove':
await(this._page.mouse.move(x, y));
break;
case 'mousedown':
await(this._page.mouse.move(x, y));
await(this._page.mouse.down({button}));
break;
case 'mouseup':
await(this._page.mouse.move(x, y));
await(this._page.mouse.up({button}));
break;
case 'doubleclick':
await(this._page.mouse.click(x, y, {button}));
await(this._page.mouse.click(x, y, {button, clickCount: 2}));
break;
case 'click':
await(this._page.mouse.click(x, y, {button}));
break;
case 'contextmenu':
await(this._page.mouse.click(x, y, {button: 'right'}));
break;
}
if (modifier)
await(this._page.keyboard.up(modifier));
}
/**
* @param {string} html
* @param {function()=} callback
*/
open(url, callback) {
console.assert(arguments.length <= 2, 'WebPage.open does not support METHOD and DATA arguments');
this._deferEvaluate = true;
if (typeof this._onInitialized === 'function')
this._onInitialized();
this._deferEvaluate = false;
this.loading = true;
this.loadingProgress = 50;
const handleNavigation = (error, response) => {
this.loadingProgress = 100;
this.loading = false;
if (error) {
this.onResourceError.call(null, {
url,
errorString: 'SSL handshake failed'
});
}
const status = error ? 'fail' : 'success';
if (this.onLoadFinished)
this.onLoadFinished.call(null, status);
if (callback)
callback.call(null, status);
this.loadingProgress = 0;
};
this._page.goto(url).then(response => handleNavigation(null, response))
.catch(e => handleNavigation(e, null));
}
/**
* @param {!{width: number, height: number}} options
*/
set viewportSize(options) {
await(this._page.setViewport(options));
}
/**
* @param {function()|string} fun
* @param {!Array<!Object>} args
*/
evaluate(fun, ...args) {
if (typeof fun === 'string')
fun = `(${fun})()`;
if (this._deferEvaluate)
return await(this._page.evaluateOnNewDocument(fun, ...args));
return await(this._currentFrame.evaluate(fun, ...args));
}
/**
* {string} fileName
*/
render(fileName) {
if (fileName.endsWith('pdf')) {
const options = {};
const paperSize = this.paperSize || {};
options.margin = paperSize.margin;
options.format = paperSize.format;
options.landscape = paperSize.orientation === 'landscape';
options.width = paperSize.width;
options.height = paperSize.height;
options.path = fileName;
await(this._page.pdf(options));
} else {
const options = {};
if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) {
options.clip = {
x: this.clipRect.left,
y: this.clipRect.top,
width: this.clipRect.width,
height: this.clipRect.height
};
}
options.path = fileName;
await(this._page.screenshot(options));
}
}
release() {
this._page.close();
}
close() {
this._page.close();
}
}
class WebPageSettings {
/**
* @param {!Page} page
*/
constructor(page) {
this._page = page;
}
/**
* @param {string} value
*/
set userAgent(value) {
await(this._page.setUserAgent(value));
}
/**
* @return {string}
*/
get userAgent() {
return await(this._page.evaluate(() => window.navigator.userAgent));
}
}
class PhantomRequest {
constructor() {
this._url = undefined;
this._headers = undefined;
}
/**
* @param {string} key
* @param {string} value
*/
setHeader(key, value) {
if (!this._headers)
this._headers = new Map();
this._headers.set(key, value);
}
abort() {
this._aborted = true;
}
/**
* @param {string} url
*/
changeUrl(newUrl) {
this._url = newUrl;
}
}
class PhantomResponse {
/**
* @param {!Response} response
* @param {boolean} isResponseFinished
*/
constructor(response, isResponseFinished) {
this.url = response.url;
this.status = response.status;
this.statusText = response.statusText;
this.stage = isResponseFinished ? 'end' : 'start';
this.headers = [];
for (const entry of response.headers.entries()) {
this.headers.push({
name: entry[0],
value: entry[1]
});
}
}
}
class RequestData {
/**
* @param {!InterceptedRequest} request
*/
constructor(request) {
this.url = request.url,
this.headers = {};
for (const entry of request.headers.entries())
this.headers[entry[0]] = entry[1];
}
}
// To prevent reenterability, eventemitters should emit events
// only being in a consistent state.
// This is not the case for 'ws' npm module: https://goo.gl/sy3dJY
//
// Since out phantomjs environment uses nested event loops, we
// exploit this condition in 'ws', which probably never happens
// in case of regular I/O.
//
// This class is a wrapper around EventEmitter which re-emits events asynchronously,
// helping to overcome the issue.
class AsyncEmitter extends EventEmitter {
/**
* @param {!Page} page
*/
constructor(page) {
super();
this._page = page;
this._symbol = Symbol('AsyncEmitter');
this.on('newListener', this._onListenerAdded);
this.on('removeListener', this._onListenerRemoved);
}
_onListenerAdded(event, listener) {
// Async listener calls original listener on next tick.
const asyncListener = (...args) => {
process.nextTick(() => listener.apply(null, args));
};
listener[this._symbol] = asyncListener;
this._page.on(event, asyncListener);
}
_onListenerRemoved(event, listener) {
this._page.removeListener(event, listener[this._symbol]);
}
}
module.exports = WebPage;

View File

@ -1,83 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const http = require('http');
const await = require('./utilities').await;
class WebServer {
constructor() {
this._server = http.createServer();
this.objectName = 'WebServer';
this.listenOnPort = this.listen;
this.newRequest = function(req, res) { };
Object.defineProperty(this, 'port', {
get: () => {
if (!this._server.listening)
return '';
return this._server.address().port + '';
},
enumerable: true,
configurable: false
});
}
close() {
this._server.close();
}
/**
* @param {nubmer} port
* @return {boolean}
*/
listen(port, callback) {
if (this._server.listening)
return false;
this.newRequest = callback;
this._server.listen(port);
const errorPromise = new Promise(x => this._server.once('error', x));
const successPromise = new Promise(x => this._server.once('listening', x));
await(Promise.race([errorPromise, successPromise]));
if (!this._server.listening)
return false;
this._server.on('request', (req, res) => {
res.close = res.end.bind(res);
const headers = res.getHeaders();
res.headers = [];
for (const key in headers) {
res.headers.push({
name: key,
value: headers[key]
});
}
res.header = res.getHeader;
res.setHeaders = headers => {
for (const key in headers)
res.setHeader(key, headers[key]);
};
Object.defineProperty(res, 'statusCode', {
enumerable: true,
configurable: true,
writable: true,
value: res.statusCode
});
this.newRequest.call(null, req, res);
});
return true;
}
}
module.exports = WebServer;

View File

@ -1,115 +0,0 @@
#!/usr/bin/env node
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const await = require('./utilities').await;
const vm = require('vm');
const path = require('path');
const fs = require('fs');
const Phantom = require('./Phantom');
const FileSystem = require('./FileSystem');
const System = require('./System');
const WebPage = require('./WebPage');
const WebServer = require('./WebServer');
const child_process = require('child_process');
const puppeteer = require('..');
const argv = require('minimist')(process.argv.slice(2), {
alias: { v: 'version' },
boolean: ['headless'],
default: {'headless': true },
});
if (argv.version) {
console.log('PhantomShim v' + Phantom.version.join('.'));
return;
}
if (argv['ssl-certificates-path']) {
console.error('Flag --ssl-certificates-path is not supported.');
process.exit(1);
return;
}
const scriptArguments = argv._;
if (!scriptArguments.length) {
console.log(__filename.split('/').pop() + ' [scriptfile]');
return;
}
const scriptPath = path.resolve(process.cwd(), scriptArguments[0]);
if (!fs.existsSync(scriptPath)) {
console.error(`script not found: ${scriptPath}`);
process.exit(1);
return;
}
const context = createPhantomContext(argv.headless, scriptPath, argv);
const scriptContent = fs.readFileSync(scriptPath, 'utf8');
vm.runInContext(scriptContent, context);
/**
* @param {boolean} headless
* @param {string} scriptPath
* @param {!Array<string>} argv
* @return {!Object}
*/
function createPhantomContext(headless, scriptPath, argv) {
const context = {};
let browser = null;
context.setInterval = setInterval;
context.setTimeout = setTimeout;
context.clearInterval = clearInterval;
context.clearTimeout = clearTimeout;
context.phantom = Phantom.create(context, scriptPath);
context.console = console;
context.window = context;
context.WebPage = options => new WebPage(ensureBrowser(), scriptPath, options);
vm.createContext(context);
const nativeExports = {
fs: new FileSystem(),
system: new System(argv._),
webpage: {
create: context.WebPage,
},
webserver: {
create: () => new WebServer(),
},
cookiejar: {
create: () => {},
},
child_process: child_process
};
const bootstrapPath = path.join(__dirname, '..', 'third_party', 'phantomjs', 'bootstrap.js');
const bootstrapCode = fs.readFileSync(bootstrapPath, 'utf8');
vm.runInContext(bootstrapCode, context, {
filename: 'bootstrap.js'
})(nativeExports);
return context;
function ensureBrowser() {
if (!browser) {
browser = await(puppeteer.launch({
headless: argv.headless,
args: ['--no-sandbox']
}));
}
return browser;
}
}

View File

@ -1,32 +0,0 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const loopWhile = require('deasync').loopWhile;
module.exports = {
await: function(promise) {
let error;
let result;
let done = false;
promise.then(r => result = r)
.catch(err => error = err)
.then(() => done = true);
loopWhile(() => !done);
if (error)
throw error;
return result;
}
};

View File

@ -1,19 +0,0 @@
Short Name: phantomjs
URL: https://github.com/ariya/phantomjs/tree/2.1.1
Version: 2.1.1
License: BSD
License File: LICENSE.BSD
Security Critical: no
Description:
This package is used to aid puppeteer in running phantom.js scripts:
- test/ - testsuite is used to validate puppeteer running phantom.js scripts
- boostrap.js - used to bootstrap puppeteer environment
Local Modifications:
- test/run_test.py was changed to run puppeteer instead of phantomjs
- Certain tests under test/ were changed where tests were unreasonably strict in their expectations
(e.g. validating the exact format of error messages)
- bootstrap.js was changed to accept native modules as function arguments.
- test/run_test.py was enhanced to support "unsupported" directive

View File

@ -1,22 +0,0 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,235 +0,0 @@
/*jslint sloppy: true, nomen: true */
/*global window:true,phantom:true */
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.com>
Copyright (C) 2011 James Roe <roejames12@hotmail.com>
Copyright (C) 2011 execjosh, http://execjosh.blogspot.com
Copyright (C) 2012 James M. Greene <james.m.greene@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function(nativeExports) {
// CommonJS module implementation follows
window.global = window;
// fs is loaded at the end, when everything is ready
var fs;
var cache = {};
var paths = [];
var extensions = {
'.js': function(module, filename) {
var code = fs.read(filename);
module._compile(code);
},
'.json': function(module, filename) {
module.exports = JSON.parse(fs.read(filename));
}
};
function dirname(path) {
var replaced = path.replace(/\/[^\/]*\/?$/, '');
if (replaced == path) {
replaced = '';
}
return replaced;
}
function basename(path) {
return path.replace(/.*\//, '');
}
function joinPath() {
// It should be okay to hard-code a slash here.
// The FileSystem module returns a platform-specific
// separator, but the JavaScript engine only expects
// the slash.
var args = Array.prototype.slice.call(arguments);
return args.join('/');
}
function tryFile(path) {
if (fs.isFile(path)) return path;
return null;
}
function tryExtensions(path) {
var filename, exts = Object.keys(extensions);
for (var i=0; i<exts.length; ++i) {
filename = tryFile(path + exts[i]);
if (filename) return filename;
}
return null;
}
function tryPackage(path) {
var filename, package, packageFile = joinPath(path, 'package.json');
if (fs.isFile(packageFile)) {
package = JSON.parse(fs.read(packageFile));
if (!package || !package.main) return null;
filename = fs.absolute(joinPath(path, package.main));
return tryFile(filename) || tryExtensions(filename) ||
tryExtensions(joinPath(filename, 'index'));
}
return null;
}
function Module(filename, stubs) {
if (filename) this._setFilename(filename);
this.exports = {};
this.stubs = {};
for (var name in stubs) {
this.stubs[name] = stubs[name];
}
}
Module.prototype._setFilename = function(filename) {
this.id = this.filename = filename;
this.dirname = dirname(filename);
};
Module.prototype._isNative = function() {
return this.filename && this.filename[0] === ':';
};
Module.prototype._getPaths = function(request) {
var _paths = [], dir;
if (request[0] === '.') {
_paths.push(fs.absolute(joinPath(phantom.webdriverMode ? ":/ghostdriver" : this.dirname, request)));
} else if (fs.isAbsolute(request)) {
_paths.push(fs.absolute(request));
} else {
// first look in PhantomJS modules
_paths.push(joinPath(':/modules', request));
// then look in node_modules directories
if (!this._isNative()) {
dir = this.dirname;
while (dir) {
_paths.push(joinPath(dir, 'node_modules', request));
dir = dirname(dir);
}
}
}
for (var i=0; i<paths.length; ++i) {
if(fs.isAbsolute(paths[i])) {
_paths.push(fs.absolute(joinPath(paths[i], request)));
} else {
_paths.push(fs.absolute(joinPath(this.dirname, paths[i], request)));
}
}
return _paths;
};
Module.prototype._getFilename = function(request) {
if (nativeExports[request])
return ':/modules/' + request + '.js';
var path, filename = null, _paths = this._getPaths(request);
for (var i=0; i<_paths.length && !filename; ++i) {
path = _paths[i];
filename = tryFile(path) || tryExtensions(path) || tryPackage(path) ||
tryExtensions(joinPath(path, 'index'));
}
return filename;
};
Module.prototype._getRequire = function() {
var self = this;
function require(request) {
return self.require(request);
}
require.cache = cache;
require.extensions = extensions;
require.paths = paths;
require.stub = function(request, exports) {
self.stubs[request] = { exports: exports };
};
return require;
};
Module.prototype._load = function() {
if (this._isNative())
return;
var ext = this.filename.match(/\.[^.]+$/)[0];
if (!ext) ext = '.js';
extensions[ext](this, this.filename);
};
Module.prototype._compile = function(code) {
phantom.loadModule(code, this.filename);
};
Module.prototype.require = function(request) {
var filename, module;
// first see if there are any stubs for the request
if (this.stubs.hasOwnProperty(request)) {
if (this.stubs[request].exports instanceof Function) {
this.stubs[request].exports = this.stubs[request].exports();
}
return this.stubs[request].exports;
}
// else look for a file
filename = this._getFilename(request);
if (!filename) {
throw new Error("Cannot find module '" + request + "'");
}
if (cache.hasOwnProperty(filename)) {
return cache[filename].exports;
}
module = new Module(filename, this.stubs);
if (module._isNative()) {
module.exports = nativeExports[request] || {};
}
cache[filename] = module;
module._load();
return module.exports;
};
(function() {
var cwd, mainFilename, mainModule = new Module();
window.require = mainModule._getRequire();
fs = nativeExports.fs;
cwd = fs.absolute(phantom.libraryPath);
mainFilename = joinPath(cwd, basename(require('system').args[0]) || 'repl');
mainModule._setFilename(mainFilename);
}());
})

View File

@ -1,10 +0,0 @@
"use strict";
var system = require('system');
if (system.args.length === 1) {
console.log('Try to pass some args when invoking this script!');
} else {
system.args.forEach(function (arg, i) {
console.log(i + ': ' + arg);
});
}
phantom.exit();

View File

@ -1,28 +0,0 @@
"use strict";
var spawn = require("child_process").spawn
var execFile = require("child_process").execFile
var child = spawn("ls", ["-lF", "/rooot"])
child.stdout.on("data", function (data) {
console.log("spawnSTDOUT:", JSON.stringify(data))
})
child.stderr.on("data", function (data) {
console.log("spawnSTDERR:", JSON.stringify(data))
})
child.on("exit", function (code) {
console.log("spawnEXIT:", code)
})
//child.kill("SIGKILL")
execFile("ls", ["-lF", "/usr"], null, function (err, stdout, stderr) {
console.log("execFileSTDOUT:", JSON.stringify(stdout))
console.log("execFileSTDERR:", JSON.stringify(stderr))
})
setTimeout(function () {
phantom.exit(0)
}, 2000)

View File

@ -1,52 +0,0 @@
"use strict";
var page = require('webpage').create();
page.viewportSize = { width: 400, height : 400 };
page.content = '<html><body><canvas id="surface"></canvas></body></html>';
page.evaluate(function() {
var el = document.getElementById('surface'),
context = el.getContext('2d'),
width = window.innerWidth,
height = window.innerHeight,
cx = width / 2,
cy = height / 2,
radius = width / 2.3,
imageData,
pixels,
hue, sat, value,
i = 0, x, y, rx, ry, d,
f, g, p, u, v, w, rgb;
el.width = width;
el.height = height;
imageData = context.createImageData(width, height);
pixels = imageData.data;
for (y = 0; y < height; y = y + 1) {
for (x = 0; x < width; x = x + 1, i = i + 4) {
rx = x - cx;
ry = y - cy;
d = rx * rx + ry * ry;
if (d < radius * radius) {
hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI);
sat = Math.sqrt(d) / radius;
g = Math.floor(hue);
f = hue - g;
u = 255 * (1 - sat);
v = 255 * (1 - sat * f);
w = 255 * (1 - sat * (1 - f));
pixels[i] = [255, v, u, u, w, 255, 255][g];
pixels[i + 1] = [w, 255, 255, v, u, u, w][g];
pixels[i + 2] = [u, u, w, 255, 255, v, u][g];
pixels[i + 3] = 255;
}
}
}
context.putImageData(imageData, 0, 0);
document.body.style.backgroundColor = 'white';
document.body.style.margin = '0px';
});
page.render('colorwheel.png');
phantom.exit();

View File

@ -1,10 +0,0 @@
"use strict";
var t = 10,
interval = setInterval(function(){
if ( t > 0 ) {
console.log(t--);
} else {
console.log("BLAST OFF!");
phantom.exit();
}
}, 1000);

View File

@ -1,60 +0,0 @@
// Detect if a web page sniffs the user agent or not.
"use strict";
var page = require('webpage').create(),
system = require('system'),
sniffed,
address;
page.onInitialized = function () {
page.evaluate(function () {
(function () {
var userAgent = window.navigator.userAgent,
platform = window.navigator.platform;
window.navigator = {
appCodeName: 'Mozilla',
appName: 'Netscape',
cookieEnabled: false,
sniffed: false
};
window.navigator.__defineGetter__('userAgent', function () {
window.navigator.sniffed = true;
return userAgent;
});
window.navigator.__defineGetter__('platform', function () {
window.navigator.sniffed = true;
return platform;
});
})();
});
};
if (system.args.length === 1) {
console.log('Usage: detectsniff.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
console.log('Checking ' + address + '...');
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit();
} else {
window.setTimeout(function () {
sniffed = page.evaluate(function () {
return navigator.sniffed;
});
if (sniffed) {
console.log('The page tried to sniff the user agent.');
} else {
console.log('The page did not try to sniff the user agent.');
}
phantom.exit();
}, 1500);
}
});
}

View File

@ -1,24 +0,0 @@
// echoToFile.js - Write in a given file all the parameters passed on the CLI
"use strict";
var fs = require('fs'),
system = require('system');
if (system.args.length < 3) {
console.log("Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>");
phantom.exit(1);
} else {
var content = '',
f = null,
i;
for ( i= 2; i < system.args.length; ++i ) {
content += system.args[i] + (i === system.args.length-1 ? '' : ' ');
}
try {
fs.write(system.args[1], content, 'w');
} catch(e) {
console.log(e);
}
phantom.exit();
}

View File

@ -1,30 +0,0 @@
"use strict";
var feature, supported = [], unsupported = [];
phantom.injectJs('modernizr.js');
console.log('Detected features (using Modernizr ' + Modernizr._version + '):');
for (feature in Modernizr) {
if (Modernizr.hasOwnProperty(feature)) {
if (feature[0] !== '_' && typeof Modernizr[feature] !== 'function' &&
feature !== 'input' && feature !== 'inputtypes') {
if (Modernizr[feature]) {
supported.push(feature);
} else {
unsupported.push(feature);
}
}
}
}
console.log('');
console.log('Supported:');
supported.forEach(function (e) {
console.log(' ' + e);
});
console.log('');
console.log('Not supported:');
unsupported.forEach(function (e) {
console.log(' ' + e);
});
phantom.exit();

View File

@ -1,10 +0,0 @@
"use strict";
var fibs = [0, 1];
var ticker = window.setInterval(function () {
console.log(fibs[fibs.length - 1]);
fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]);
if (fibs.length > 10) {
window.clearInterval(ticker);
phantom.exit();
}
}, 300);

View File

@ -1,3 +0,0 @@
"use strict";
console.log('Hello, world!');
phantom.exit();

View File

@ -1,26 +0,0 @@
// Use 'page.injectJs()' to load the script itself in the Page context
"use strict";
if ( typeof(phantom) !== "undefined" ) {
var 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.onAlert = function(msg) {
console.log(msg);
};
console.log("* Script running in the Phantom context.");
console.log("* Script will 'inject' itself in a page...");
page.open("about:blank", function(status) {
if ( status === "success" ) {
console.log(page.injectJs("injectme.js") ? "... done injecting itself!" : "... fail! Check the $PWD?!");
}
phantom.exit();
});
} else {
alert("* Script running in the Page context.");
}

View File

@ -1,24 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system'),
t, address;
if (system.args.length === 1) {
console.log('Usage: loadspeed.js <some URL>');
phantom.exit(1);
} else {
t = Date.now();
address = system.args[1];
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
t = Date.now() - t;
console.log('Page title is ' + page.evaluate(function () {
return document.title;
}));
console.log('Loading time ' + t + ' msec');
}
phantom.exit();
});
}

View File

@ -1,26 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 2) {
console.log('Usage: loadurlwithoutcss.js URL');
phantom.exit();
}
var address = system.args[1];
page.onResourceRequested = function(requestData, request) {
if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData.headers['Content-Type'] == 'text/css') {
console.log('The url of the request is matching. Aborting: ' + requestData['url']);
request.abort();
}
};
page.open(address, function(status) {
if (status === 'success') {
phantom.exit();
} else {
console.log('Unable to load the address!');
phantom.exit();
}
});

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
"use strict";
var universe = require('./universe');
universe.start();
console.log('The answer is ' + universe.answer);
phantom.exit();

View File

@ -1,26 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system'),
address;
if (system.args.length === 1) {
console.log('Usage: netlog.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
page.onResourceRequested = function (req) {
console.log('requested: ' + JSON.stringify(req, undefined, 4));
};
page.onResourceReceived = function (res) {
console.log('received: ' + JSON.stringify(res, undefined, 4));
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
}
phantom.exit();
});
}

View File

@ -1,144 +0,0 @@
"use strict";
if (!Date.prototype.toISOString) {
Date.prototype.toISOString = function () {
function pad(n) { return n < 10 ? '0' + n : n; }
function ms(n) { return n < 10 ? '00'+ n : n < 100 ? '0' + n : n }
return this.getFullYear() + '-' +
pad(this.getMonth() + 1) + '-' +
pad(this.getDate()) + 'T' +
pad(this.getHours()) + ':' +
pad(this.getMinutes()) + ':' +
pad(this.getSeconds()) + '.' +
ms(this.getMilliseconds()) + 'Z';
}
}
function createHAR(address, title, startTime, resources)
{
var entries = [];
resources.forEach(function (resource) {
var request = resource.request,
startReply = resource.startReply,
endReply = resource.endReply;
if (!request || !startReply || !endReply) {
return;
}
// Exclude Data URI from HAR file because
// they aren't included in specification
if (request.url.match(/(^data:image\/.*)/i)) {
return;
}
entries.push({
startedDateTime: request.time.toISOString(),
time: endReply.time - request.time,
request: {
method: request.method,
url: request.url,
httpVersion: "HTTP/1.1",
cookies: [],
headers: request.headers,
queryString: [],
headersSize: -1,
bodySize: -1
},
response: {
status: endReply.status,
statusText: endReply.statusText,
httpVersion: "HTTP/1.1",
cookies: [],
headers: endReply.headers,
redirectURL: "",
headersSize: -1,
bodySize: startReply.bodySize,
content: {
size: startReply.bodySize,
mimeType: endReply.contentType
}
},
cache: {},
timings: {
blocked: 0,
dns: -1,
connect: -1,
send: 0,
wait: startReply.time - request.time,
receive: endReply.time - startReply.time,
ssl: -1
},
pageref: address
});
});
return {
log: {
version: '1.2',
creator: {
name: "PhantomJS",
version: phantom.version.major + '.' + phantom.version.minor +
'.' + phantom.version.patch
},
pages: [{
startedDateTime: startTime.toISOString(),
id: address,
title: title,
pageTimings: {
onLoad: page.endTime - page.startTime
}
}],
entries: entries
}
};
}
var page = require('webpage').create(),
system = require('system');
if (system.args.length === 1) {
console.log('Usage: netsniff.js <some URL>');
phantom.exit(1);
} else {
page.address = system.args[1];
page.resources = [];
page.onLoadStarted = function () {
page.startTime = new Date();
};
page.onResourceRequested = function (req) {
page.resources[req.id] = {
request: req,
startReply: null,
endReply: null
};
};
page.onResourceReceived = function (res) {
if (res.stage === 'start') {
page.resources[res.id].startReply = res;
}
if (res.stage === 'end') {
page.resources[res.id].endReply = res;
}
};
page.open(page.address, function (status) {
var har;
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit(1);
} else {
page.endTime = new Date();
page.title = page.evaluate(function () {
return document.title;
});
har = createHAR(page.address, page.title, page.startTime, page.resources);
console.log(JSON.stringify(har, undefined, 4));
phantom.exit();
}
});
}

View File

@ -1,25 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system'),
host, port, address;
if (system.args.length < 4) {
console.log('Usage: openurlwithproxy.js <proxyHost> <proxyPort> <URL>');
phantom.exit(1);
} else {
host = system.args[1];
port = system.args[2];
address = system.args[3];
phantom.setProxy(host, port, 'manual', '', '');
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address "' +
address + '" using proxy "' + host + ':' + port + '"');
} else {
console.log('Page title is ' + page.evaluate(function () {
return document.title;
}));
}
phantom.exit();
});
}

View File

@ -1,17 +0,0 @@
"use strict";
function helloWorld() {
console.log(phantom.outputEncoding + ": こんにちは、世界!");
}
console.log("Using default encoding...");
helloWorld();
console.log("\nUsing other encodings...");
var encodings = ["euc-jp", "sjis", "utf8", "System"];
for (var i = 0; i < encodings.length; i++) {
phantom.outputEncoding = encodings[i];
helloWorld();
}
phantom.exit()

View File

@ -1,147 +0,0 @@
// The purpose of this is to show how and when events fire, considering 5 steps
// happening as follows:
//
// 1. Load URL
// 2. Load same URL, but adding an internal FRAGMENT to it
// 3. Click on an internal Link, that points to another internal FRAGMENT
// 4. Click on an external Link, that will send the page somewhere else
// 5. Close page
//
// Take particular care when going through the output, to understand when
// things happen (and in which order). Particularly, notice what DOESN'T
// happen during step 3.
//
// If invoked with "-v" it will print out the Page Resources as they are
// Requested and Received.
//
// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
// registered but not used here. This is left for you to have fun with.
// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
// NOTE.3: Main audience for this are people new to PhantomJS.
"use strict";
var sys = require("system"),
page = require("webpage").create(),
logResources = false,
step1url = "http://en.wikipedia.org/wiki/DOM_events",
step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow";
if (sys.args.length > 1 && sys.args[1] === "-v") {
logResources = true;
}
function printArgs() {
var i, ilen;
for (i = 0, ilen = arguments.length; i < ilen; ++i) {
console.log(" arguments[" + i + "] = " + JSON.stringify(arguments[i]));
}
console.log("");
}
////////////////////////////////////////////////////////////////////////////////
page.onInitialized = function() {
console.log("page.onInitialized");
printArgs.apply(this, arguments);
};
page.onLoadStarted = function() {
console.log("page.onLoadStarted");
printArgs.apply(this, arguments);
};
page.onLoadFinished = function() {
console.log("page.onLoadFinished");
printArgs.apply(this, arguments);
};
page.onUrlChanged = function() {
console.log("page.onUrlChanged");
printArgs.apply(this, arguments);
};
page.onNavigationRequested = function() {
console.log("page.onNavigationRequested");
printArgs.apply(this, arguments);
};
page.onRepaintRequested = function() {
console.log("page.onRepaintRequested");
printArgs.apply(this, arguments);
};
if (logResources === true) {
page.onResourceRequested = function() {
console.log("page.onResourceRequested");
printArgs.apply(this, arguments);
};
page.onResourceReceived = function() {
console.log("page.onResourceReceived");
printArgs.apply(this, arguments);
};
}
page.onClosing = function() {
console.log("page.onClosing");
printArgs.apply(this, arguments);
};
// window.console.log(msg);
page.onConsoleMessage = function() {
console.log("page.onConsoleMessage");
printArgs.apply(this, arguments);
};
// window.alert(msg);
page.onAlert = function() {
console.log("page.onAlert");
printArgs.apply(this, arguments);
};
// var confirmed = window.confirm(msg);
page.onConfirm = function() {
console.log("page.onConfirm");
printArgs.apply(this, arguments);
};
// var user_value = window.prompt(msg, default_value);
page.onPrompt = function() {
console.log("page.onPrompt");
printArgs.apply(this, arguments);
};
////////////////////////////////////////////////////////////////////////////////
setTimeout(function() {
console.log("");
console.log("### STEP 1: Load '" + step1url + "'");
page.open(step1url);
}, 0);
setTimeout(function() {
console.log("");
console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)");
page.open(step2url);
}, 5000);
setTimeout(function() {
console.log("");
console.log("### STEP 3: Click on page internal link (aka FRAGMENT)");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[href='#Event_object']").dispatchEvent(ev);
});
}, 10000);
setTimeout(function() {
console.log("");
console.log("### STEP 4: Click on page external link");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[title='JavaScript']").dispatchEvent(ev);
});
}, 15000);
setTimeout(function() {
console.log("");
console.log("### STEP 5: Close page and shutdown (with a delay)");
page.close();
setTimeout(function(){
phantom.exit();
}, 100);
}, 20000);

View File

@ -1,18 +0,0 @@
"use strict";
var p = require("webpage").create();
p.onConsoleMessage = function(msg) { console.log(msg); };
// Calls to "callPhantom" within the page 'p' arrive here
p.onCallback = function(msg) {
console.log("Received by the 'phantom' main context: "+msg);
return "Hello there, I'm coming to you from the 'phantom' context instead";
};
p.evaluate(function() {
// Return-value of the "onCallback" handler arrive here
var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context");
console.log("Received by the 'page' context: "+callbackResponse);
});
phantom.exit();

View File

@ -1,21 +0,0 @@
// Read the Phantom webpage '#intro' element text using jQuery and "includeJs"
"use strict";
var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.open("http://phantomjs.org/", function(status) {
if (status === "success") {
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
page.evaluate(function() {
console.log("$(\".explanation\").text() -> " + $(".explanation").text());
});
phantom.exit(0);
});
} else {
phantom.exit(1);
}
});

View File

@ -1,15 +0,0 @@
// Example using HTTP POST operation
"use strict";
var page = require('webpage').create(),
server = 'http://posttestserver.com/post.php?dump',
data = 'universe=expanding&answer=42';
page.open(server, 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});

View File

@ -1,19 +0,0 @@
// Example using HTTP POST operation
"use strict";
var page = require('webpage').create(),
server = 'http://posttestserver.com/post.php?dump',
data = '{"universe": "expanding", "answer": 42}';
var headers = {
"Content-Type": "application/json"
}
page.open(server, 'post', data, headers, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});

View File

@ -1,35 +0,0 @@
// Example using HTTP POST operation
"use strict";
var page = require('webpage').create(),
server = require('webserver').create(),
system = require('system'),
data = 'universe=expanding&answer=42';
if (system.args.length !== 2) {
console.log('Usage: postserver.js <portnumber>');
phantom.exit(1);
}
var port = system.args[1];
service = server.listen(port, function (request, response) {
console.log('Request received at ' + new Date());
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
};
response.write(JSON.stringify(request, null, 4));
response.close();
});
page.open('http://localhost:' + port + '/', 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.plainText);
}
phantom.exit();
});

View File

@ -1,10 +0,0 @@
var system = require('system'),
env = system.env,
key;
for (key in env) {
if (env.hasOwnProperty(key)) {
console.log(key + '=' + env[key]);
}
}
phantom.exit();

View File

@ -1,90 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system');
function someCallback(pageNum, numPages) {
return "<h1> someCallback: " + pageNum + " / " + numPages + "</h1>";
}
if (system.args.length < 3) {
console.log('Usage: printheaderfooter.js URL filename');
phantom.exit(1);
} else {
var address = system.args[1];
var output = system.args[2];
page.viewportSize = { width: 600, height: 600 };
page.paperSize = {
format: 'A4',
margin: "1cm",
/* default header/footer for pages that don't have custom overwrites (see below) */
header: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
if (pageNum == 1) {
return "";
}
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})
},
footer: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
if (pageNum == numPages) {
return "";
}
return "<h1>Footer <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})
}
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
/* check whether the loaded page overwrites the header/footer setting,
i.e. whether a PhantomJSPriting object exists. Use that then instead
of our defaults above.
example:
<html>
<head>
<script type="text/javascript">
var PhantomJSPrinting = {
header: {
height: "1cm",
contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
},
footer: {
height: "1cm",
contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
}
};
</script>
</head>
<body><h1>asdfadsf</h1><p>asdfadsfycvx</p></body>
</html>
*/
if (page.evaluate(function(){return typeof PhantomJSPrinting == "object";})) {
paperSize = page.paperSize;
paperSize.header.height = page.evaluate(function() {
return PhantomJSPrinting.header.height;
});
paperSize.header.contents = phantom.callback(function(pageNum, numPages) {
return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.header.contents(pageNum, numPages);}, pageNum, numPages);
});
paperSize.footer.height = page.evaluate(function() {
return PhantomJSPrinting.footer.height;
});
paperSize.footer.contents = phantom.callback(function(pageNum, numPages) {
return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.footer.contents(pageNum, numPages);}, pageNum, numPages);
});
page.paperSize = paperSize;
console.log(page.paperSize.header.height);
console.log(page.paperSize.footer.height);
}
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}

View File

@ -1,36 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 7) {
console.log('Usage: printmargins.js URL filename LEFT TOP RIGHT BOTTOM');
console.log(' margin examples: "1cm", "10px", "7mm", "5in"');
phantom.exit(1);
} else {
var address = system.args[1];
var output = system.args[2];
var marginLeft = system.args[3];
var marginTop = system.args[4];
var marginRight = system.args[5];
var marginBottom = system.args[6];
page.viewportSize = { width: 600, height: 600 };
page.paperSize = {
format: 'A4',
margin: {
left: marginLeft,
top: marginTop,
right: marginRight,
bottom: marginBottom
}
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}

View File

@ -1,49 +0,0 @@
"use strict";
var page = require('webpage').create(),
system = require('system'),
address, output, size;
if (system.args.length < 3 || system.args.length > 5) {
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px');
console.log(' "800px*600px" window, clipped to 800x600');
phantom.exit(1);
} else {
address = system.args[1];
output = system.args[2];
page.viewportSize = { width: 600, height: 600 };
if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
size = system.args[3].split('*');
page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
: { format: system.args[3], orientation: 'portrait', margin: '1cm' };
} else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
size = system.args[3].split('*');
if (size.length === 2) {
pageWidth = parseInt(size[0], 10);
pageHeight = parseInt(size[1], 10);
page.viewportSize = { width: pageWidth, height: pageHeight };
page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
} else {
console.log("size:", system.args[3]);
pageWidth = parseInt(system.args[3], 10);
pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
console.log ("pageHeight:",pageHeight);
page.viewportSize = { width: pageWidth, height: pageHeight };
}
}
if (system.args.length > 4) {
page.zoomFactor = system.args[4];
}
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
phantom.exit(1);
} else {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}

View File

@ -1,74 +0,0 @@
// Render Multiple URLs to file
"use strict";
var RenderUrlsToFile, arrayOfUrls, system;
system = require("system");
/*
Render given urls
@param array of URLs to render
@param callbackPerUrl Function called after finishing each URL, including the last URL
@param callbackFinal Function called after finishing everything
*/
RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) {
var getFilename, next, page, retrieve, urlIndex, webpage;
urlIndex = 0;
webpage = require("webpage");
page = null;
getFilename = function() {
return "rendermulti-" + urlIndex + ".png";
};
next = function(status, url, file) {
page.close();
callbackPerUrl(status, url, file);
return retrieve();
};
retrieve = function() {
var url;
if (urls.length > 0) {
url = urls.shift();
urlIndex++;
page = webpage.create();
page.viewportSize = {
width: 800,
height: 600
};
page.settings.userAgent = "Phantom.js bot";
return page.open("http://" + url, function(status) {
var file;
file = getFilename();
if (status === "success") {
return window.setTimeout((function() {
page.render(file);
return next(status, url, file);
}), 200);
} else {
return next(status, url, file);
}
});
} else {
return callbackFinal();
}
};
return retrieve();
};
arrayOfUrls = null;
if (system.args.length > 1) {
arrayOfUrls = Array.prototype.slice.call(system.args, 1);
} else {
console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]");
arrayOfUrls = ["www.google.com", "www.bbc.co.uk", "phantomjs.org"];
}
RenderUrlsToFile(arrayOfUrls, (function(status, url, file) {
if (status !== "success") {
return console.log("Unable to render '" + url + "'");
} else {
return console.log("Rendered '" + url + "' at '" + file + "'");
}
}), function() {
return phantom.exit();
});

View File

@ -1,181 +0,0 @@
/**
* Captures the full height document even if it's not showing on the screen or captures with the provided range of screen sizes.
*
* A basic example for taking a screen shot using phantomjs which is sampled for https://nodejs-dersleri.github.io/
*
* usage : phantomjs responsive-screenshot.js {url} [output format] [doClipping]
*
* examples >
* phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/
* phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ pdf
* phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ true
* phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ png true
*
* @author Salih sagdilek <salihsagdilek@gmail.com>
*/
/**
* http://phantomjs.org/api/system/property/args.html
*
* Queries and returns a list of the command-line arguments.
* The first one is always the script name, which is then followed by the subsequent arguments.
*/
var args = require('system').args;
/**
* http://phantomjs.org/api/fs/
*
* file system api
*/
var fs = require('fs');
/**
* http://phantomjs.org/api/webpage/
*
* Web page api
*/
var page = new WebPage();
/**
* if url address does not exist, exit phantom
*/
if ( 1 === args.length ) {
console.log('Url address is required');
phantom.exit();
}
/**
* setup url address (second argument);
*/
var urlAddress = args[1].toLowerCase();
/**
* set output extension format
* @type {*}
*/
var ext = getFileExtension();
/**
* set if clipping ?
* @type {boolean}
*/
var clipping = getClipping();
/**
* setup viewports
*/
var viewports = [
{
width : 1200,
height : 800
},
{
width : 1024,
height : 768
},
{
width : 768,
height : 1024
},
{
width : 480,
height : 640
},
{
width : 320,
height : 480
}
];
page.open(urlAddress, function (status) {
if ( 'success' !== status ) {
console.log('Unable to load the url address!');
} else {
var folder = urlToDir(urlAddress);
var output, key;
function render(n) {
if ( !!n ) {
key = n - 1;
page.viewportSize = viewports[key];
if ( clipping ) {
page.clipRect = viewports[key];
}
output = folder + "/" + getFileName(viewports[key]);
console.log('Saving ' + output);
page.render(output);
render(key);
}
}
render(viewports.length);
}
phantom.exit();
});
/**
* filename generator helper
* @param viewport
* @returns {string}
*/
function getFileName(viewport) {
var d = new Date();
var date = [
d.getUTCFullYear(),
d.getUTCMonth() + 1,
d.getUTCDate()
];
var time = [
d.getHours() <= 9 ? '0' + d.getHours() : d.getHours(),
d.getMinutes() <= 9 ? '0' + d.getMinutes() : d.getMinutes(),
d.getSeconds() <= 9 ? '0' + d.getSeconds() : d.getSeconds(),
d.getMilliseconds()
];
var resolution = viewport.width + (clipping ? "x" + viewport.height : '');
return date.join('-') + '_' + time.join('-') + "_" + resolution + ext;
}
/**
* output extension format helper
*
* @returns {*}
*/
function getFileExtension() {
if ( 'true' != args[2] && !!args[2] ) {
return '.' + args[2];
}
return '.png';
}
/**
* check if clipping
*
* @returns {boolean}
*/
function getClipping() {
if ( 'true' == args[3] ) {
return !!args[3];
} else if ( 'true' == args[2] ) {
return !!args[2];
}
return false;
}
/**
* url to directory helper
*
* @param url
* @returns {string}
*/
function urlToDir(url) {
var dir = url
.replace(/^(http|https):\/\//, '')
.replace(/\/$/, '');
if ( !fs.makeTree(dir) ) {
console.log('"' + dir + '" is NOT created.');
phantom.exit();
}
return dir;
}

View File

@ -1,92 +0,0 @@
"use strict";
var system = require('system');
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 100ms
};
if (system.args.length !== 2) {
console.log('Usage: run-jasmine.js URL');
phantom.exit(1);
}
var 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.open(system.args[1], function(status){
if (status !== "success") {
console.log("Unable to open " + system.args[1]);
phantom.exit(1);
} else {
waitFor(function(){
return page.evaluate(function(){
return document.body.querySelector('.symbolSummary .pending') === null
});
}, function(){
var exitCode = page.evaluate(function(){
try {
console.log('');
console.log(document.body.querySelector('.description').innerText);
var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
if (list && list.length > 0) {
console.log('');
console.log(list.length + ' test(s) FAILED:');
for (i = 0; i < list.length; ++i) {
var el = list[i],
desc = el.querySelector('.description'),
msg = el.querySelector('.resultMessage.fail');
console.log('');
console.log(desc.innerText);
console.log(msg.innerText);
console.log('');
}
return 1;
} else {
console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
return 0;
}
} catch (ex) {
console.log(ex);
return 1;
}
});
phantom.exit(exitCode);
});
}
});

View File

@ -1,94 +0,0 @@
"use strict";
var system = require('system');
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 100ms
};
if (system.args.length !== 2) {
console.log('Usage: run-jasmine2.js URL');
phantom.exit(1);
}
var 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.open(system.args[1], function(status){
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
waitFor(function(){
return page.evaluate(function(){
return (document.body.querySelector('.symbolSummary .pending') === null &&
document.body.querySelector('.duration') !== null);
});
}, function(){
var exitCode = page.evaluate(function(){
console.log('');
var title = 'Jasmine';
var version = document.body.querySelector('.version').innerText;
var duration = document.body.querySelector('.duration').innerText;
var banner = title + ' ' + version + ' ' + duration;
console.log(banner);
var list = document.body.querySelectorAll('.results > .failures > .spec-detail.failed');
if (list && list.length > 0) {
console.log('');
console.log(list.length + ' test(s) FAILED:');
for (i = 0; i < list.length; ++i) {
var el = list[i],
desc = el.querySelector('.description'),
msg = el.querySelector('.messages > .result-message');
console.log('');
console.log(desc.innerText);
console.log(msg.innerText);
console.log('');
}
return 1;
} else {
console.log(document.body.querySelector('.alert > .bar.passed,.alert > .bar.skipped').innerText);
return 0;
}
});
phantom.exit(exitCode);
});
}
});

View File

@ -1,77 +0,0 @@
"use strict";
var system = require('system');
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 250ms
};
if (system.args.length !== 2) {
console.log('Usage: run-qunit.js URL');
phantom.exit(1);
}
var 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.open(system.args[1], function(status){
if (status !== "success") {
console.log("Unable to access network");
phantom.exit(1);
} else {
waitFor(function(){
return page.evaluate(function(){
var el = document.getElementById('qunit-testresult');
if (el && el.innerText.match('completed')) {
return true;
}
return false;
});
}, function(){
var failedNum = page.evaluate(function(){
var el = document.getElementById('qunit-testresult');
console.log(el.innerText);
try {
return el.getElementsByClassName('failed')[0].innerHTML;
} catch (e) { }
return 10000;
});
phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
});
}
});

View File

@ -1,24 +0,0 @@
// List all the files in a Tree of Directories
"use strict";
var system = require('system');
if (system.args.length !== 2) {
console.log("Usage: phantomjs scandir.js DIRECTORY_TO_SCAN");
phantom.exit(1);
}
var scanDirectory = function (path) {
var fs = require('fs');
if (fs.exists(path) && fs.isFile(path)) {
console.log(path);
} else if (fs.isDirectory(path)) {
fs.list(path).forEach(function (e) {
if ( e !== "." && e !== ".." ) { //< Avoid loops
scanDirectory(path + '/' + e);
}
});
}
};
scanDirectory(system.args[1]);
phantom.exit();

View File

@ -1,44 +0,0 @@
"use strict";
var page = require('webpage').create();
var server = require('webserver').create();
var system = require('system');
var host, port;
if (system.args.length !== 2) {
console.log('Usage: server.js <some port>');
phantom.exit(1);
} else {
port = system.args[1];
var listening = server.listen(port, function (request, response) {
console.log("GOT HTTP REQUEST");
console.log(JSON.stringify(request, null, 4));
// we set the headers here
response.statusCode = 200;
response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
// this is also possible:
response.setHeader("foo", "bar");
// now we write the body
// note: the headers above will now be sent implictly
response.write("<html><head><title>YES!</title></head>");
// note: writeBody can be called multiple times
response.write("<body><p>pretty cool :)</body></html>");
response.close();
});
if (!listening) {
console.log("could not create web server listening on port " + port);
phantom.exit();
}
var url = "http://localhost:" + port + "/foo/bar.php?asdf=true";
console.log("SENDING REQUEST TO:");
console.log(url);
page.open(url, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
console.log("GOT REPLY FROM SERVER:");
console.log(page.content);
}
phantom.exit();
});
}

View File

@ -1,35 +0,0 @@
"use strict";
var port, server, service,
system = require('system');
if (system.args.length !== 2) {
console.log('Usage: serverkeepalive.js <portnumber>');
phantom.exit(1);
} else {
port = system.args[1];
server = require('webserver').create();
service = server.listen(port, { keepAlive: true }, function (request, response) {
console.log('Request at ' + new Date());
console.log(JSON.stringify(request, null, 4));
var body = JSON.stringify(request, null, 4);
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain',
'Connection': 'Keep-Alive',
'Keep-Alive': 'timeout=5, max=100',
'Content-Length': body.length
};
response.write(body);
response.close();
});
if (service) {
console.log('Web server running on port ' + port);
} else {
console.log('Error: Could not create web server listening on port ' + port);
phantom.exit();
}
}

View File

@ -1,43 +0,0 @@
"use strict";
var port, server, service,
system = require('system');
if (system.args.length !== 2) {
console.log('Usage: simpleserver.js <portnumber>');
phantom.exit(1);
} else {
port = system.args[1];
server = require('webserver').create();
service = server.listen(port, function (request, response) {
console.log('Request at ' + new Date());
console.log(JSON.stringify(request, null, 4));
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/html'
};
response.write('<html>');
response.write('<head>');
response.write('<title>Hello, world!</title>');
response.write('</head>');
response.write('<body>');
response.write('<p>This is from PhantomJS web server.</p>');
response.write('<p>Request data:</p>');
response.write('<pre>');
response.write(JSON.stringify(request, null, 4));
response.write('</pre>');
response.write('</body>');
response.write('</html>');
response.close();
});
if (service) {
console.log('Web server running on port ' + port);
} else {
console.log('Error: Could not create web server listening on port ' + port);
phantom.exit();
}
}

View File

@ -1,27 +0,0 @@
// sleepsort.js - Sort integers from the commandline in a very ridiculous way: leveraging timeouts :P
"use strict";
var system = require('system');
function sleepSort(array, callback) {
var sortedCount = 0,
i, len;
for ( i = 0, len = array.length; i < len; ++i ) {
setTimeout((function(j){
return function() {
console.log(array[j]);
++sortedCount;
(len === sortedCount) && callback();
};
}(i)), array[i]);
}
}
if ( system.args.length < 2 ) {
console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES");
phantom.exit(1);
} else {
sleepSort(system.args.slice(1), function() {
phantom.exit();
});
}

View File

@ -1,19 +0,0 @@
"use strict";
var system = require('system');
system.stdout.write('Hello, system.stdout.write!');
system.stdout.writeLine('\nHello, system.stdout.writeLine!');
system.stderr.write('Hello, system.stderr.write!');
system.stderr.writeLine('\nHello, system.stderr.writeLine!');
system.stdout.writeLine('system.stdin.readLine(): ');
var line = system.stdin.readLine();
system.stdout.writeLine(JSON.stringify(line));
// This is essentially a `readAll`
system.stdout.writeLine('system.stdin.read(5): (ctrl+D to end)');
var input = system.stdin.read(5);
system.stdout.writeLine(JSON.stringify(input));
phantom.exit(0);

View File

@ -1,10 +0,0 @@
// This is to be used by "module.js" (and "module.coffee") example(s).
// There should NOT be a "universe.coffee" as only 1 of the 2 would
// ever be loaded unless the file extension was specified.
"use strict";
exports.answer = 42;
exports.start = function () {
console.log('Starting the universe....');
}

View File

@ -1,25 +0,0 @@
// Modify global object at the page initialization.
// In this example, effectively Math.random() always returns 0.42.
"use strict";
var page = require('webpage').create();
page.onInitialized = function () {
page.evaluate(function () {
Math.random = function() {
return 42 / 100;
};
});
};
page.open('http://ariya.github.com/js/random/', function (status) {
var result;
if (status !== 'success') {
console.log('Network error.');
} else {
console.log(page.evaluate(function () {
return document.getElementById('numbers').textContent;
}));
}
phantom.exit();
});

View File

@ -1,15 +0,0 @@
"use strict";
var page = require('webpage').create();
console.log('The default user agent is ' + page.settings.userAgent);
page.settings.userAgent = 'SpecialAgent';
page.open('http://www.httpuseragent.org', function (status) {
if (status !== 'success') {
console.log('Unable to access network');
} else {
var ua = page.evaluate(function () {
return document.getElementById('myagent').innerText;
});
console.log(ua);
}
phantom.exit();
});

View File

@ -1,6 +0,0 @@
"use strict";
console.log('using PhantomJS version ' +
phantom.version.major + '.' +
phantom.version.minor + '.' +
phantom.version.patch);
phantom.exit();

View File

@ -1,58 +0,0 @@
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
"use strict";
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
var page = require('webpage').create();
// Open Twitter on 'sencha' profile and, onPageLoad, do...
page.open("http://twitter.com/#!/sencha", function (status) {
// Check for page load success
if (status !== "success") {
console.log("Unable to access network");
} else {
// Wait for 'signin-dropdown' to be visible
waitFor(function() {
// Check in the page if a specific element is now visible
return page.evaluate(function() {
return $("#signin-dropdown").is(":visible");
});
}, function() {
console.log("The sign-in dialog should be visible now.");
phantom.exit();
});
}
});

View File

@ -1,73 +0,0 @@
"use strict";
var p = require("webpage").create();
function pageTitle(page) {
return page.evaluate(function(){
return window.document.title;
});
}
function setPageTitle(page, newTitle) {
page.evaluate(function(newTitle){
window.document.title = newTitle;
}, newTitle);
}
p.open("../test/webpage-spec-frames/index.html", function(status) {
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToChildFrame(\"frame1\"): "+p.switchToChildFrame("frame1"));
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToChildFrame(\"frame1-2\"): "+p.switchToChildFrame("frame1-2"));
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToParentFrame(): "+p.switchToParentFrame());
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToChildFrame(0): "+p.switchToChildFrame(0));
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToMainFrame()"); p.switchToMainFrame();
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
console.log("p.switchToChildFrame(\"frame2\"): "+p.switchToChildFrame("frame2"));
console.log("pageTitle(): " + pageTitle(p));
console.log("currentFrameName(): "+p.currentFrameName());
console.log("childFramesCount(): "+p.childFramesCount());
console.log("childFramesName(): "+p.childFramesName());
console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
console.log("");
phantom.exit();
});

View File

@ -1,8 +0,0 @@
//! no-harness
//! expect-exit: 0
//! expect-stdout: "we are alive"
var sys = require('system');
sys.stdout.write("we are alive\n");
phantom.exit();
sys.stdout.write("ERROR control passed beyond phantom.exit");

View File

@ -1,8 +0,0 @@
//! no-harness
//! expect-exit: 23
//! expect-stdout: "we are alive"
var sys = require('system');
sys.stdout.write("we are alive\n");
phantom.exit(23);
sys.stdout.write("ERROR control passed beyond phantom.exit");

View File

@ -1,27 +0,0 @@
// Test the properties of the 'module' object.
// Assumes the 'dummy_exposed' module is to be found in a directory
// named 'node_modules'.
// Module load might fail, so do it in a setup function.
var module;
setup(function () {
module = require("dummy_exposed");
});
test(function() {
assert_regexp_match(module.filename, /\/node_modules\/dummy_exposed\.js$/);
}, "module.filename is the absolute pathname of the module .js file");
test(function() {
assert_regexp_match(module.dirname, /\/node_modules$/);
}, "module.dirname is the absolute pathname of the directory containing "+
"the module");
test(function() {
assert_equals(module.id, module.filename);
}, "module.id equals module.filename");
test(function() {
var dummy_file = module.require('./dummy_file');
assert_equals(dummy_file, 'spec/node_modules/dummy_file');
}, "module.require is callable and resolves relative to the module");

View File

@ -1,39 +0,0 @@
test(function () {
assert_type_of(phantom, 'object');
}, "phantom object");
test(function () {
assert_own_property(phantom, 'libraryPath');
assert_type_of(phantom.libraryPath, 'string');
assert_greater_than(phantom.libraryPath.length, 0);
}, "phantom.libraryPath");
test(function () {
assert_own_property(phantom, 'outputEncoding');
assert_type_of(phantom.outputEncoding, 'string');
assert_equals(phantom.outputEncoding.toLowerCase(), 'utf-8'); // default
}, "phantom.outputEncoding");
test(function () {
assert_own_property(phantom, 'injectJs');
assert_type_of(phantom.injectJs, 'function');
}, "phantom.injectJs");
test(function () {
assert_own_property(phantom, 'exit');
assert_type_of(phantom.exit, 'function');
}, "phantom.exit");
test(function () {
assert_own_property(phantom, 'cookiesEnabled');
assert_type_of(phantom.cookiesEnabled, 'boolean');
assert_is_true(phantom.cookiesEnabled);
}, "phantom.cookiesEnabled");
test(function () {
assert_own_property(phantom, 'version');
assert_type_of(phantom.version, 'object');
assert_type_of(phantom.version.major, 'number');
assert_type_of(phantom.version.minor, 'number');
assert_type_of(phantom.version.patch, 'number');
}, "phantom.version");

View File

@ -1,10 +0,0 @@
/* The require tests need to run inside a module to work correctly; that
module is require/require_spec.js. (That directory also contains a
bunch of other files used by this test.) The module exports an array
of test functions in the form expected by generate_tests(). */
var rtests = require("require/require_spec.js").tests;
for (var i = 0; i < rtests.length; i++) {
test.apply(null, rtests[i]);
}

View File

@ -1,2 +0,0 @@
var b = require('./b');
exports.b = b;

View File

@ -1,2 +0,0 @@
var a = require('./a');
exports.a = a;

View File

@ -1 +0,0 @@
module.exports = 'dir/dummy';

View File

@ -1 +0,0 @@
module.exports = 'subdir/dummy';

View File

@ -1 +0,0 @@
exports.dummyFile2 = require('dummy_file2');

View File

@ -1 +0,0 @@
module.exports = 'require/subdir2/loader'

View File

@ -1 +0,0 @@
module.exports = 'require/dummy';

View File

@ -1,3 +0,0 @@
{
"message": "hello"
}

View File

@ -1 +0,0 @@
module.exports = 'require/node_modules/dummy_file';

View File

@ -1 +0,0 @@
module.exports = 'require/node_modules/dummy_module';

View File

@ -1,4 +0,0 @@
{
"name": "dummy",
"main": "./libdir/dummy_module.js"
}

View File

@ -1 +0,0 @@
module.exports = 'require/node_modules/dummy_module2';

View File

@ -1,3 +0,0 @@
exports.requireNonExistent = function() {
require('./non_existent');
};

View File

@ -1,131 +0,0 @@
var fs = require('fs');
var tests = [];
exports.tests = tests;
tests.push([function () {
assert_no_property(window, 'CoffeeScript');
assert_own_property(window, 'require');
assert_own_property(require('webpage'), 'create');
assert_own_property(require('webserver'), 'create');
assert_own_property(require('cookiejar'), 'create');
assert_own_property(require('fs'), 'separator');
assert_equals(require('system').platform, 'phantomjs');
}, "native modules"]);
tests.push([function () {
assert_equals(require('./json_dummy').message, 'hello');
assert_equals(require('./dummy.js'), 'require/dummy');
}, "JS and JSON modules"]);
tests.push([function () {
require('./empty').hello = 'hola';
assert_equals(require('./empty').hello, 'hola');
// assert_own_property rejects Functions
assert_equals(require.hasOwnProperty('cache'), true);
var exposed = require('dummy_exposed');
assert_equals(require.cache[exposed.filename], exposed);
}, "module caching"]);
tests.push([function () {
var a = require('./a');
var b = require('./b');
assert_equals(a.b, b);
assert_equals(b.a, a);
}, "circular dependencies"]);
tests.push([function () {
assert_throws("Cannot find module 'dummy_missing'",
function () { require('dummy_missing'); });
try {
require('./not_found').requireNonExistent();
} catch (e) {
assert_regexp_match(e.stack, /at require /);
}
}, "error handling 1"]);
tests.push([function error_handling_2 () {
try {
require('./thrower').fn();
} catch (e) {
assert_regexp_match(e.toString() + "\n" + e.stack,
/^Error: fn\nError: fn\n at Object.thrower/);
}
}, "error handling 2"]);
tests.push([function () {
assert_equals(require('./stubber').stubbed, 'stubbed module');
assert_equals(require('./stubber').child.stubbed, 'stubbed module');
assert_throws("Cannot find module 'stubbed'",
function () { require('stubbed'); });
var count = 0;
require.stub('lazily_stubbed', function() {
++count;
return 'lazily stubbed module';
});
assert_equals(require('lazily_stubbed'), 'lazily stubbed module');
require('lazily_stubbed');
assert_equals(count, 1);
}, "stub modules"]);
tests.push([function () {
assert_equals(require('./dummy'), 'require/dummy');
assert_equals(require('../fixtures/dummy'), 'spec/dummy');
assert_equals(require('./dir/dummy'), 'dir/dummy');
assert_equals(require('./dir/subdir/dummy'), 'subdir/dummy');
assert_equals(require('./dir/../dummy'), 'require/dummy');
assert_equals(require('./dir/./dummy'), 'dir/dummy');
assert_equals(require(
fs.absolute(module.dirname + '/dummy.js')), 'require/dummy');
}, "relative and absolute paths"]);
tests.push([function () {
assert_equals(require('dummy_file'), 'require/node_modules/dummy_file');
assert_equals(require('dummy_file2'), 'spec/node_modules/dummy_file2');
assert_equals(require('./dir/subdir/loader').dummyFile2,
'spec/node_modules/dummy_file2');
assert_equals(require('dummy_module'),
'require/node_modules/dummy_module');
assert_equals(require('dummy_module2'),
'require/node_modules/dummy_module2');
}, "loading from node_modules"]);
function require_paths_tests_1 () {
assert_equals(require('loader').dummyFile2,
'spec/node_modules/dummy_file2');
assert_equals(require('../subdir2/loader'),
'require/subdir2/loader');
assert_equals(require('../fixtures/dummy'), 'spec/dummy');
}
function require_paths_tests_2 () {
assert_throws("Cannot find module 'loader'",
function () { require('loader'); });
}
tests.push([function () {
require.paths.push('dir/subdir');
this.add_cleanup(function () { require.paths.pop(); });
require_paths_tests_1();
}, "relative paths in require.paths"]);
tests.push([
require_paths_tests_2, "relative paths in require paths (after removal)"]);
tests.push([function () {
require.paths.push(fs.absolute(module.dirname + '/dir/subdir'));
this.add_cleanup(function () { require.paths.pop(); });
require_paths_tests_1();
}, "absolute paths in require.paths"]);
tests.push([
require_paths_tests_2, "relative paths in require paths (after removal)"]);

View File

@ -1,5 +0,0 @@
require.stub('stubbed', 'stubbed module');
exports.stubbed = require('stubbed');
try {
exports.child = require('./stubber_child');
} catch (e) {}

View File

@ -1 +0,0 @@
exports.stubbed = require('stubbed');

View File

@ -1,3 +0,0 @@
exports.fn = function thrower() {
throw new Error('fn');
};

View File

@ -1,12 +0,0 @@
// A SyntaxError leaks to phantom.onError, despite the try-catch.
setup({ allow_uncaught_exception: true });
test(function () {
var helperFile = "../fixtures/parse-error-helper.js";
try {
phantom.injectJs(helperFile);
assert_is_true(false);
} catch (e) {
assert_is_true(e.stack.indexOf('fixtures/parse-error-helper.js:2') !== -1);
}
}, "stack trace from syntax error in injected file");

View File

@ -1,33 +0,0 @@
//! unsupported
/* Test the test server itself. */
var webpage = require('webpage');
function test_one_page(url) {
var page = webpage.create();
page.onResourceReceived = this.step_func(function (response) {
assert_equals(response.status, 200);
});
page.onResourceError = this.unreached_func();
page.onResourceTimeout = this.unreached_func();
page.onLoadFinished = this.step_func_done(function (status) {
assert_equals(status, 'success');
});
page.open(url);
}
function do_test(path) {
var http_url = TEST_HTTP_BASE + path;
var https_url = TEST_HTTPS_BASE + path;
var http_test = async_test(http_url);
var https_test = async_test(https_url);
http_test.step(test_one_page, null, http_url);
https_test.step(test_one_page, null, https_url);
}
[
'hello.html',
'status?200',
'echo'
]
.forEach(do_test);

View File

@ -1,7 +0,0 @@
//! unsupported
//! no-harness
//! expect-exit: -15
//! expect-stderr: TIMEOUT: Process terminated after 0.25 seconds.
//! timeout: 0.25
// no code, so phantom will just sleep forever

View File

@ -1,16 +0,0 @@
// These are cursory tests; we assume the underlying Qt
// features are properly tested elsewhere.
test(function () {
assert_equals(
phantom.resolveRelativeUrl(
"../scripts/foo.js",
"http://example.com/topic/page.html"),
"http://example.com/scripts/foo.js");
assert_equals(
phantom.fullyDecodeUrl(
"https://ja.wikipedia.org/wiki/%E8%87%A8%E6%B5%B7%E5%AD%A6%E6%A0%A1"),
"https://ja.wikipedia.org/wiki/臨海学校");
}, "resolveRelativeUrl and fullyDecodeUrl");

View File

@ -1,7 +0,0 @@
// This is separate from basics/phantom-object.js because it has to be
// updated with every release.
test(function () {
assert_equals(phantom.version.major, 0);
assert_equals(phantom.version.minor, 0);
assert_equals(phantom.version.patch, 1);
}, "PhantomJS version number is accurate");

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIJAJ7HwZBrgnLwMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0xNTA4MTEyMjU4MTZaFw0yNTA4MTAyMjU4MTZaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBANFha8c5JKjYrHc7BTqmuFSAxYsSKbUUa0k+0PFpjhj7Io/NOeHhxfdLJX/B
LVQXEDhvOlSTDBgC3RQkxCZJmMzKZjMDlj0cxY0esZtcqt0sRpwRvT+EBE9SlFu4
TWM2BQ6k5E4OIX/9aUk9HQ99pSjqmhu/7n76n/5DfqxGwkfVZengI1KwfezaB5+Q
wAvoS7tadROqTyynV1kd+OF9BJZwO1eR9lAiGc139J/BHegVcqdrI043oR+1vyTw
BFpodw4HYdJHNgo7DKAtmXoDAws5myqx2GcnVng1wyzu6LdM65nMV4/p5Y/Y6Ziy
RqeV1gVbtpxTcrLmWFnI8BRwFBUCAwEAAaNQME4wHQYDVR0OBBYEFPP1YOkZpJmE
x/W48Kwv2N1QC1oDMB8GA1UdIwQYMBaAFPP1YOkZpJmEx/W48Kwv2N1QC1oDMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA1NxsrmKxGecAS6TEHNBqFZ
9NhV23kXY5sdv8zl7HUmzR+vIBumd9lkSZdOwAy5/hmj6ACReSJ9f2xpyi0fOtx5
WZ8Vcrg9Qjuy17qmGi66yL860yr0h6hltzCWCi7e26Eybawm3/9PmbNV3Hcwgxug
D+gv4LZLlyj4JI4lg/8RVXaNXqGBZ39YhRH0LFVjbYiFWUGqzfAT9YBoC67Ov8Yv
Bl1PoV3sJcagx67X6y8ru+gecc/OOXKJHxSidhjRqhKB6WOWIPfugsMOl1g2FMPv
tuPFsIQNSaln7V+ECeDOipJOSp9KAyM5fNcVjldd/e4V+qwcyoOijFywNfSK10M=
-----END CERTIFICATE-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDRYWvHOSSo2Kx3
OwU6prhUgMWLEim1FGtJPtDxaY4Y+yKPzTnh4cX3SyV/wS1UFxA4bzpUkwwYAt0U
JMQmSZjMymYzA5Y9HMWNHrGbXKrdLEacEb0/hARPUpRbuE1jNgUOpORODiF//WlJ
PR0PfaUo6pobv+5++p/+Q36sRsJH1WXp4CNSsH3s2gefkMAL6Eu7WnUTqk8sp1dZ
HfjhfQSWcDtXkfZQIhnNd/SfwR3oFXKnayNON6Eftb8k8ARaaHcOB2HSRzYKOwyg
LZl6AwMLOZsqsdhnJ1Z4NcMs7ui3TOuZzFeP6eWP2OmYskanldYFW7acU3Ky5lhZ
yPAUcBQVAgMBAAECggEAOwI/w8fhAwz9niSuFpeB/57DDayywGveyKfBbygWegfc
97YZCAX/KvCswtKImdheI+mFAOzoTaQQ9mpeNYQsYhrwrpPmNZb0Pg9WcritFuQx
ii6drVbheBGH6kmI1dsVlcj25uCopE+g6pkkpYb9kwh7IjL3XiX4DUqsWpUej+ub
2iL/luW7nYHHIRqzOFgP3v/f29sFHNvYcgihphBMHtgb4VpeYQ/f7AC7k1bFYfA/
TmvfUcXdiPwJf0XICZOaLrT/6pigk0bRiLNn8npISu7Wlf4jF60bNAe4+krBVU4O
p8UjW99LiGKLDh8GpoudnzlnnngZ3SA5+bO7kwTjCQKBgQDvJwUShOWm2+5wJsr4
hWieTVDaZEDb+1WTe7DwtqRWNBWXchh8is9buWeXIe6+1WldBYYiQjgdggQCw8xG
IFFg1j1E6kPqk/kzrHYSsJ+/u8uaxypvvrVBhUqt5FduOxFojW2REX9W5n8HTdT4
32BGR4mGpuXzR+BsVK00QRgM+wKBgQDgIXtu6rbfx+mdXTFi6apWJoyu5bRWcrL2
mGoR+IjCk6NefcvBE33q54H/dk3+0Sxp6+uFo7lyKv4EL3lozQO2oga6sp2LOIEK
DUo+KQVOmntCNrjuN/PbjSu2s1j5QDnLNR9VvXGiYBWdpZ7k3YzoKJ1I4ZyB3kGs
H/lCXv52LwKBgER1HvaWJEcHXdGsyR0q0y+9Yg+h8w8FexGkrpm5LoGely+q8Wd1
NLZE9GpGxFjMLkT6d9MGsZmAxjUkZy0Lwz+9E/zOMnLLuOIZ1BK1jIUN9NJxgKxM
IwaGaUItwvlC31DWay7Dm3f8sxAcL4KuLpjvkWaCEAD76joYYxw6JfBRAoGADMe7
+xolLWN/3bpHq6U5UkpGcV6lxtwpekg8nCO44Kd8hFHWAX90CaYD0qZTUjlpN+z8
9BTe6TSsYV63pJM0KADbM2Al/Z9ONF2Hoz3BkLbcWm02ZFcKb7WADZ3yb9wKr5yq
2b/AsAqckO21vsUnWMGgHlzHCNy8j+0O0IsMJX8CgYAORhyGaU7x5t4kEvqBNIan
mOzuB0b5nYV9mHxmyFhOsa8LeM25SA4n1rFpTb8h6vmZF1y9+4Zy4uNfCR2wXg0v
I51qtZ8npbIksYvNqvHaTPg8ZBcFK5mHr3TDxXJCcc0ylzM98ze08D+qKr0joX4w
KlqN6KjGmYfb+RHehLk9sw==
-----END PRIVATE KEY-----

View File

@ -1 +0,0 @@
module.exports = 'spec/dummy';

View File

@ -1,9 +0,0 @@
ErrorHelper = {
foo: function() {
this.bar()
},
bar: function bar() {
referenceError
}
};

View File

@ -1,2 +0,0 @@
var ok;
bar("run away"

View File

@ -1,36 +0,0 @@
// Launch the official test suite for ECMA-262
var webpage = require('webpage');
page = webpage.create();
page.onError = function() {};
page.open('http://test262.ecmascript.org/', function() {
page.evaluate(function() { $('a#run').click(); });
page.evaluate(function() { $('img#btnRunAll').click(); });
function monitor() {
var data = page.evaluate(function() {
return {
ran: $('#totalCounter').text(),
total: $('#testsToRun').text(),
pass: $('#Pass').text(),
fail: $('#Fail').text(),
progress: $('div#progressbar').text()
};
});
console.log('Tests: ', data.ran, 'of', data.total,
' Pass:', data.pass, ' Fail:', data.fail);
if (data.progress.indexOf('complete') > 0) {
page.render('report.png');
phantom.exit();
} else {
setTimeout(monitor, 1000);
}
}
setTimeout(monitor, 0);
});

View File

@ -1,93 +0,0 @@
//! unsupported
var cookie0 = {
'name': 'Valid-Cookie-Name',
'value': 'Valid-Cookie-Value',
'domain': 'localhost',
'path': '/foo',
'httponly': true,
'secure': false
};
var cookie1 = {
'name': 'Valid-Cookie-Name-1',
'value': 'Valid-Cookie-Value',
'domain': 'localhost',
'path': '/foo',
'httponly': true,
'secure': false
};
var cookie2 = {
'name': 'Valid-Cookie-Name-2',
'value': 'Valid-Cookie-Value',
'domain': 'localhost',
'path': '/foo',
'httponly': true,
'secure': false
};
var cookies = [{
'name': 'Valid-Cookie-Name',
'value': 'Valid-Cookie-Value',
'domain': 'localhost',
'path': '/foo',
'httponly': true,
'secure': false
},{
'name': 'Valid-Cookie-Name-Sec',
'value': 'Valid-Cookie-Value-Sec',
'domain': 'localhost',
'path': '/foo',
'httponly': true,
'secure': false,
'expires': new Date().getTime() + 3600 //< expires in 1h
}];
var cookiejar, jar1, jar2;
setup(function () {
cookiejar = require('cookiejar');
jar1 = cookiejar.create();
jar2 = cookiejar.create();
});
test(function () {
assert_type_of(jar1, 'object');
assert_not_equals(jar1, null);
assert_type_of(jar1.cookies, 'object');
assert_type_of(jar1.addCookie, 'function');
assert_type_of(jar1.deleteCookie, 'function');
assert_type_of(jar1.clearCookies, 'function');
}, "cookie jar properties");
test(function () {
assert_equals(jar1.cookies.length, 0);
jar1.addCookie(cookie0);
assert_equals(jar1.cookies.length, 1);
jar1.deleteCookie('Valid-Cookie-Name');
assert_equals(jar1.cookies.length, 0);
}, "adding and removing cookies");
test(function () {
assert_equals(jar1.cookies.length, 0);
jar1.cookies = cookies;
assert_equals(jar1.cookies.length, 2);
jar1.clearCookies();
assert_equals(jar1.cookies.length, 0);
}, "setting and clearing a cookie jar");
test(function () {
jar1.addCookie(cookie1);
assert_equals(jar1.cookies.length, 1);
assert_equals(jar2.cookies.length, 0);
jar2.addCookie(cookie2);
jar1.deleteCookie('Valid-Cookie-Name-1');
assert_equals(jar1.cookies.length, 0);
assert_equals(jar2.cookies.length, 1);
jar1.close();
jar2.close();
}, "cookie jar isolation");

View File

@ -1,52 +0,0 @@
//! unsupported
var cookies = {
'beforeExpires': {
'name': 'beforeExpires',
'value': 'expireValue',
'domain': '.abc.com',
'path': '/',
'httponly': false,
'secure': false,
'expires': 'Tue, 10 Jun 2025 12:28:29 GMT'
},
'noExpiresDate': {
'name': 'noExpiresDate',
'value': 'value',
'domain': '.abc.com',
'path': '/',
'httponly': false,
'secure': false,
'expires': null
},
'afterExpires': {
'name': 'afterExpires',
'value': 'value',
'domain': '.abc.com',
'path': '/',
'httponly': false,
'secure': false,
'expires': 'Mon, 10 Jun 2024 12:28:29 GMT'
}
};
test(function () {
var i, c, d, prop;
for (i in cookies) {
if (!cookies.hasOwnProperty(i)) continue;
phantom.addCookie(cookies[i]);
}
for (i in phantom.cookies) {
d = phantom.cookies[i];
c = cookies[d.name];
for (prop in c) {
if (!c.hasOwnProperty(prop)) continue;
if (c[prop] === null) {
assert_no_property(d, prop);
} else {
assert_own_property(d, prop);
assert_equals(c[prop], d[prop]);
}
}
}
}, "optional cookie properties should not leak");

View File

@ -1,220 +0,0 @@
// Basic Files API (read, write, remove, ...)
var FILENAME = "temp-01.test",
FILENAME_COPY = FILENAME + ".copy",
FILENAME_MOVED = FILENAME + ".moved",
FILENAME_EMPTY = FILENAME + ".empty",
FILENAME_ENC = FILENAME + ".enc",
FILENAME_BIN = FILENAME + ".bin",
ABSENT = "absent-01.test";
var fs;
setup(function () {
fs = require('fs');
var f = fs.open(FILENAME, "w");
f.write("hello");
f.writeLine("");
f.writeLine("world");
f.close();
});
test(function () {
assert_is_true(fs.exists(FILENAME));
// we might've gotten DOS line endings
assert_greater_than_equal(fs.size(FILENAME), "hello\nworld\n".length);
}, "create a file with contents");
test(function () {
assert_is_false(fs.exists(FILENAME_EMPTY));
fs.touch(FILENAME_EMPTY);
assert_is_true(fs.exists(FILENAME_EMPTY));
assert_equals(fs.size(FILENAME_EMPTY), 0);
}, "create (touch) an empty file");
test(function () {
var content = "";
var f = fs.open(FILENAME, "r");
this.add_cleanup(function () { f.close(); });
content = f.read();
assert_equals(content, "hello\nworld\n");
}, "read content from a file");
test(function () {
var content = "";
var f = fs.open(FILENAME, "r");
this.add_cleanup(function () { f.close(); });
f.seek(3);
content = f.read(5);
assert_equals(content, "lo\nwo");
}, "read specific number of bytes from a specific position in a file");
test(function () {
var content = "";
var f = fs.open(FILENAME, "rw+");
this.add_cleanup(function () { f.close(); });
f.writeLine("asdf");
content = f.read();
assert_equals(content, "hello\nworld\nasdf\n");
}, "append content to a file");
test(function () {
var f = fs.open(FILENAME, "r");
this.add_cleanup(function () { f.close(); });
assert_equals(f.getEncoding(), "UTF-8");
}, "get the file encoding (default: UTF-8)");
test(function () {
var f = fs.open(FILENAME, { charset: "UTF-8", mode: "r" });
this.add_cleanup(function () { f.close(); });
assert_equals(f.getEncoding(), "UTF-8");
var g = fs.open(FILENAME, { charset: "SJIS", mode: "r" });
this.add_cleanup(function () { g.close(); });
assert_equals(g.getEncoding(), "Shift_JIS");
}, "set the encoding on open", {/* unsupported */expected_fail: true});
test(function () {
var f = fs.open(FILENAME, { charset: "UTF-8", mode: "r" });
this.add_cleanup(function () { f.close(); });
assert_equals(f.getEncoding(), "UTF-8");
f.setEncoding("utf8");
assert_equals(f.getEncoding(), "UTF-8");
var g = fs.open(FILENAME, { charset: "SJIS", mode: "r" });
this.add_cleanup(function () { g.close(); });
assert_equals(g.getEncoding(), "Shift_JIS");
g.setEncoding("eucjp");
assert_equals(g.getEncoding(), "EUC-JP");
}, "change the encoding using setEncoding", {/* unsupported */expected_fail: true});
test(function () {
assert_is_false(fs.exists(FILENAME_COPY));
fs.copy(FILENAME, FILENAME_COPY);
assert_is_true(fs.exists(FILENAME_COPY));
assert_equals(fs.read(FILENAME), fs.read(FILENAME_COPY));
}, "copy a file");
test(function () {
assert_is_true(fs.exists(FILENAME));
var contentBeforeMove = fs.read(FILENAME);
fs.move(FILENAME, FILENAME_MOVED);
assert_is_false(fs.exists(FILENAME));
assert_is_true(fs.exists(FILENAME_MOVED));
assert_equals(fs.read(FILENAME_MOVED), contentBeforeMove);
}, "move a file");
test(function () {
assert_is_true(fs.exists(FILENAME_MOVED));
assert_is_true(fs.exists(FILENAME_COPY));
assert_is_true(fs.exists(FILENAME_EMPTY));
fs.remove(FILENAME_MOVED);
fs.remove(FILENAME_COPY);
fs.remove(FILENAME_EMPTY);
assert_is_false(fs.exists(FILENAME_MOVED));
assert_is_false(fs.exists(FILENAME_COPY));
assert_is_false(fs.exists(FILENAME_EMPTY));
}, "remove a file");
test(function () {
assert_throws("Unable to open file '"+ ABSENT +"'",
function () { fs.open(ABSENT, "r"); });
assert_throws("Unable to copy file '" + ABSENT +
"' at '" + FILENAME_COPY + "'",
function () { fs.copy(ABSENT, FILENAME_COPY); });
}, "operations on nonexistent files throw an exception", {/* unsupported */expected_fail: true});
test(function () {
var data = "ÄABCÖ";
var data_b = String.fromCharCode(
0xC3, 0x84, 0x41, 0x42, 0x43, 0xC3, 0x96);
var f = fs.open(FILENAME_ENC, "w");
this.add_cleanup(function () {
f.close();
fs.remove(FILENAME_ENC);
});
f.write(data);
f.close();
f = fs.open(FILENAME_ENC, "r");
assert_equals(f.read(), data);
var g = fs.open(FILENAME_ENC, "rb");
this.add_cleanup(function () { g.close(); });
assert_equals(g.read(), data_b);
}, "read/write UTF-8 text by default");
test(function () {
var data = "ピタゴラスイッチ";
var data_b = String.fromCharCode(
0x83, 0x73, 0x83, 0x5e, 0x83, 0x53, 0x83, 0x89,
0x83, 0x58, 0x83, 0x43, 0x83, 0x62, 0x83, 0x60);
var f = fs.open(FILENAME_ENC, { mode: "w", charset: "Shift_JIS" });
this.add_cleanup(function () {
f.close();
fs.remove(FILENAME_ENC);
});
f.write(data);
f.close();
f = fs.open(FILENAME_ENC, { mode: "r", charset: "Shift_JIS" });
assert_equals(f.read(), data);
var g = fs.open(FILENAME_ENC, "rb");
this.add_cleanup(function () { g.close(); });
assert_equals(g.read(), data_b);
}, "read/write Shift-JIS text with options", {/* unsupported */expected_fail: true});
test(function () {
var data = String.fromCharCode(0, 1, 2, 3, 4, 5);
var f = fs.open(FILENAME_BIN, "wb");
this.add_cleanup(function () {
f.close();
fs.remove(FILENAME_BIN);
});
f.write(data);
f.close();
f = fs.open(FILENAME_BIN, "rb");
assert_equals(f.read(), data);
}, "read/write binary data");
test(function () {
var data = String.fromCharCode(0, 1, 2, 3, 4, 5);
fs.write(FILENAME_BIN, data, "b");
this.add_cleanup(function () {
fs.remove(FILENAME_BIN);
});
assert_equals(fs.read(FILENAME_BIN, "b"), data);
}, "read/write binary data (shortcuts)");

View File

@ -1,91 +0,0 @@
var fs = require('fs');
var ABSENT_DIR = "absentdir02",
ABSENT_FILE = "absentfile02",
TEST_DIR = "testdir02",
TEST_FILE = "temp-02.test",
TEST_FILE_PATH = fs.join(TEST_DIR, TEST_FILE),
TEST_CONTENT = "test content",
CONTENT_MULTIPLIER = 1024;
test(function () {
assert_throws("Unable to read file '"+ ABSENT_FILE +"' size",
function () { fs.size(ABSENT_FILE); });
assert_equals(fs.lastModified(ABSENT_FILE), null);
}, "size/date queries on nonexistent files", {/* unsupported */expected_fail: true});
test(function () {
// Round down to the nearest multiple of two seconds, because
// file timestamps might only have that much precision.
var before_creation = Math.floor(Date.now() / 2000) * 2000;
var f = fs.open(TEST_FILE, "w");
this.add_cleanup(function () {
if (f !== null) f.close();
fs.remove(TEST_FILE);
});
for (var i = 0; i < CONTENT_MULTIPLIER; i++) {
f.write(TEST_CONTENT);
}
f.close(); f = null;
// Similarly, but round _up_.
var after_creation = Math.ceil(Date.now() / 2000) * 2000;
assert_equals(fs.size(TEST_FILE),
TEST_CONTENT.length * CONTENT_MULTIPLIER);
var flm = fs.lastModified(TEST_FILE).getTime();
assert_greater_than_equal(flm, before_creation);
assert_less_than_equal(flm, after_creation);
}, "size/date queries on existing files");
test(function () {
fs.makeDirectory(TEST_DIR);
this.add_cleanup(function () { fs.removeTree(TEST_DIR); });
fs.write(TEST_FILE_PATH, TEST_CONTENT, "w");
assert_is_true(fs.exists(TEST_FILE_PATH));
assert_is_true(fs.exists(TEST_DIR));
assert_is_false(fs.exists(ABSENT_FILE));
assert_is_false(fs.exists(ABSENT_DIR));
assert_is_true(fs.isDirectory(TEST_DIR));
assert_is_false(fs.isDirectory(ABSENT_DIR));
assert_is_true(fs.isFile(TEST_FILE_PATH));
assert_is_false(fs.isFile(ABSENT_FILE));
var absPath = fs.absolute(TEST_FILE_PATH);
assert_is_false(fs.isAbsolute(TEST_FILE_PATH));
assert_is_true(fs.isAbsolute(absPath));
assert_is_true(fs.isReadable(TEST_FILE_PATH));
assert_is_true(fs.isWritable(TEST_FILE_PATH));
assert_is_false(fs.isExecutable(TEST_FILE_PATH));
assert_is_false(fs.isReadable(ABSENT_FILE));
assert_is_false(fs.isWritable(ABSENT_FILE));
assert_is_false(fs.isExecutable(ABSENT_FILE));
assert_is_true(fs.isReadable(TEST_DIR));
assert_is_true(fs.isWritable(TEST_DIR));
assert_is_true(fs.isExecutable(TEST_DIR));
assert_is_false(fs.isReadable(ABSENT_DIR));
assert_is_false(fs.isWritable(ABSENT_DIR));
assert_is_false(fs.isExecutable(ABSENT_DIR));
assert_is_false(fs.isLink(TEST_DIR));
assert_is_false(fs.isLink(TEST_FILE_PATH));
assert_is_false(fs.isLink(ABSENT_DIR));
assert_is_false(fs.isLink(ABSENT_FILE));
}, "file types and access modes");

View File

@ -1,72 +0,0 @@
var fs = require('fs');
var system = require('system');
var TEST_DIR = "testdir",
TEST_FILE = "testfile",
START_CWD = fs.workingDirectory;
test(function () {
assert_is_true(fs.makeDirectory(TEST_DIR));
this.add_cleanup(function () { fs.removeTree(TEST_DIR); });
assert_is_true(fs.changeWorkingDirectory(TEST_DIR));
this.add_cleanup(function () { fs.changeWorkingDirectory(START_CWD); });
fs.write(TEST_FILE, TEST_FILE, "w");
var suffix = fs.join("", TEST_DIR, TEST_FILE),
abs = fs.absolute(".." + suffix),
lastIndex = abs.lastIndexOf(suffix);
assert_not_equals(lastIndex, -1);
assert_equals(lastIndex + suffix.length, abs.length);
}, "manipulation of current working directory");
test(function () {
fs.copyTree(phantom.libraryPath, TEST_DIR);
this.add_cleanup(function () { fs.removeTree(TEST_DIR); });
assert_deep_equals(fs.list(phantom.libraryPath), fs.list(TEST_DIR));
}, "copying a directory tree");
test(function () {
assert_type_of(fs.readLink, 'function');
// TODO: test the actual functionality once we can create symlinks.
}, "fs.readLink exists");
generate_tests(function fs_join_test (parts, expected) {
var actual = fs.join.apply(null, parts);
assert_equals(actual, expected);
}, [
[ "fs.join: []", [], "." ],
[ "fs.join: nonsense", [[], null], "." ],
[ "fs.join: 1 element", [""], "." ],
[ "fs.join: 2 elements", ["", "a"], "/a" ],
[ "fs.join: 3 elements", ["a", "b", "c"], "a/b/c" ],
[ "fs.join: 4 elements", ["", "a", "b", "c"], "/a/b/c" ],
[ "fs.join: empty elements", ["", "a", "", "b", "", "c"], "/a/b/c" ],
[ "fs.join: empty elements 2", ["a", "", "b", "", "c"], "a/b/c" ]
]);
generate_tests(function fs_split_test (input, expected) {
var path = input.join(fs.separator);
var actual = fs.split(path);
assert_deep_equals(actual, expected);
}, [
[ "fs.split: absolute",
["", "a", "b", "c", "d"], ["", "a", "b", "c", "d"] ],
[ "fs.split: absolute, trailing",
["", "a", "b", "c", "d", ""], ["", "a", "b", "c", "d"] ],
[ "fs.split: non-absolute",
["a", "b", "c", "d"], ["a", "b", "c", "d"] ],
[ "fs.split: non-absolute, trailing",
["a", "b", "c", "d", ""], ["a", "b", "c", "d"] ],
[ "fs.split: repeated separators",
["a", "", "", "",
"b", "",
"c", "", "",
"d", "", "", ""], ["a", "b", "c", "d"] ]
]);

View File

@ -1,22 +0,0 @@
//! stdin: Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich
//! stdin: いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす
//^ first line: pangram in German
//^ second line: pan+isogram in hiragana (the Iroha)
var stdin;
setup(function () { stdin = require("system").stdin; });
test(function () {
assert_equals(stdin.readLine(),
"Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich");
}, "input line one (German)");
test(function () {
assert_equals(stdin.readLine(),
"いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす");
}, "input line two (Japanese)");
test(function () {
assert_equals(stdin.readLine(), "");
}, "input line three (EOF)");

View File

@ -1,14 +0,0 @@
//! no-harness
//! expect-stdout: Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich
//! expect-stderr: いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす
//^ stdout: pangram in German
//^ stderr: pan+isogram in hiragana (the Iroha)
phantom.onError = function () { phantom.exit(1); };
var sys = require("system");
sys.stdout.write("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich\n");
sys.stderr.write("いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす");
phantom.exit(0);

Some files were not shown because too many files have changed in this diff Show More