jasmine-headless-webkit 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -6,3 +6,7 @@ Makefile
6
6
  specrunner.moc
7
7
  specrunner.o
8
8
  ext/jasmine-webkit-specrunner/jasmine-webkit-specrunner
9
+ *.o
10
+ moc_*.*
11
+ .DS_Store
12
+ hydra-runner.log
data/Gemfile CHANGED
@@ -12,3 +12,4 @@ gem 'guard-coffeescript'
12
12
  gem 'growl'
13
13
  gem 'rake', '0.8.7'
14
14
  gem 'mocha', '0.9.12'
15
+ gem 'guard-jasmine-headless-webkit'
data/Guardfile CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
 
6
6
  guard 'shell' do
7
- watch(%r{ext/jasmine-webkit-specrunner/specrunner.cpp}) { compile }
7
+ watch(%r{ext/jasmine-webkit-specrunner/.*\.(cpp|h)}) { compile }
8
8
  end
9
9
  # A sample Guardfile
10
10
  # More info at https://github.com/guard/guard#readme
data/Rakefile CHANGED
@@ -16,31 +16,17 @@ Jasmine::Headless::Task.new
16
16
  namespace :spec do
17
17
  desc "Run on three Rubies"
18
18
  task :platforms do
19
- current = %x{rvm-prompt v}
20
-
21
- fail = false
22
- %w{1.8.7 1.9.2 ree}.each do |version|
23
- puts "Switching to #{version}"
24
- Bundler.with_clean_env do
25
- system %{bash -c 'source ~/.rvm/scripts/rvm ; rvm #{version} ; bundle install ; bundle exec rake spec'}
26
- end
27
- if $?.exitstatus != 0
28
- fail = true
29
- break
30
- end
31
- end
32
-
33
- system %{rvm #{current}}
34
-
35
- exit (fail ? 1 : 0)
19
+ system %{rvm 1.8.7,1.9.2,ree ruby bundle}
20
+ system %{rvm 1.8.7,1.9.2,ree ruby bundle exec rake spec}
21
+ raise StandardError.new if $?.exitstatus != 0
36
22
  end
37
23
  end
38
24
 
39
25
  task :default => [ 'spec:platforms', 'jasmine:headless' ]
40
26
 
41
27
  desc "Build the runner"
42
- task :build do
43
- Dir.chdir 'ext/jasmine-headless-specrunner' do
28
+ task :build_runner do
29
+ Dir.chdir 'ext/jasmine-webkit-specrunner' do
44
30
  system %{ruby extconf.rb}
45
31
  end
46
32
  end
@@ -0,0 +1,30 @@
1
+ #include <QtGui>
2
+ #include <QtWebKit>
3
+
4
+ #include "Page.h"
5
+
6
+ namespace HeadlessSpecRunner {
7
+ Page::Page() : QWebPage(), confirmResult(true) {}
8
+
9
+ void Page::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID) {
10
+ emit consoleLog(message, lineNumber, sourceID);
11
+ }
12
+
13
+ bool Page::javaScriptConfirm(QWebFrame *frame, const QString &msg) {
14
+ if (confirmResult) {
15
+ emit internalLog("TODO", "jasmine-headless-webkit can't handle confirm() yet! You should mock window.confirm for now. Returning true.");
16
+ return true;
17
+ } else {
18
+ confirmResult = true;
19
+ return false;
20
+ }
21
+ }
22
+
23
+ void Page::javaScriptAlert(QWebFrame *frame, const QString &msg) {
24
+ emit internalLog("alert", msg);
25
+ }
26
+
27
+ void Page::oneFalseConfirm() {
28
+ confirmResult = false;
29
+ }
30
+ }
@@ -0,0 +1,25 @@
1
+ #ifndef JHW_PAGE
2
+ #define JHW_PAGE
3
+
4
+ #include <QtGui>
5
+ #include <QtWebKit>
6
+
7
+ namespace HeadlessSpecRunner {
8
+ class Page: public QWebPage {
9
+ Q_OBJECT
10
+ public:
11
+ Page();
12
+ void oneFalseConfirm();
13
+ signals:
14
+ void consoleLog(const QString &msg, int lineNumber, const QString &sourceID);
15
+ void internalLog(const QString &note, const QString &msg);
16
+ protected:
17
+ void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID);
18
+ bool javaScriptConfirm(QWebFrame *frame, const QString &msg);
19
+ void javaScriptAlert(QWebFrame *frame, const QString &msg);
20
+ private:
21
+ bool confirmResult;
22
+ };
23
+ }
24
+
25
+ #endif
@@ -0,0 +1,270 @@
1
+ #include <QtGui>
2
+ #include <QtWebKit>
3
+ #include <QFile>
4
+ #include <QTextStream>
5
+ #include <iostream>
6
+ #include <QQueue>
7
+
8
+ #include "Runner.h"
9
+
10
+ namespace HeadlessSpecRunner {
11
+ Runner::Runner() : QObject()
12
+ , m_runs(0)
13
+ , hasErrors(false)
14
+ , usedConsole(false)
15
+ , showColors(false)
16
+ , isFinished(false)
17
+ , didFail(false)
18
+ , consoleNotUsedThisRun(false) {
19
+ m_page.settings()->enablePersistentStorage();
20
+ connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
21
+ connect(&m_page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(errorLog(QString, int, QString)));
22
+ connect(&m_page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString)));
23
+ connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
24
+ }
25
+
26
+ void Runner::addFile(const QString &spec) {
27
+ runnerFiles.enqueue(spec);
28
+ }
29
+
30
+ void Runner::go()
31
+ {
32
+ m_ticker.stop();
33
+ m_page.setPreferredContentsSize(QSize(1024, 600));
34
+ addJHW();
35
+ loadSpec();
36
+ }
37
+ void Runner::addJHW()
38
+ {
39
+ m_page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
40
+ }
41
+
42
+ void Runner::loadSpec()
43
+ {
44
+ m_page.mainFrame()->load(runnerFiles.dequeue());
45
+ m_ticker.start(200, this);
46
+ }
47
+
48
+ void Runner::watch(bool ok)
49
+ {
50
+ if (!ok) {
51
+ std::cerr << "Can't load " << qPrintable(m_page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
52
+ std::cerr << "Out of curiosity, did your tests try to submit a form and you haven't prevented that?" << std::endl;
53
+ std::cerr << "Try running your tests in your browser with the Jasmine server and see what happens." << std::endl;
54
+ QApplication::instance()->exit(1);
55
+ return;
56
+ }
57
+
58
+ m_ticker.start(200, this);
59
+ }
60
+
61
+ bool Runner::hasElement(const char *select)
62
+ {
63
+ return !m_page.mainFrame()->findFirstElement(select).isNull();
64
+ }
65
+
66
+ void Runner::setColors(bool colors)
67
+ {
68
+ showColors = colors;
69
+ }
70
+
71
+ void Runner::reportFile(const QString &file)
72
+ {
73
+ reportFilename = file;
74
+ }
75
+
76
+ void Runner::red()
77
+ {
78
+ if (showColors) std::cout << "\033[0;31m";
79
+ }
80
+
81
+ void Runner::green()
82
+ {
83
+ if (showColors) std::cout << "\033[0;32m";
84
+ }
85
+
86
+ bool Runner::hasError() {
87
+ return hasErrors;
88
+ }
89
+
90
+ void Runner::yellow()
91
+ {
92
+ if (showColors) std::cout << "\033[0;33m";
93
+ }
94
+
95
+ void Runner::clear()
96
+ {
97
+ if (showColors) std::cout << "\033[m";
98
+ }
99
+
100
+ void Runner::specPassed()
101
+ {
102
+ consoleNotUsedThisRun = true;
103
+ green();
104
+ std::cout << '.';
105
+ clear();
106
+ fflush(stdout);
107
+ }
108
+
109
+ void Runner::specFailed(const QString &specDetail)
110
+ {
111
+ consoleNotUsedThisRun = true;
112
+ didFail = true;
113
+ red();
114
+ std::cout << 'F';
115
+ failedSpecs.push(specDetail);
116
+ clear();
117
+ fflush(stdout);
118
+ }
119
+
120
+ void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
121
+ {
122
+ red();
123
+ std::cout << "[error] ";
124
+ clear();
125
+ std::cout << qPrintable(sourceID) << ":" << lineNumber << " : " << qPrintable(msg);
126
+ std::cout << std::endl;
127
+
128
+ hasErrors = true;
129
+ m_runs = 0;
130
+ m_ticker.start(200, this);
131
+ }
132
+
133
+ void Runner::internalLog(const QString &note, const QString &msg) {
134
+ red();
135
+ std::cout << "[" << qPrintable(note) << "] ";
136
+ clear();
137
+ std::cout << qPrintable(msg);
138
+ std::cout << std::endl;
139
+ }
140
+
141
+ void Runner::log(const QString &msg)
142
+ {
143
+ usedConsole = true;
144
+ green();
145
+ if (consoleNotUsedThisRun) {
146
+ std::cout << std::endl;
147
+ consoleNotUsedThisRun = false;
148
+ }
149
+ std::cout << "[console] ";
150
+ clear();
151
+ if (msg.contains("\n"))
152
+ std::cout << std::endl;
153
+ std::cout << qPrintable(msg);
154
+ std::cout << std::endl;
155
+ }
156
+
157
+ void Runner::leavePageAttempt(const QString &msg)
158
+ {
159
+ red();
160
+ std::cout << "[error] ";
161
+ clear();
162
+ std::cout << qPrintable(msg) << std::endl;
163
+ m_page.oneFalseConfirm();
164
+ hasErrors = true;
165
+ }
166
+
167
+ void Runner::printName(const QString &name)
168
+ {
169
+ std::cout << std::endl << std::endl;
170
+ red();
171
+ std::cout << qPrintable(name) << std::endl;
172
+ clear();
173
+ }
174
+
175
+ void Runner::printResult(const QString &result)
176
+ {
177
+ red();
178
+ std::cout << " " << qPrintable(result) << std::endl;
179
+ clear();
180
+ }
181
+
182
+ void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
183
+ {
184
+ std::cout << std::endl;
185
+ if (didFail) {
186
+ red();
187
+ std::cout << "FAIL: ";
188
+ } else {
189
+ green();
190
+ std::cout << "PASS";
191
+
192
+ if (hasErrors) {
193
+ std::cout << " with JS errors";
194
+ }
195
+
196
+ std::cout << ": ";
197
+ }
198
+
199
+ std::cout << qPrintable(total) << " tests, " << qPrintable(failed) << " failures, " << qPrintable(duration) << " secs.";
200
+ clear();
201
+ std::cout << std::endl;
202
+
203
+ if (!reportFilename.isEmpty()) {
204
+ QFile reportFH(reportFilename);
205
+
206
+ if (reportFH.open(QFile::WriteOnly)) {
207
+ QTextStream report(&reportFH);
208
+ report << qPrintable(total) << "/" << qPrintable(failed) << "/";
209
+ report << (usedConsole ? "T" : "F");
210
+ report << "/" << qPrintable(duration) << "\n";
211
+
212
+ QString failedSpec;
213
+
214
+ while (!failedSpecs.isEmpty()) {
215
+ failedSpec = failedSpecs.pop();
216
+ report << qPrintable(failedSpec) << "\n";
217
+ }
218
+
219
+ reportFH.close();
220
+ }
221
+ }
222
+
223
+ isFinished = true;
224
+ }
225
+
226
+ void Runner::timerEvent(QTimerEvent *event)
227
+ {
228
+ ++m_runs;
229
+
230
+ if (event->timerId() != m_ticker.timerId())
231
+ return;
232
+
233
+ if (hasErrors && m_runs > 2)
234
+ QApplication::instance()->exit(1);
235
+
236
+ if (isFinished) {
237
+ int exitCode = 0;
238
+ if (didFail || hasErrors) {
239
+ exitCode = 1;
240
+ } else {
241
+ if (usedConsole) {
242
+ exitCode = 2;
243
+ }
244
+ }
245
+
246
+ bool runAgain = true;
247
+
248
+ if (runnerFiles.count() == 0) {
249
+ runAgain = false;
250
+ } else {
251
+ if (exitCode == 1) {
252
+ runAgain = false;
253
+ }
254
+ }
255
+
256
+ if (runAgain) {
257
+ isFinished = false;
258
+ loadSpec();
259
+ } else {
260
+ QApplication::instance()->exit(exitCode);
261
+ }
262
+ }
263
+
264
+ if (m_runs > 30) {
265
+ std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl;
266
+ QApplication::instance()->exit(1);
267
+ }
268
+ }
269
+ }
270
+
@@ -0,0 +1,61 @@
1
+ #ifndef JHW_RUNNER
2
+ #define JHW_RUNNER
3
+
4
+ #include <QtGui>
5
+ #include <QtWebKit>
6
+ #include <QFile>
7
+ #include <QTextStream>
8
+ #include <iostream>
9
+ #include <QQueue>
10
+
11
+ #include "Page.h"
12
+
13
+ namespace HeadlessSpecRunner {
14
+ class Runner: public QObject {
15
+ Q_OBJECT
16
+ public:
17
+ Runner();
18
+ void setColors(bool colors);
19
+ void reportFile(const QString &file);
20
+ void addFile(const QString &spec);
21
+ void go();
22
+ public slots:
23
+ void log(const QString &msg);
24
+ bool hasError();
25
+ void leavePageAttempt(const QString &msg);
26
+ void specPassed();
27
+ void specFailed(const QString &specDetail);
28
+ void printName(const QString &name);
29
+ void printResult(const QString &result);
30
+ void finishSuite(const QString &duration, const QString &total, const QString& failed);
31
+ private slots:
32
+ void watch(bool ok);
33
+ void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
34
+ void internalLog(const QString &note, const QString &msg);
35
+ void addJHW();
36
+ protected:
37
+ bool hasElement(const char *select);
38
+ void timerEvent(QTimerEvent *event);
39
+ private:
40
+ HeadlessSpecRunner::Page m_page;
41
+ QBasicTimer m_ticker;
42
+ int m_runs;
43
+ bool hasErrors;
44
+ bool usedConsole;
45
+ bool showColors;
46
+ bool isFinished;
47
+ bool didFail;
48
+ bool consoleNotUsedThisRun;
49
+ QQueue<QString> runnerFiles;
50
+ QString reportFilename;
51
+ QStack<QString> failedSpecs;
52
+
53
+ void red();
54
+ void green();
55
+ void yellow();
56
+ void clear();
57
+ void loadSpec();
58
+ };
59
+ }
60
+
61
+ #endif
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  $: << File.expand_path("../../../lib", __FILE__)
2
4
 
3
5
  require 'qt/qmake'