Adds support for multiple Cookie Jars.

Previously, there was a single global cookie jar shared between all web pages.
Now, one can have separate cookie jars for different web pages.

Makes CookieJar a normal class, not a singleton.
Moves many public CookieJar methods to public slots.
Adds default cookie jar to Phantom.
Adds the CookieJar module that provides access to cookie jars in javascript.
Adds cookie jar module tests.

Usage:
var jar = require('cookiejar').create();
var webpage = require('webpage').create();
webpage.cookieJar = jar;
...
webpage.close();
jar.close();

JS API changes:
Webpage:
    var jar = page.cookieJar; -- assigns 'jar' the given webpage's cookie jar.
    page.cookiejar = jar; -- sets 'jar' as the given webpage's cookie jar.
CookieJar:
    var jar = require('cookiejar').create(path)
        creates a cookie jar with persistent storage at the given file path
        (path not mandatory).
    var cookies = jar.cookies; -- assign's 'jar' the list of cookies in the
        cookie jar.
    jar.cookies = [c1, c2]; -- sets the cookie jar's cookies as the ones in the
        list.
    jar.addCookie(cookie) -- adds cookie 'cookie' to the cookie jar.

https://github.com/ariya/phantomjs/issues/11417
1.x
Joseph Rollinson 2013-06-18 14:09:36 -05:00 committed by Ariya Hidayat
parent 3ae9d38d40
commit 244cf251cd
14 changed files with 286 additions and 50 deletions

View File

