commit 209dd69ae1e2117a883ae9bbd11170ee01a326db Author: John Bintz Date: Mon Apr 11 06:24:07 2011 -0400 adding ext and updating gemfile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4040c6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.gem +.bundle +Gemfile.lock +pkg/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..1bfa24a --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "http://rubygems.org" + +# Specify your gem's dependencies in jasmine-headless-webkit.gemspec +gemspec diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..14cfe0b --- /dev/null +++ b/Rakefile @@ -0,0 +1,2 @@ +require 'bundler' +Bundler::GemHelper.install_tasks diff --git a/ext/jasmine-webkit-specrunner/Info.plist b/ext/jasmine-webkit-specrunner/Info.plist new file mode 100644 index 0000000..032fa01 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleIconFile + + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleExecutable + specrunner + CFBundleIdentifier + com.yourcompany.specrunner + NOTE + This file was generated by Qt/QMake. + LSUIElement + 1 + + diff --git a/ext/jasmine-webkit-specrunner/extconf.rb b/ext/jasmine-webkit-specrunner/extconf.rb new file mode 100644 index 0000000..b7b2995 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/extconf.rb @@ -0,0 +1,2 @@ +system %{qmake} +system %{make} diff --git a/ext/jasmine-webkit-specrunner/specrunner.cpp b/ext/jasmine-webkit-specrunner/specrunner.cpp new file mode 100644 index 0000000..5a920fa --- /dev/null +++ b/ext/jasmine-webkit-specrunner/specrunner.cpp @@ -0,0 +1,164 @@ +/* + Copyright (c) 2010 Sencha Inc. + Copyright (c) 2011 John Bintz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#include +#include +#include + +#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) +#error Use Qt 4.7 or later version +#endif + +class HeadlessSpecRunner: public QObject +{ + Q_OBJECT +public: + HeadlessSpecRunner(); + void load(const QString &spec); +public slots: + void log(const QString &msg); + void specLog(int indent, const QString &msg, const QString &clazz); +private slots: + void watch(bool ok); +protected: + bool hasElement(const char *select); + void timerEvent(QTimerEvent *event); +private: + QWebPage m_page; + QBasicTimer m_ticker; + int m_runs; +}; + +HeadlessSpecRunner::HeadlessSpecRunner() + : QObject() + , m_runs(0) +{ + m_page.settings()->enablePersistentStorage(); + connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool))); +} + +void HeadlessSpecRunner::load(const QString &spec) +{ + m_ticker.stop(); + m_page.mainFrame()->addToJavaScriptWindowObject("debug", this); + m_page.mainFrame()->load(spec); + m_page.setPreferredContentsSize(QSize(1024, 600)); +} + +void HeadlessSpecRunner::watch(bool ok) +{ + if (!ok) { + std::cerr << "Can't load' " << qPrintable(m_page.mainFrame()->url().toString()) << std::endl; + QApplication::instance()->exit(1); + return; + } + + m_ticker.start(200, this); +} + +bool HeadlessSpecRunner::hasElement(const char *select) +{ + return !m_page.mainFrame()->findFirstElement(select).isNull(); +} + +void HeadlessSpecRunner::log(const QString &msg) +{ + std::cout << "\033[0;32m" << "[console] " << "\033[m"; + std::cout << qPrintable(msg); + std::cout << std::endl; +} + +void HeadlessSpecRunner::specLog(int indent, const QString &msg, const QString &clazz) +{ + for (int i = 0; i < indent; ++i) + std::cout << " "; + if ( clazz.endsWith("fail") ) { + std::cout << "\033[0;31m" << qPrintable(msg) << "\033[m"; + } else { + std::cout << "\033[0;33m" << qPrintable(msg) << "\033[m"; + } + std::cout << std::endl; +} + +#define DUMP_MSG "(function(n, i) { \ + if (n.toString() === '[object NodeList]') { \ + for (var c = 0; c < n.length; ++c) arguments.callee(n[c], i); return \ + }\ + if (n.className === 'description' || n.className == 'resultMessage fail') {\ + debug.specLog(i, n.textContent, n.className);\ + }\ + var e = n.firstElementChild;\ + while (e) {\ + arguments.callee(e, i + 1); e = e.nextElementSibling; \ + }\ + n.className = '';\ +})(document.getElementsByClassName('suite failed'), 0);" + +void HeadlessSpecRunner::timerEvent(QTimerEvent *event) +{ + if (event->timerId() != m_ticker.timerId()) + return; + + if (!hasElement(".jasmine_reporter") && !hasElement(".runner.running")) + return; + + if (hasElement(".runner.passed")) { + QWebElement desc = m_page.mainFrame()->findFirstElement(".description"); + std::cout << "\033[0;32m" << "PASS: " << qPrintable(desc.toPlainText()) << "\033[m" << std::endl; + QApplication::instance()->exit(0); + return; + } + + if (hasElement(".runner.failed")) { + QWebElement desc = m_page.mainFrame()->findFirstElement(".description"); + std::cout << "\033[0;31m" << "FAIL: " << qPrintable(desc.toPlainText()) << "\033[m" << std::endl; + m_page.mainFrame()->evaluateJavaScript(DUMP_MSG); +//QDesktopServices::openUrl(m_page.mainFrame()->url()); + QApplication::instance()->exit(1); + return; + } + + ++m_runs; + if (m_runs > 20) { + std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl; + QApplication::instance()->exit(1); + } +} + +#include "specrunner.moc" + +int main(int argc, char** argv) +{ + if (argc != 2) { + std::cerr << "Run Jasmine's SpecRunner headlessly" << std::endl << std::endl; + std::cerr << " specrunner SpecRunner.html" << std::endl; + return 1; + } + + QApplication app(argc, argv); + + HeadlessSpecRunner runner; + runner.load(QString::fromLocal8Bit(argv[1])); + return app.exec(); +} + diff --git a/ext/jasmine-webkit-specrunner/specrunner.pro b/ext/jasmine-webkit-specrunner/specrunner.pro new file mode 100644 index 0000000..409c8b4 --- /dev/null +++ b/ext/jasmine-webkit-specrunner/specrunner.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +CONFIG -= app_bundle +TARGET = jasmine-webkit-specrunner +SOURCES = specrunner.cpp +QT += network webkit +QMAKE_INFO_PLIST = Info.plist diff --git a/jasmine-headless-webkit.gemspec b/jasmine-headless-webkit.gemspec new file mode 100644 index 0000000..5a54303 --- /dev/null +++ b/jasmine-headless-webkit.gemspec @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "jasmine-headless-webkit/version" + +Gem::Specification.new do |s| + s.name = "jasmine-headless-webkit" + s.version = Jasmine::Headless::Webkit::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["John Bintz", "Sencha Inc."] + s.email = ["john@coswellproductions.com"] + s.homepage = "" + s.summary = %q{Run Jasmine specs headlessly in a WebKit browser} + s.description = %q{Run Jasmine specs headlessly} + + s.rubyforge_project = "jasmine-headless-webkit" + + s.extensions = `git ls-files -- ext/**/extconf.rb`.split("\n") + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] +end diff --git a/lib/jasmine-headless-webkit.rb b/lib/jasmine-headless-webkit.rb new file mode 100644 index 0000000..8bf6f3b --- /dev/null +++ b/lib/jasmine-headless-webkit.rb @@ -0,0 +1,7 @@ +module Jasmine + module Headless + module Webkit + # Your code goes here... + end + end +end diff --git a/lib/jasmine-headless-webkit/version.rb b/lib/jasmine-headless-webkit/version.rb new file mode 100644 index 0000000..556f032 --- /dev/null +++ b/lib/jasmine-headless-webkit/version.rb @@ -0,0 +1,7 @@ +module Jasmine + module Headless + module Webkit + VERSION = "0.0.1" + end + end +end