@ -78,32 +78,22 @@ QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)
} }
QT_END_NAMESPACE QT_END_NAMESPACE
// private: // public:
CookieJar::CookieJar(QString cookiesFile, QObject *parent) CookieJar::CookieJar(QString cookiesFile, QObject *parent)
: QNetworkCookieJar(parent) : QNetworkCookieJar(parent)
, m_cookieStorage(new QSettings(cookiesFile, QSettings::IniFormat, this))
, m_enabled(true) , m_enabled(true)
{ {
load(); if (cookiesFile == "") {
} m_cookieStorage = 0;
qDebug() << "CookieJar - Created but will not store cookies (use option '--cookies-file=<filename>' to enable persistent cookie storage)";
// public: } else {
CookieJar *CookieJar::instance(QString cookiesFile) m_cookieStorage = new QSettings(cookiesFile, QSettings::IniFormat, this);
{ load();
static CookieJar *singleton = NULL; qDebug() << "CookieJar - Created and will store cookies in:" << cookiesFile;
if (!singleton) {
if (cookiesFile.isEmpty()) {
qDebug() << "CookieJar - Created but will not store cookies (use option '--cookies-file=<filename>' to enable persistent cookie storage)";
} else {
qDebug() << "CookieJar - Created and will store cookies in:" << cookiesFile;
}
// Create singleton and assign ownershipt to the Phantom singleton object
// NOTE: First time this is done is when we set "once and for all" the Cookies' File
singleton = new CookieJar(cookiesFile, Phantom::instance());
} }
return singleton;
} }
// private:
CookieJar::~CookieJar() CookieJar::~CookieJar()
{ {
// On destruction, before saving, clear all the session cookies // On destruction, before saving, clear all the session cookies
@ -390,6 +380,11 @@ bool CookieJar::isEnabled() const
return m_enabled; return m_enabled;
} }
void CookieJar::close()
{
deleteLater();
}
// private: // private:
bool CookieJar::purgeExpiredCookies() bool CookieJar::purgeExpiredCookies()
{ {
@ -457,7 +452,9 @@ void CookieJar::save()
#endif #endif
// Store cookies // Store cookies
m_cookieStorage->setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(allCookies())); if (m_cookieStorage) {
m_cookieStorage->setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(allCookies()));
}
} }
} }
@ -468,7 +465,9 @@ void CookieJar::load()
qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>"); qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
// Load all the cookies // Load all the cookies
setAllCookies(qvariant_cast<QList<QNetworkCookie> >(m_cookieStorage->value(QLatin1String("cookies")))); if (m_cookieStorage) {
setAllCookies(qvariant_cast<QList<QNetworkCookie> >(m_cookieStorage->value(QLatin1String("cookies"))));
}
// If any cookie has expired since last execution, purge and save before going any further // If any cookie has expired since last execution, purge and save before going any further
if (purgeExpiredCookies()) { if (purgeExpiredCookies()) {

View File

@ -40,35 +40,36 @@ class CookieJar: public QNetworkCookieJar
{ {
Q_OBJECT Q_OBJECT
private:
CookieJar(QString cookiesFile, QObject *parent = NULL);
public: public:
static CookieJar *instance(QString cookiesFile = QString()); CookieJar(QString cookiesFile, QObject *parent = NULL);
virtual ~CookieJar(); virtual ~CookieJar();
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl & url); bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl & url);
QList<QNetworkCookie> cookiesForUrl (const QUrl & url) const; QList<QNetworkCookie> cookiesForUrl (const QUrl & url) const;
bool addCookie(const QNetworkCookie &cookie, const QString &url = QString()); bool addCookie(const QNetworkCookie &cookie, const QString &url = QString());
bool addCookieFromMap(const QVariantMap &cookie, const QString &url = QString());
bool addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url = QString()); bool addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url = QString());
bool addCookiesFromMap(const QVariantList &cookiesList, const QString &url = QString());
QList<QNetworkCookie> cookies(const QString &url = QString()) const; QList<QNetworkCookie> cookies(const QString &url = QString()) const;
QVariantList cookiesToMap(const QString &url = QString()) const;
QNetworkCookie cookie(const QString &name, const QString &url = QString()) const; QNetworkCookie cookie(const QString &name, const QString &url = QString()) const;
QVariantMap cookieToMap(const QString &name, const QString &url = QString()) const;
bool deleteCookie(const QString &name, const QString &url = QString());
bool deleteCookies(const QString &url = QString()); bool deleteCookies(const QString &url = QString());
void clearCookies();
void enable(); void enable();
void disable(); void disable();
bool isEnabled() const; bool isEnabled() const;
public slots:
bool addCookieFromMap(const QVariantMap &cookie, const QString &url = QString());
bool addCookiesFromMap(const QVariantList &cookiesList, const QString &url = QString());
QVariantList cookiesToMap(const QString &url = QString()) const;
QVariantMap cookieToMap(const QString &name, const QString &url = QString()) const;
bool deleteCookie(const QString &name, const QString &url = QString());
void clearCookies();
void close();
private slots: private slots:
bool purgeExpiredCookies(); bool purgeExpiredCookies();
bool purgeSessionCookies(); bool purgeSessionCookies();

68
src/modules/cookiejar.js Normal file
View File

@ -0,0 +1,68 @@
/*jslint sloppy: true, nomen: true */
/*global exports:true */
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2013 Joseph Rollinson, jtrollinson@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.
*/
/* Takes in a QtCookieJar and decorates it with useful functions. */
function decorateCookieJar(jar) {
/* Allows one to add a cookie to the cookie jar from inside JavaScript */
jar.addCookie = function(cookie) {
jar.addCookieFromMap(cookie);
};
/* Getting and Setting jar.cookies gets and sets all the cookies in the
* cookie jar.
*/
jar.__defineGetter__('cookies', function() {
return this.cookiesToMap();
});
jar.__defineSetter__('cookies', function(cookies) {
this.addCookiesFromMap(cookies);
});
return jar;
}
/* Creates and decorates a new cookie jar.
* path is the file path where Phantomjs will store the cookie jar persistently.
* path is not mandatory.
*/
exports.create = function (path) {
if (arguments.length < 1) {
path = "";
}
return decorateCookieJar(phantom.createCookieJar(path));
};
/* Exports the decorateCookieJar function */
exports.decorate = decorateCookieJar;

View File

@ -414,6 +414,20 @@ function decorateNewPage(opts, page) {
this.evaluate.apply(this, args); this.evaluate.apply(this, args);
}; };
/**
* get cookie jar for the page
*/
page.__defineGetter__("cookieJar", function() {
return require("cookiejar").decorate(this.cookieJar());
});
/**
* set cookie jar for the page
*/
page.__defineSetter__("cookieJar", function(cookieJar) {
this.setCookieJarFromQObject(cookieJar);
});
/** /**
* get cookies of the page * get cookies of the page
*/ */

View File

@ -120,8 +120,6 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent, const Config *config
, m_networkDiskCache(0) , m_networkDiskCache(0)
, m_sslConfiguration(QSslConfiguration::defaultConfiguration()) , m_sslConfiguration(QSslConfiguration::defaultConfiguration())
{ {
setCookieJar(CookieJar::instance());
if (config->diskCacheEnabled()) { if (config->diskCacheEnabled()) {
m_networkDiskCache = new QNetworkDiskCache(this); m_networkDiskCache = new QNetworkDiskCache(this);
m_networkDiskCache->setCacheDirectory(QDesktopServices::storageLocation(QDesktopServices::CacheLocation)); m_networkDiskCache->setCacheDirectory(QDesktopServices::storageLocation(QDesktopServices::CacheLocation));
@ -195,8 +193,9 @@ void NetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
QNetworkAccessManager::setCookieJar(cookieJar); QNetworkAccessManager::setCookieJar(cookieJar);
// Remove NetworkAccessManager's ownership of this CookieJar and // Remove NetworkAccessManager's ownership of this CookieJar and
// pass it to the PhantomJS Singleton object. // pass it to the PhantomJS Singleton object.
// CookieJar is a SINGLETON, shouldn't be deleted when // CookieJar is shared between multiple instances of NetworkAccessManager.
// the NetworkAccessManager is deleted but only when we shutdown. // It shouldn't be deleted when the NetworkAccessManager is deleted, but
// only when close is called on the cookie jar.
cookieJar->setParent(Phantom::instance()); cookieJar->setParent(Phantom::instance());
} }

View File

@ -97,9 +97,10 @@ void Phantom::init()
} }
// Initialize the CookieJar // Initialize the CookieJar
CookieJar::instance(m_config.cookiesFile()); m_defaultCookieJar = new CookieJar(m_config.cookiesFile());
m_page = new WebPage(this, QUrl::fromLocalFile(m_config.scriptFile())); m_page = new WebPage(this, QUrl::fromLocalFile(m_config.scriptFile()));
m_page->setCookieJar(m_defaultCookieJar);
m_pages.append(m_page); m_pages.append(m_page);
QString proxyType = m_config.proxyType(); QString proxyType = m_config.proxyType();
@ -290,15 +291,15 @@ bool Phantom::printDebugMessages() const
bool Phantom::areCookiesEnabled() const bool Phantom::areCookiesEnabled() const
{ {
return CookieJar::instance()->isEnabled(); return m_defaultCookieJar->isEnabled();
} }
void Phantom::setCookiesEnabled(const bool value) void Phantom::setCookiesEnabled(const bool value)
{ {
if (value) { if (value) {
CookieJar::instance()->enable(); m_defaultCookieJar->enable();
} else { } else {
CookieJar::instance()->disable(); m_defaultCookieJar->disable();
} }
} }
@ -308,9 +309,14 @@ bool Phantom::webdriverMode() const
} }
// public slots: // public slots:
QObject *Phantom::createCookieJar(const QString& filePath) {
return new CookieJar(filePath, this);
}
QObject *Phantom::createWebPage() QObject *Phantom::createWebPage()
{ {
WebPage *page = new WebPage(this); WebPage *page = new WebPage(this);
page->setCookieJar(m_defaultCookieJar);
// Store pointer to the page for later cleanup // Store pointer to the page for later cleanup
m_pages.append(page); m_pages.append(page);
@ -436,33 +442,33 @@ void Phantom::onInitialized()
bool Phantom::setCookies(const QVariantList &cookies) bool Phantom::setCookies(const QVariantList &cookies)
{ {
// Delete all the cookies from the CookieJar // Delete all the cookies from the CookieJar
CookieJar::instance()->clearCookies(); m_defaultCookieJar->clearCookies();
// Add a new set of cookies // Add a new set of cookies
return CookieJar::instance()->addCookiesFromMap(cookies); return m_defaultCookieJar->addCookiesFromMap(cookies);
} }
QVariantList Phantom::cookies() const QVariantList Phantom::cookies() const
{ {
// Return all the Cookies in the CookieJar, as a list of Maps (aka JSON in JS space) // Return all the Cookies in the CookieJar, as a list of Maps (aka JSON in JS space)
return CookieJar::instance()->cookiesToMap(); return m_defaultCookieJar->cookiesToMap();
} }
bool Phantom::addCookie(const QVariantMap &cookie) bool Phantom::addCookie(const QVariantMap &cookie)
{ {
return CookieJar::instance()->addCookieFromMap(cookie); return m_defaultCookieJar->addCookieFromMap(cookie);
} }
bool Phantom::deleteCookie(const QString &cookieName) bool Phantom::deleteCookie(const QString &cookieName)
{ {
if (!cookieName.isEmpty()) { if (!cookieName.isEmpty()) {
return CookieJar::instance()->deleteCookie(cookieName); return m_defaultCookieJar->deleteCookie(cookieName);
} }
return false; return false;
} }
void Phantom::clearCookies() void Phantom::clearCookies()
{ {
CookieJar::instance()->clearCookies(); m_defaultCookieJar->clearCookies();
} }

View File

@ -39,6 +39,7 @@
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "childprocess.h" #include "childprocess.h"
#include "cookiejar.h"
class WebPage; class WebPage;
class CustomPage; class CustomPage;
@ -108,6 +109,7 @@ public:
Q_INVOKABLE QObject *_createChildProcess(); Q_INVOKABLE QObject *_createChildProcess();
public slots: public slots:
QObject *createCookieJar(const QString &filePath);
QObject *createWebPage(); QObject *createWebPage();
QObject *createWebServer(); QObject *createWebServer();
QObject *createFilesystem(); QObject *createFilesystem();
@ -193,6 +195,7 @@ private:
QList<QPointer<WebPage> > m_pages; QList<QPointer<WebPage> > m_pages;
QList<QPointer<WebServer> > m_servers; QList<QPointer<WebServer> > m_servers;
Config m_config; Config m_config;
CookieJar *m_defaultCookieJar;
friend class CustomPage; friend class CustomPage;
}; };

View File

@ -53,6 +53,7 @@ OTHER_FILES += \
modules/webpage.js \ modules/webpage.js \
modules/webserver.js \ modules/webserver.js \
modules/child_process.js \ modules/child_process.js \
modules/cookiejar.js \
repl.js repl.js
include(gif/gif.pri) include(gif/gif.pri)

View File

@ -10,6 +10,7 @@
<file>modules/system.js</file> <file>modules/system.js</file>
<file>modules/child_process.js</file> <file>modules/child_process.js</file>
<file>modules/_coffee-script.js</file> <file>modules/_coffee-script.js</file>
<file>modules/cookiejar.js</file>
<file>repl.js</file> <file>repl.js</file>
<file>coffee-script/package.json</file> <file>coffee-script/package.json</file>

View File

@ -110,6 +110,10 @@ public:
} }
} }
void setCookieJar(CookieJar *cookieJar) {
m_cookieJar = cookieJar;
}
public slots: public slots:
bool shouldInterruptJavaScript() { bool shouldInterruptJavaScript() {
m_webPage->javascriptInterrupt(); m_webPage->javascriptInterrupt();
@ -219,6 +223,7 @@ protected:
newPage = new WebPage(Phantom::instance()); newPage = new WebPage(Phantom::instance());
Phantom::instance()->m_pages.append(newPage); Phantom::instance()->m_pages.append(newPage);
} }
newPage->setCookieJar(m_cookieJar);
// Apply default settings // Apply default settings
newPage->applySettings(Phantom::instance()->defaultPageSettings()); newPage->applySettings(Phantom::instance()->defaultPageSettings());
@ -235,6 +240,7 @@ private:
QString m_userAgent; QString m_userAgent;
QStringList m_uploadFiles; QStringList m_uploadFiles;
friend class WebPage; friend class WebPage;
CookieJar *m_cookieJar;
}; };
@ -775,36 +781,51 @@ QVariantMap WebPage::customHeaders() const
return m_networkAccessManager->customHeaders(); return m_networkAccessManager->customHeaders();
} }
void WebPage::setCookieJar(CookieJar *cookieJar) {
m_cookieJar = cookieJar;
m_customWebPage->setCookieJar(m_cookieJar);
m_networkAccessManager->setCookieJar(m_cookieJar);
}
void WebPage::setCookieJarFromQObject(QObject *cookieJar) {
setCookieJar(qobject_cast<CookieJar *>(cookieJar));
}
CookieJar *WebPage::cookieJar()
{
return m_cookieJar;
}
bool WebPage::setCookies(const QVariantList &cookies) bool WebPage::setCookies(const QVariantList &cookies)
{ {
// Delete all the cookies for this URL // Delete all the cookies for this URL
CookieJar::instance()->deleteCookies(this->url()); m_cookieJar->deleteCookies(this->url());
// Add a new set of cookies foor this URL // Add a new set of cookies foor this URL
return CookieJar::instance()->addCookiesFromMap(cookies, this->url()); return m_cookieJar->addCookiesFromMap(cookies, this->url());
} }
QVariantList WebPage::cookies() const QVariantList WebPage::cookies() const
{ {
// Return all the Cookies visible to this Page, as a list of Maps (aka JSON in JS space) // Return all the Cookies visible to this Page, as a list of Maps (aka JSON in JS space)
return CookieJar::instance()->cookiesToMap(this->url()); return m_cookieJar->cookiesToMap(this->url());
} }
bool WebPage::addCookie(const QVariantMap &cookie) bool WebPage::addCookie(const QVariantMap &cookie)
{ {
return CookieJar::instance()->addCookieFromMap(cookie, this->url()); return m_cookieJar->addCookieFromMap(cookie, this->url());
} }
bool WebPage::deleteCookie(const QString &cookieName) bool WebPage::deleteCookie(const QString &cookieName)
{ {
if (!cookieName.isEmpty()) { if (!cookieName.isEmpty()) {
return CookieJar::instance()->deleteCookie(cookieName, this->url()); return m_cookieJar->deleteCookie(cookieName, this->url());
} }
return false; return false;
} }
bool WebPage::clearCookies() bool WebPage::clearCookies()
{ {
return CookieJar::instance()->deleteCookies(this->url()); return m_cookieJar->deleteCookies(this->url());
} }
void WebPage::openUrl(const QString &address, const QVariant &op, const QVariantMap &settings) void WebPage::openUrl(const QString &address, const QVariant &op, const QVariantMap &settings)

View File

@ -36,6 +36,8 @@
#include <QWebPage> #include <QWebPage>
#include <QWebFrame> #include <QWebFrame>
#include "cookiejar.h"
class Config; class Config;
class CustomPage; class CustomPage;
class WebpageCallbacks; class WebpageCallbacks;
@ -357,6 +359,21 @@ public slots:
*/ */
QString currentFrameName() const; QString currentFrameName() const;
/**
* Allows to set cookie jar for this page.
*/
void setCookieJar(CookieJar *cookieJar);
/**
* Allows to set cookie jar in through QtWebKit Bridge
*/
void setCookieJarFromQObject(QObject *cookieJar);
/**
* Returns the CookieJar object
*/
CookieJar *cookieJar();
/** /**
* Allows to set cookies by this Page, at the current URL. * Allows to set cookies by this Page, at the current URL.
* This means that loading new URLs, causes the cookies to change dynamically * This means that loading new URLs, causes the cookies to change dynamically
@ -520,6 +537,7 @@ private:
bool m_ownsPages; bool m_ownsPages;
int m_loadingProgress; int m_loadingProgress;
bool m_shouldInterruptJs; bool m_shouldInterruptJs;
CookieJar *m_cookieJar;
friend class Phantom; friend class Phantom;
friend class CustomPage; friend class CustomPage;

100
test/cookiejar-spec.js Normal file
View File

@ -0,0 +1,100 @@
describe("CookieJar object", function() {
var jar = require('cookiejar').create();
it("should be creatable", function() {
expect(typeof jar).toEqual('object');
expect(jar).toNotEqual(null);
});
expectHasProperty(jar, 'cookies');
expectHasFunction(jar, 'addCookie');
expectHasFunction(jar, 'deleteCookie');
expectHasFunction(jar, 'clearCookies');
it("should add a cookie and then remove it", function() {
var cookie = {
'name' : 'Valid-Cookie-Name',
'value' : 'Valid-Cookie-Value',
'domain' : 'localhost',
'path' : '/foo',
'httponly' : true,
'secure' : false
};
jar.addCookie(cookie);
var cookies = jar.cookies;
expect(cookies.length).toEqual(1);
expect(jar.deleteCookie('Valid-Cookie-Name')).toBe(true);
expect(jar.cookies.length).toBe(0);
});
it("should set and get cookies with .cookies", function() {
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
}];
jar.cookies = cookies;
expect(jar.cookies.length).toBe(2);
jar.clearCookies();
expect(jar.cookies.length).toEqual(0);
});
it("should be separate cookie jars", function() {
var jar1 = require('cookiejar').create();
var jar2 = require('cookiejar').create();
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
};
jar1.addCookie(cookie1);
expect(jar1.cookies.length).toBe(1);
expect(jar2.cookies.length).toBe(0);
jar2.addCookie(cookie2);
expect(jar1.deleteCookie('Valid-Cookie-Name-1')).toBe(true);
expect(jar1.cookies.length).toBe(0);
expect(jar2.cookies.length).toBe(1);
jar1.close();
jar2.close();
});
});

View File

@ -11,6 +11,10 @@ describe("require()", function() {
should.exist(require('webserver').create); should.exist(require('webserver').create);
}); });
it("loads 'cookiejar' native module", function() {
should.exist(require('cookiejar').create);
});
it("loads 'system' native module", function() { it("loads 'system' native module", function() {
require('system').platform.should.equal('phantomjs'); require('system').platform.should.equal('phantomjs');
}); });

View File

@ -70,6 +70,7 @@ phantom.injectJs("./fs-spec-03.js"); //< Filesystem Specs 03 (Paths)
phantom.injectJs("./fs-spec-04.js"); //< Filesystem Specs 04 (Tests) phantom.injectJs("./fs-spec-04.js"); //< Filesystem Specs 04 (Tests)
phantom.injectJs("./system-spec.js"); phantom.injectJs("./system-spec.js");
phantom.injectJs("./webkit-spec.js"); phantom.injectJs("./webkit-spec.js");
phantom.injectJs("./cookiejar-spec.js");
require("./module_spec.js"); require("./module_spec.js");
require("./require/require_spec.js"); require("./require/require_spec.js");
require("./cjk-text-codecs.js"); require("./cjk-text-codecs.js");