Merge branch 'master' of github.com:travis-ci/travis-web
Conflicts: public/scripts/app.js public/scripts/min/app.js public/styles/app.css public/version
This commit is contained in:
commit
393ef62eae
20
AssetFile
20
AssetFile
|
@ -23,12 +23,28 @@ input assets.scripts do
|
||||||
safe_concat assets.vendor_order, 'vendor.js'
|
safe_concat assets.vendor_order, 'vendor.js'
|
||||||
end
|
end
|
||||||
|
|
||||||
match %r(^(?!vendor).*\.js$) do
|
match 'spec/*.js' do
|
||||||
|
concat 'spec/specs.js'
|
||||||
|
end
|
||||||
|
|
||||||
|
match 'spec/support/*.js' do
|
||||||
|
concat 'spec/support.js'
|
||||||
|
end
|
||||||
|
|
||||||
|
match 'spec/vendor/*.js' do
|
||||||
|
concat assets.spec_vendor_order, 'spec/vendor.js'
|
||||||
|
end
|
||||||
|
|
||||||
|
match 'spec/{vendor,support,specs}.js' do
|
||||||
|
concat ['spec/vendor.js', 'spec/support.js', 'spec/specs.js'], 'specs.js'
|
||||||
|
end
|
||||||
|
|
||||||
|
match %r(^(?!vendor|spec).*\.js$) do
|
||||||
modules = proc { |input| input.path.gsub(%r((^app/|lib/|\.js$)), '') }
|
modules = proc { |input| input.path.gsub(%r((^app/|lib/|\.js$)), '') }
|
||||||
minispade(string: assets.development?, rewrite_requires: true, module_id_generator: modules)
|
minispade(string: assets.development?, rewrite_requires: true, module_id_generator: modules)
|
||||||
end
|
end
|
||||||
|
|
||||||
match '**/*.js' do
|
match %r(^(?!spec).*\.js$) do
|
||||||
concat ['vendor.js'], ['app.js', 'min/app.js']
|
concat ['vendor.js'], ['app.js', 'min/app.js']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
12
Gemfile.lock
12
Gemfile.lock
|
@ -43,7 +43,7 @@ GIT
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/travis-ci/travis-api.git
|
remote: git://github.com/travis-ci/travis-api.git
|
||||||
revision: 6b02ffabacd4476e1a0b4d7f150d0733cfbb57d9
|
revision: 816ebc66c8b65c44d6144e721b1b4f048e86d7df
|
||||||
specs:
|
specs:
|
||||||
travis-api (0.0.1)
|
travis-api (0.0.1)
|
||||||
backports (~> 2.5)
|
backports (~> 2.5)
|
||||||
|
@ -61,7 +61,7 @@ GIT
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/travis-ci/travis-core.git
|
remote: git://github.com/travis-ci/travis-core.git
|
||||||
revision: 310d93a0c6dec233a15264172168fc58fb243f3b
|
revision: 56ca16046cba99cc0b4cd0c520c6bb13ace9932a
|
||||||
branch: sf-travis-api
|
branch: sf-travis-api
|
||||||
specs:
|
specs:
|
||||||
travis-core (0.0.1)
|
travis-core (0.0.1)
|
||||||
|
@ -143,13 +143,13 @@ GEM
|
||||||
data_migrations (0.0.1)
|
data_migrations (0.0.1)
|
||||||
activerecord
|
activerecord
|
||||||
rake
|
rake
|
||||||
debugger (1.2.0)
|
debugger (1.2.1)
|
||||||
columnize (>= 0.3.1)
|
columnize (>= 0.3.1)
|
||||||
debugger-linecache (~> 1.1.1)
|
debugger-linecache (~> 1.1.1)
|
||||||
debugger-ruby_core_source (~> 1.1.3)
|
debugger-ruby_core_source (~> 1.1.4)
|
||||||
debugger-linecache (1.1.2)
|
debugger-linecache (1.1.2)
|
||||||
debugger-ruby_core_source (>= 1.1.1)
|
debugger-ruby_core_source (>= 1.1.1)
|
||||||
debugger-ruby_core_source (1.1.3)
|
debugger-ruby_core_source (1.1.4)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.1.3)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
eventmachine (1.0.0)
|
eventmachine (1.0.0)
|
||||||
|
@ -273,7 +273,7 @@ GEM
|
||||||
kgio (~> 2.6)
|
kgio (~> 2.6)
|
||||||
rack
|
rack
|
||||||
raindrops (~> 0.7)
|
raindrops (~> 0.7)
|
||||||
yard (0.8.2.1)
|
yard (0.8.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
20
assets/scripts/app/models/event.coffee
Normal file
20
assets/scripts/app/models/event.coffee
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
require 'travis/model'
|
||||||
|
|
||||||
|
@Travis.Event = Travis.Model.extend
|
||||||
|
event: DS.attr('string')
|
||||||
|
repoId: DS.attr('number', key: 'repository_id')
|
||||||
|
createdAt: DS.attr('string', key: 'created_at')
|
||||||
|
|
||||||
|
message: (->
|
||||||
|
message = "#{@get('event')}: #{@get('_data.result')}"
|
||||||
|
message = "#{message}: #{@get('_data.message')}"
|
||||||
|
message
|
||||||
|
).property('_data.result', '_data.message')
|
||||||
|
|
||||||
|
_data: (->
|
||||||
|
@get('data.data')
|
||||||
|
).property('data.data')
|
||||||
|
|
||||||
|
@Travis.Event.reopenClass
|
||||||
|
byRepoId: (id) ->
|
||||||
|
@find repository_id: id
|
|
@ -15,7 +15,11 @@ require 'travis/model'
|
||||||
builds: (->
|
builds: (->
|
||||||
id = @get('id')
|
id = @get('id')
|
||||||
builds = Travis.Build.byRepoId id, event_type: 'push'
|
builds = Travis.Build.byRepoId id, event_type: 'push'
|
||||||
array = Travis.ExpandableRecordArray.create(type: Travis.Build, content: Ember.A([]), store: @get('store'))
|
array = Travis.ExpandableRecordArray.create
|
||||||
|
type: Travis.Build
|
||||||
|
content: Ember.A([])
|
||||||
|
store: @get('store')
|
||||||
|
|
||||||
array.load(builds)
|
array.load(builds)
|
||||||
array
|
array
|
||||||
).property()
|
).property()
|
||||||
|
|
26
assets/scripts/app/templates/events/list.hbs
Normal file
26
assets/scripts/app/templates/events/list.hbs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{{#if view.events.isLoaded}}
|
||||||
|
<table id="events" class="list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Message</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{#each event in view.events}}
|
||||||
|
{{#view Travis.EventsItemView contextBinding="event"}}
|
||||||
|
<td class="created_at">
|
||||||
|
{{formatTime createdAt}}
|
||||||
|
</td>
|
||||||
|
<td class="message">
|
||||||
|
{{event.message}}
|
||||||
|
</td>
|
||||||
|
{{/view}}
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{else}}
|
||||||
|
<div class="loading"><span>Loading</span></div>
|
||||||
|
{{/if}}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
@Travis.reopen
|
@Travis.reopen
|
||||||
ApplicationView: Travis.View.extend
|
ApplicationView: Travis.View.extend
|
||||||
templateName: 'application'
|
templateName: 'application'
|
||||||
|
classNames: ['application']
|
||||||
|
|
||||||
localeDidChange: (->
|
localeDidChange: (->
|
||||||
if locale = Travis.app.get('auth.user.locale')
|
if locale = Travis.app.get('auth.user.locale')
|
||||||
|
|
8
assets/scripts/app/views/events.coffee
Normal file
8
assets/scripts/app/views/events.coffee
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
@Travis.reopen
|
||||||
|
EventsView: Travis.View.extend
|
||||||
|
templateName: 'events/list'
|
||||||
|
eventsBinding: 'controller.events'
|
||||||
|
|
||||||
|
EventsItemView: Travis.View.extend
|
||||||
|
tagName: 'tr'
|
||||||
|
|
|
@ -14,11 +14,6 @@ describe 'events', ->
|
||||||
payload =
|
payload =
|
||||||
repository:
|
repository:
|
||||||
id: 10
|
id: 10
|
||||||
slug: 'travis-ci/travis-support'
|
|
||||||
last_build_id: 10
|
|
||||||
last_build_number: 10
|
|
||||||
last_build_started_at: '2012-07-02T00:01:00Z'
|
|
||||||
last_build_finished_at: '2012-07-02T00:02:30Z'
|
|
||||||
build:
|
build:
|
||||||
id: 10
|
id: 10
|
||||||
repository_id: 10
|
repository_id: 10
|
||||||
|
@ -32,6 +27,13 @@ describe 'events', ->
|
||||||
Travis.app.receive 'build:started',
|
Travis.app.receive 'build:started',
|
||||||
build:
|
build:
|
||||||
id: 10
|
id: 10
|
||||||
|
repository:
|
||||||
|
id: 10
|
||||||
|
slug: 'travis-ci/travis-support'
|
||||||
|
last_build_id: 10
|
||||||
|
last_build_number: 10
|
||||||
|
last_build_started_at: '2012-07-02T00:01:00Z'
|
||||||
|
last_build_finished_at: '2012-07-02T00:02:30Z'
|
||||||
|
|
||||||
waits(100)
|
waits(100)
|
||||||
runs ->
|
runs ->
|
||||||
|
@ -39,45 +41,45 @@ describe 'events', ->
|
||||||
row: 2
|
row: 2
|
||||||
item: { slug: 'travis-ci/travis-support', build: { number: 4, url: '/travis-ci/travis-support/builds/10', duration: '1 min 30 sec', finishedAt: 'less than a minute ago' } }
|
item: { slug: 'travis-ci/travis-support', build: { number: 4, url: '/travis-ci/travis-support/builds/10', duration: '1 min 30 sec', finishedAt: 'less than a minute ago' } }
|
||||||
|
|
||||||
describe 'an event adding a build', ->
|
# describe 'an event adding a build', ->
|
||||||
beforeEach ->
|
# beforeEach ->
|
||||||
app 'travis-ci/travis-core/builds'
|
# app 'travis-ci/travis-core/builds'
|
||||||
waitFor buildsRendered
|
# waitFor buildsRendered
|
||||||
|
#
|
||||||
it 'adds a build to the builds list', ->
|
# it 'adds a build to the builds list', ->
|
||||||
payload =
|
# payload =
|
||||||
build:
|
# build:
|
||||||
id: 11
|
# id: 11
|
||||||
repository_id: 1
|
# repository_id: 1
|
||||||
commit_id: 11
|
# commit_id: 11
|
||||||
number: '3'
|
# number: '3'
|
||||||
duration: 55
|
# duration: 55
|
||||||
started_at: '2012-07-02T00:02:00Z'
|
# started_at: '2012-07-02T00:02:00Z'
|
||||||
finished_at: '2012-07-02T00:02:55Z'
|
# finished_at: '2012-07-02T00:02:55Z'
|
||||||
event_type: 'push'
|
# event_type: 'push'
|
||||||
result: 1
|
# result: 1
|
||||||
commit:
|
# commit:
|
||||||
id: 11
|
# id: 11
|
||||||
sha: '1234567'
|
# sha: '1234567'
|
||||||
branch: 'master'
|
# branch: 'master'
|
||||||
message: 'commit message 3'
|
# message: 'commit message 3'
|
||||||
|
#
|
||||||
|
#
|
||||||
$.mockjax
|
# $.mockjax
|
||||||
url: '/builds/11'
|
# url: '/builds/11'
|
||||||
responseTime: 0
|
# responseTime: 0
|
||||||
responseText: payload
|
# responseText: payload
|
||||||
|
#
|
||||||
Em.run ->
|
# Em.run ->
|
||||||
Travis.app.receive 'build:started',
|
# Travis.app.receive 'build:started',
|
||||||
build:
|
# build:
|
||||||
id: 11
|
# id: 11
|
||||||
|
#
|
||||||
waits(100)
|
# waits(100)
|
||||||
runs ->
|
# runs ->
|
||||||
listsBuild
|
# listsBuild
|
||||||
row: 3
|
# row: 3
|
||||||
item: { id: 11, slug: 'travis-ci/travis-core', number: '3', sha: '1234567', branch: 'master', message: 'commit message 3', finishedAt: 'less than a minute ago', duration: '55 sec', color: 'red' }
|
# item: { id: 11, slug: 'travis-ci/travis-core', number: '3', sha: '1234567', branch: 'master', message: 'commit message 3', finishedAt: 'less than a minute ago', duration: '55 sec', color: 'red' }
|
||||||
|
|
||||||
describe 'an event adding a job', ->
|
describe 'an event adding a job', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@ -90,15 +92,6 @@ describe 'events', ->
|
||||||
payload =
|
payload =
|
||||||
job:
|
job:
|
||||||
id: 15
|
id: 15
|
||||||
repository_id: 1
|
|
||||||
build_id: 1
|
|
||||||
commit_id: 1
|
|
||||||
log_id: 1
|
|
||||||
number: '1.4'
|
|
||||||
duration: 55
|
|
||||||
started_at: '2012-07-02T00:02:00Z'
|
|
||||||
finished_at: '2012-07-02T00:02:55Z'
|
|
||||||
config: { rvm: 'jruby' }
|
|
||||||
|
|
||||||
$.mockjax
|
$.mockjax
|
||||||
url: '/jobs/15'
|
url: '/jobs/15'
|
||||||
|
@ -109,7 +102,15 @@ describe 'events', ->
|
||||||
Travis.app.receive 'job:started',
|
Travis.app.receive 'job:started',
|
||||||
job:
|
job:
|
||||||
id: 15
|
id: 15
|
||||||
|
repository_id: 1
|
||||||
build_id: 1
|
build_id: 1
|
||||||
|
commit_id: 1
|
||||||
|
log_id: 1
|
||||||
|
number: '1.4'
|
||||||
|
duration: 55
|
||||||
|
started_at: '2012-07-02T00:02:00Z'
|
||||||
|
finished_at: '2012-07-02T00:02:55Z'
|
||||||
|
config: { rvm: 'jruby' }
|
||||||
|
|
||||||
waits(100)
|
waits(100)
|
||||||
runs ->
|
runs ->
|
||||||
|
@ -124,7 +125,7 @@ describe 'events', ->
|
||||||
id: 12
|
id: 12
|
||||||
repository_id: 1
|
repository_id: 1
|
||||||
number: '1.4'
|
number: '1.4'
|
||||||
queue: 'common'
|
queue: 'builds.common'
|
||||||
|
|
||||||
$.mockjax
|
$.mockjax
|
||||||
url: '/jobs/12'
|
url: '/jobs/12'
|
||||||
|
@ -135,6 +136,10 @@ describe 'events', ->
|
||||||
Travis.app.receive 'job:started',
|
Travis.app.receive 'job:started',
|
||||||
job:
|
job:
|
||||||
id: 12
|
id: 12
|
||||||
|
repository_id: 1
|
||||||
|
number: '1.4'
|
||||||
|
queue: 'builds.common'
|
||||||
|
state: 'created'
|
||||||
|
|
||||||
waits(100)
|
waits(100)
|
||||||
runs ->
|
runs ->
|
32
assets/scripts/spec/spec_helper.coffee
Normal file
32
assets/scripts/spec/spec_helper.coffee
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
minispade.require 'app'
|
||||||
|
|
||||||
|
@reset = ->
|
||||||
|
Em.run ->
|
||||||
|
if Travis.app
|
||||||
|
if Travis.app.store
|
||||||
|
Travis.app.store.destroy()
|
||||||
|
Travis.app.destroy()
|
||||||
|
delete Travis.app
|
||||||
|
delete Travis.store
|
||||||
|
|
||||||
|
waits(500) # TODO not sure what we need to wait for here
|
||||||
|
$('#application').remove()
|
||||||
|
$('body').append( $('<div id="application"></div>') )
|
||||||
|
|
||||||
|
@app = (url) ->
|
||||||
|
reset()
|
||||||
|
Em.run ->
|
||||||
|
Travis.run(rootElement: $('#application'))
|
||||||
|
waitFor -> Travis.app
|
||||||
|
# TODO: so much waiting here, I'm sure we can minimize this
|
||||||
|
runs ->
|
||||||
|
url = "/#{url}" if url && !url.match(/^\//)
|
||||||
|
Travis.app.router.route(url)
|
||||||
|
waits 100
|
||||||
|
runs ->
|
||||||
|
foo = 'bar'
|
||||||
|
|
||||||
|
_Date = Date
|
||||||
|
@Date = (date) ->
|
||||||
|
new _Date(date || '2012-07-02T00:03:00Z')
|
||||||
|
@Date.UTC = _Date.UTC
|
|
@ -4,7 +4,7 @@
|
||||||
@hasText = (selector, text) ->
|
@hasText = (selector, text) ->
|
||||||
-> $(selector).text().trim() == text
|
-> $(selector).text().trim() == text
|
||||||
|
|
||||||
@reposRendered = notEmpty('#repos li a.current')
|
@reposRendered = notEmpty('#repos li.selected')
|
||||||
@buildRendered = notEmpty('#summary .number')
|
@buildRendered = notEmpty('#summary .number')
|
||||||
@buildsRendered = notEmpty('#builds .number')
|
@buildsRendered = notEmpty('#builds .number')
|
||||||
@jobRendered = notEmpty('#summary .number')
|
@jobRendered = notEmpty('#summary .number')
|
|
@ -1,11 +1,11 @@
|
||||||
@displaysRepository = (repo) ->
|
@displaysRepository = (repo) ->
|
||||||
expect($('#repository h3 a').attr('href')).toEqual (repo.href)
|
expect($('#repo h3 a').attr('href')).toEqual (repo.href)
|
||||||
|
|
||||||
@displaysTabs = (tabs) ->
|
@displaysTabs = (tabs) ->
|
||||||
for name, tab of tabs
|
for name, tab of tabs
|
||||||
expect($("#tab_#{name} a").attr('href')).toEqual tab.href unless tab.hidden
|
expect($("#tab_#{name} a").attr('href')).toEqual tab.href unless tab.hidden
|
||||||
expect($("#tab_#{name}").hasClass('active')).toEqual !!tab.active
|
expect($("#tab_#{name}").hasClass('active')).toEqual !!tab.active
|
||||||
expect($("#tab_#{name}").hasClass('display')).toEqual !tab.hidden if name in ['build', 'job']
|
expect($("#tab_#{name}").hasClass('display-inline')).toEqual !tab.hidden if name in ['build', 'job']
|
||||||
|
|
||||||
@displaysSummary = (data) ->
|
@displaysSummary = (data) ->
|
||||||
element = $('#summary .left:first-child dt:first-child')
|
element = $('#summary .left:first-child dt:first-child')
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
@displaysLog = (lines) ->
|
@displaysLog = (lines) ->
|
||||||
ix = 0
|
ix = 0
|
||||||
log = $.map(lines, (line) -> ix += 1; "#{ix}#{line}").join("\n")
|
log = $.map(lines, (line) -> ix += 1; "#{ix}#{line}").join("\n")
|
||||||
expect($('#log').text().trim()).toEqual log
|
expect($('#log p').text().trim()).toEqual log
|
||||||
|
|
||||||
@listsRepos = (items) ->
|
@listsRepos = (items) ->
|
||||||
listsItems('repo', items)
|
listsItems('repo', items)
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
row = $('#repos li')[data.row - 1]
|
row = $('#repos li')[data.row - 1]
|
||||||
repo = data.item
|
repo = data.item
|
||||||
|
|
||||||
expect($('a.current', row).attr('href')).toEqual "/#{repo.slug}"
|
expect($('a.slug', row).attr('href')).toEqual "/#{repo.slug}"
|
||||||
expect($('a.last_build', row).attr('href')).toEqual repo.build.url
|
expect($('a.last_build', row).attr('href')).toEqual repo.build.url
|
||||||
expect($('.duration', row).text()).toEqual repo.build.duration
|
expect($('.duration', row).text()).toEqual repo.build.duration
|
||||||
expect($('.finished_at', row).text()).toEqual repo.build.finishedAt
|
expect($('.finished_at', row).text()).toEqual repo.build.finishedAt
|
||||||
|
@ -81,19 +81,19 @@
|
||||||
expect(element.attr('class')).toMatch job.color
|
expect(element.attr('class')).toMatch job.color
|
||||||
|
|
||||||
element = $("td.number", row)
|
element = $("td.number", row)
|
||||||
expect(element.text()).toEqual job.number
|
expect(element.text().trim()).toEqual job.number
|
||||||
|
|
||||||
element = $("td.number a", row)
|
element = $("td.number a", row)
|
||||||
expect(element.attr('href')).toEqual "/#{job.repo}/jobs/#{job.id}"
|
expect(element.attr('href')).toEqual "/#{job.repo}/jobs/#{job.id}"
|
||||||
|
|
||||||
element = $("td.duration", row)
|
element = $("td.duration", row)
|
||||||
expect(element.text()).toEqual job.duration
|
expect(element.text().trim()).toEqual job.duration
|
||||||
|
|
||||||
element = $("td.finished_at", row)
|
element = $("td.finished_at", row)
|
||||||
expect(element.text()).toEqual job.finishedAt
|
expect(element.text().trim()).toEqual job.finishedAt
|
||||||
|
|
||||||
element = $("td:nth-child(6)", row)
|
element = $("td:nth-child(6)", row)
|
||||||
expect(element.text()).toEqual job.rvm
|
expect(element.text().trim()).toEqual job.rvm
|
||||||
|
|
||||||
@listsQueuedJobs = (jobs) ->
|
@listsQueuedJobs = (jobs) ->
|
||||||
listsItems('queuedJob', jobs)
|
listsItems('queuedJob', jobs)
|
|
@ -1,5 +1,3 @@
|
||||||
require 'ext/jquery'
|
|
||||||
|
|
||||||
responseTime = 0
|
responseTime = 0
|
||||||
|
|
||||||
repos = [
|
repos = [
|
||||||
|
@ -29,8 +27,8 @@ jobs = [
|
||||||
{ id: 4, repository_id: 1, build_id: 2, commit_id: 2, log_id: 4, number: '2.1', config: { rvm: 'rbx' } }
|
{ id: 4, repository_id: 1, build_id: 2, commit_id: 2, log_id: 4, number: '2.1', config: { rvm: 'rbx' } }
|
||||||
{ id: 5, repository_id: 2, build_id: 3, commit_id: 3, log_id: 5, number: '3.1', config: { rvm: 'rbx' }, duration: 30, started_at: '2012-07-02T00:01:00Z', finished_at: '2012-07-02T00:01:30Z', result: 1 }
|
{ id: 5, repository_id: 2, build_id: 3, commit_id: 3, log_id: 5, number: '3.1', config: { rvm: 'rbx' }, duration: 30, started_at: '2012-07-02T00:01:00Z', finished_at: '2012-07-02T00:01:30Z', result: 1 }
|
||||||
{ id: 6, repository_id: 3, build_id: 4, commit_id: 4, log_id: 6, number: '4.1', config: { rvm: 'rbx' }, started_at: '2012-07-02T00:02:00Z' }
|
{ id: 6, repository_id: 3, build_id: 4, commit_id: 4, log_id: 6, number: '4.1', config: { rvm: 'rbx' }, started_at: '2012-07-02T00:02:00Z' }
|
||||||
{ id: 7, repository_id: 1, build_id: 5, commit_id: 5, log_id: 7, number: '5.1', config: { rvm: 'rbx' }, state: 'created', queue: 'common' }
|
{ id: 7, repository_id: 1, build_id: 5, commit_id: 5, log_id: 7, number: '5.1', config: { rvm: 'rbx' }, state: 'created', queue: 'builds.common' }
|
||||||
{ id: 8, repository_id: 1, build_id: 5, commit_id: 5, log_id: 8, number: '5.2', config: { rvm: 'rbx' }, state: 'created', queue: 'common' }
|
{ id: 8, repository_id: 1, build_id: 5, commit_id: 5, log_id: 8, number: '5.2', config: { rvm: 'rbx' }, state: 'created', queue: 'builds.common' }
|
||||||
]
|
]
|
||||||
|
|
||||||
artifacts = [
|
artifacts = [
|
||||||
|
@ -95,7 +93,7 @@ for repository in repos
|
||||||
|
|
||||||
$.mockjax
|
$.mockjax
|
||||||
url: '/builds'
|
url: '/builds'
|
||||||
data: { repository_id: repository.id, event_type: 'push', orderBy: 'number DESC' }
|
data: { repository_id: repository.id, event_type: 'push' }
|
||||||
responseTime: responseTime
|
responseTime: responseTime
|
||||||
responseText:
|
responseText:
|
||||||
builds: (builds[id - 1] for id in repository.build_ids)
|
builds: (builds[id - 1] for id in repository.build_ids)
|
523
assets/scripts/spec/vendor/jquery.mockjax.js
vendored
Normal file
523
assets/scripts/spec/vendor/jquery.mockjax.js
vendored
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
/*!
|
||||||
|
* MockJax - jQuery Plugin to Mock Ajax requests
|
||||||
|
*
|
||||||
|
* Version: 1.5.1
|
||||||
|
* Released:
|
||||||
|
* Home: http://github.com/appendto/jquery-mockjax
|
||||||
|
* Author: Jonathan Sharp (http://jdsharp.com)
|
||||||
|
* License: MIT,GPL
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 appendTo LLC.
|
||||||
|
* Dual licensed under the MIT or GPL licenses.
|
||||||
|
* http://appendto.com/open-source-licenses
|
||||||
|
*/
|
||||||
|
(function($) {
|
||||||
|
var _ajax = $.ajax,
|
||||||
|
mockHandlers = [],
|
||||||
|
CALLBACK_REGEX = /=\?(&|$)/,
|
||||||
|
jsc = (new Date()).getTime();
|
||||||
|
|
||||||
|
|
||||||
|
// Parse the given XML string.
|
||||||
|
function parseXML(xml) {
|
||||||
|
if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
|
||||||
|
DOMParser = function() { };
|
||||||
|
DOMParser.prototype.parseFromString = function( xmlString ) {
|
||||||
|
var doc = new ActiveXObject('Microsoft.XMLDOM');
|
||||||
|
doc.async = 'false';
|
||||||
|
doc.loadXML( xmlString );
|
||||||
|
return doc;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
|
||||||
|
if ( $.isXMLDoc( xmlDoc ) ) {
|
||||||
|
var err = $('parsererror', xmlDoc);
|
||||||
|
if ( err.length == 1 ) {
|
||||||
|
throw('Error: ' + $(xmlDoc).text() );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw('Unable to parse XML');
|
||||||
|
}
|
||||||
|
} catch( e ) {
|
||||||
|
var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
|
||||||
|
$(document).trigger('xmlParseError', [ msg ]);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return xmlDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger a jQuery event
|
||||||
|
function trigger(s, type, args) {
|
||||||
|
(s.context ? $(s.context) : $.event).trigger(type, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the data field on the mock handler and the request match. This
|
||||||
|
// can be used to restrict a mock handler to being used only when a certain
|
||||||
|
// set of data is passed to it.
|
||||||
|
function isMockDataEqual( mock, live ) {
|
||||||
|
var identical = false;
|
||||||
|
// Test for situations where the data is a querystring (not an object)
|
||||||
|
if (typeof live === 'string') {
|
||||||
|
// Querystring may be a regex
|
||||||
|
return $.isFunction( mock.test ) ? mock.test(live) : mock == live;
|
||||||
|
}
|
||||||
|
$.each(mock, function(k, v) {
|
||||||
|
if ( live[k] === undefined ) {
|
||||||
|
identical = false;
|
||||||
|
return identical;
|
||||||
|
} else {
|
||||||
|
identical = true;
|
||||||
|
if ( typeof live[k] == 'object' ) {
|
||||||
|
return isMockDataEqual(mock[k], live[k]);
|
||||||
|
} else {
|
||||||
|
if ( $.isFunction( mock[k].test ) ) {
|
||||||
|
identical = mock[k].test(live[k]);
|
||||||
|
} else {
|
||||||
|
identical = ( mock[k] == live[k] );
|
||||||
|
}
|
||||||
|
return identical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return identical;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the given handler should mock the given request
|
||||||
|
function getMockForRequest( handler, requestSettings ) {
|
||||||
|
// If the mock was registered with a function, let the function decide if we
|
||||||
|
// want to mock this request
|
||||||
|
if ( $.isFunction(handler) ) {
|
||||||
|
return handler( requestSettings );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect the URL of the request and check if the mock handler's url
|
||||||
|
// matches the url for this ajax request
|
||||||
|
if ( $.isFunction(handler.url.test) ) {
|
||||||
|
// The user provided a regex for the url, test it
|
||||||
|
if ( !handler.url.test( requestSettings.url ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Look for a simple wildcard '*' or a direct URL match
|
||||||
|
var star = handler.url.indexOf('*');
|
||||||
|
if (handler.url !== requestSettings.url && star === -1 ||
|
||||||
|
!new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace('*', '.+')).test(requestSettings.url)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect the data submitted in the request (either POST body or GET query string)
|
||||||
|
if ( handler.data && requestSettings.data ) {
|
||||||
|
if ( !isMockDataEqual(handler.data, requestSettings.data) ) {
|
||||||
|
// They're not identical, do not mock this request
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Inspect the request type
|
||||||
|
if ( handler && handler.type &&
|
||||||
|
handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) {
|
||||||
|
// The request type doesn't match (GET vs. POST)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If logging is enabled, log the mock to the console
|
||||||
|
function logMock( mockHandler, requestSettings ) {
|
||||||
|
var c = $.extend({}, $.mockjaxSettings, mockHandler);
|
||||||
|
if ( c.log && $.isFunction(c.log) ) {
|
||||||
|
c.log('MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url, $.extend({}, requestSettings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the xhr objects send operation
|
||||||
|
function _xhrSend(mockHandler, requestSettings, origSettings) {
|
||||||
|
|
||||||
|
// This is a substitute for < 1.4 which lacks $.proxy
|
||||||
|
var process = (function(that) {
|
||||||
|
return function() {
|
||||||
|
return (function() {
|
||||||
|
// The request has returned
|
||||||
|
this.status = mockHandler.status;
|
||||||
|
this.statusText = mockHandler.statusText;
|
||||||
|
this.readyState = 4;
|
||||||
|
|
||||||
|
// We have an executable function, call it to give
|
||||||
|
// the mock handler a chance to update it's data
|
||||||
|
if ( $.isFunction(mockHandler.response) ) {
|
||||||
|
mockHandler.response(origSettings);
|
||||||
|
}
|
||||||
|
// Copy over our mock to our xhr object before passing control back to
|
||||||
|
// jQuery's onreadystatechange callback
|
||||||
|
if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) {
|
||||||
|
this.responseText = JSON.stringify(mockHandler.responseText);
|
||||||
|
} else if ( requestSettings.dataType == 'xml' ) {
|
||||||
|
if ( typeof mockHandler.responseXML == 'string' ) {
|
||||||
|
this.responseXML = parseXML(mockHandler.responseXML);
|
||||||
|
} else {
|
||||||
|
this.responseXML = mockHandler.responseXML;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.responseText = mockHandler.responseText;
|
||||||
|
}
|
||||||
|
if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) {
|
||||||
|
this.status = mockHandler.status;
|
||||||
|
}
|
||||||
|
if( typeof mockHandler.statusText === "string") {
|
||||||
|
this.statusText = mockHandler.statusText;
|
||||||
|
}
|
||||||
|
// jQuery < 1.4 doesn't have onreadystate change for xhr
|
||||||
|
if ( $.isFunction(this.onreadystatechange) ) {
|
||||||
|
if( mockHandler.isTimeout) {
|
||||||
|
this.status = -1;
|
||||||
|
}
|
||||||
|
this.onreadystatechange( mockHandler.isTimeout ? 'timeout' : undefined );
|
||||||
|
} else if ( mockHandler.isTimeout ) {
|
||||||
|
// Fix for 1.3.2 timeout to keep success from firing.
|
||||||
|
this.status = -1;
|
||||||
|
}
|
||||||
|
}).apply(that);
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
|
||||||
|
if ( mockHandler.proxy ) {
|
||||||
|
// We're proxying this request and loading in an external file instead
|
||||||
|
_ajax({
|
||||||
|
global: false,
|
||||||
|
url: mockHandler.proxy,
|
||||||
|
type: mockHandler.proxyType,
|
||||||
|
data: mockHandler.data,
|
||||||
|
dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType,
|
||||||
|
complete: function(xhr, txt) {
|
||||||
|
mockHandler.responseXML = xhr.responseXML;
|
||||||
|
mockHandler.responseText = xhr.responseText;
|
||||||
|
mockHandler.status = xhr.status;
|
||||||
|
mockHandler.statusText = xhr.statusText;
|
||||||
|
this.responseTimer = setTimeout(process, mockHandler.responseTime || 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// type == 'POST' || 'GET' || 'DELETE'
|
||||||
|
if ( requestSettings.async === false ) {
|
||||||
|
// TODO: Blocking delay
|
||||||
|
process();
|
||||||
|
} else {
|
||||||
|
this.responseTimer = setTimeout(process, mockHandler.responseTime || 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a mocked XHR Object
|
||||||
|
function xhr(mockHandler, requestSettings, origSettings, origHandler) {
|
||||||
|
// Extend with our default mockjax settings
|
||||||
|
mockHandler = $.extend({}, $.mockjaxSettings, mockHandler);
|
||||||
|
|
||||||
|
if (typeof mockHandler.headers === 'undefined') {
|
||||||
|
mockHandler.headers = {};
|
||||||
|
}
|
||||||
|
if ( mockHandler.contentType ) {
|
||||||
|
mockHandler.headers['content-type'] = mockHandler.contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: mockHandler.status,
|
||||||
|
statusText: mockHandler.statusText,
|
||||||
|
readyState: 1,
|
||||||
|
open: function() { },
|
||||||
|
send: function() {
|
||||||
|
origHandler.fired = true;
|
||||||
|
_xhrSend.call(this, mockHandler, requestSettings, origSettings);
|
||||||
|
},
|
||||||
|
abort: function() {
|
||||||
|
clearTimeout(this.responseTimer);
|
||||||
|
},
|
||||||
|
setRequestHeader: function(header, value) {
|
||||||
|
mockHandler.headers[header] = value;
|
||||||
|
},
|
||||||
|
getResponseHeader: function(header) {
|
||||||
|
// 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
|
||||||
|
if ( mockHandler.headers && mockHandler.headers[header] ) {
|
||||||
|
// Return arbitrary headers
|
||||||
|
return mockHandler.headers[header];
|
||||||
|
} else if ( header.toLowerCase() == 'last-modified' ) {
|
||||||
|
return mockHandler.lastModified || (new Date()).toString();
|
||||||
|
} else if ( header.toLowerCase() == 'etag' ) {
|
||||||
|
return mockHandler.etag || '';
|
||||||
|
} else if ( header.toLowerCase() == 'content-type' ) {
|
||||||
|
return mockHandler.contentType || 'text/plain';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getAllResponseHeaders: function() {
|
||||||
|
var headers = '';
|
||||||
|
$.each(mockHandler.headers, function(k, v) {
|
||||||
|
headers += k + ': ' + v + "\n";
|
||||||
|
});
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process a JSONP mock request.
|
||||||
|
function processJsonpMock( requestSettings, mockHandler, origSettings ) {
|
||||||
|
// Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
|
||||||
|
// because there isn't an easy hook for the cross domain script tag of jsonp
|
||||||
|
|
||||||
|
processJsonpUrl( requestSettings );
|
||||||
|
|
||||||
|
requestSettings.dataType = "json";
|
||||||
|
if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
|
||||||
|
createJsonpCallback(requestSettings, mockHandler);
|
||||||
|
|
||||||
|
// We need to make sure
|
||||||
|
// that a JSONP style response is executed properly
|
||||||
|
|
||||||
|
var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
|
||||||
|
parts = rurl.exec( requestSettings.url ),
|
||||||
|
remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
|
||||||
|
|
||||||
|
requestSettings.dataType = "script";
|
||||||
|
if(requestSettings.type.toUpperCase() === "GET" && remote ) {
|
||||||
|
var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
|
||||||
|
|
||||||
|
// Check if we are supposed to return a Deferred back to the mock call, or just
|
||||||
|
// signal success
|
||||||
|
if(newMockReturn) {
|
||||||
|
return newMockReturn;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the required callback parameter to the end of the request URL, for a JSONP request
|
||||||
|
function processJsonpUrl( requestSettings ) {
|
||||||
|
if ( requestSettings.type.toUpperCase() === "GET" ) {
|
||||||
|
if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
|
||||||
|
requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") +
|
||||||
|
(requestSettings.jsonp || "callback") + "=?";
|
||||||
|
}
|
||||||
|
} else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
|
||||||
|
requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process a JSONP request by evaluating the mocked response text
|
||||||
|
function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
|
||||||
|
// Synthesize the mock request for adding a script tag
|
||||||
|
var callbackContext = origSettings && origSettings.context || requestSettings,
|
||||||
|
newMock = null;
|
||||||
|
|
||||||
|
|
||||||
|
// If the response handler on the moock is a function, call it
|
||||||
|
if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
|
||||||
|
mockHandler.response(origSettings);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Evaluate the responseText javascript in a global context
|
||||||
|
if( typeof mockHandler.responseText === 'object' ) {
|
||||||
|
$.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
|
||||||
|
} else {
|
||||||
|
$.globalEval( '(' + mockHandler.responseText + ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successful response
|
||||||
|
jsonpSuccess( requestSettings, mockHandler );
|
||||||
|
jsonpComplete( requestSettings, mockHandler );
|
||||||
|
|
||||||
|
// If we are running under jQuery 1.5+, return a deferred object
|
||||||
|
if($.Deferred){
|
||||||
|
newMock = new $.Deferred();
|
||||||
|
if(typeof mockHandler.responseText == "object"){
|
||||||
|
newMock.resolveWith( callbackContext, [mockHandler.responseText] );
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newMock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the required JSONP callback function for the request
|
||||||
|
function createJsonpCallback( requestSettings, mockHandler ) {
|
||||||
|
jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++);
|
||||||
|
|
||||||
|
// Replace the =? sequence both in the query string and the data
|
||||||
|
if ( requestSettings.data ) {
|
||||||
|
requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1");
|
||||||
|
|
||||||
|
|
||||||
|
// Handle JSONP-style loading
|
||||||
|
window[ jsonp ] = window[ jsonp ] || function( tmp ) {
|
||||||
|
data = tmp;
|
||||||
|
jsonpSuccess( requestSettings, mockHandler );
|
||||||
|
jsonpComplete( requestSettings, mockHandler );
|
||||||
|
// Garbage collect
|
||||||
|
window[ jsonp ] = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
delete window[ jsonp ];
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
if ( head ) {
|
||||||
|
head.removeChild( script );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// The JSONP request was successful
|
||||||
|
function jsonpSuccess(requestSettings, mockHandler) {
|
||||||
|
// If a local callback was specified, fire it and pass it the data
|
||||||
|
if ( requestSettings.success ) {
|
||||||
|
requestSettings.success.call( callbackContext, ( mockHandler.response ? mockHandler.response.toString() : mockHandler.responseText || ''), status, {} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the global callback
|
||||||
|
if ( requestSettings.global ) {
|
||||||
|
trigger(requestSettings, "ajaxSuccess", [{}, requestSettings] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The JSONP request was completed
|
||||||
|
function jsonpComplete(requestSettings, mockHandler) {
|
||||||
|
// Process result
|
||||||
|
if ( requestSettings.complete ) {
|
||||||
|
requestSettings.complete.call( callbackContext, {} , status );
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request was completed
|
||||||
|
if ( requestSettings.global ) {
|
||||||
|
trigger( "ajaxComplete", [{}, requestSettings] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the global AJAX counter
|
||||||
|
if ( requestSettings.global && ! --$.active ) {
|
||||||
|
$.event.trigger( "ajaxStop" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The core $.ajax replacement.
|
||||||
|
function handleAjax( url, origSettings ) {
|
||||||
|
var mockRequest, requestSettings, mockHandler;
|
||||||
|
|
||||||
|
// If url is an object, simulate pre-1.5 signature
|
||||||
|
if ( typeof url === "object" ) {
|
||||||
|
origSettings = url;
|
||||||
|
url = undefined;
|
||||||
|
} else {
|
||||||
|
// work around to support 1.5 signature
|
||||||
|
origSettings.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the original settings for the request
|
||||||
|
requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings);
|
||||||
|
|
||||||
|
// Iterate over our mock handlers (in registration order) until we find
|
||||||
|
// one that is willing to intercept the request
|
||||||
|
for(var k = 0; k < mockHandlers.length; k++) {
|
||||||
|
if ( !mockHandlers[k] ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mockHandler = getMockForRequest( mockHandlers[k], requestSettings );
|
||||||
|
if(!mockHandler) {
|
||||||
|
// No valid mock found for this request
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle console logging
|
||||||
|
logMock( mockHandler, requestSettings );
|
||||||
|
|
||||||
|
|
||||||
|
if ( requestSettings.dataType === "jsonp" ) {
|
||||||
|
if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
|
||||||
|
// This mock will handle the JSONP request
|
||||||
|
return mockRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Removed to fix #54 - keep the mocking data object intact
|
||||||
|
//mockHandler.data = requestSettings.data;
|
||||||
|
|
||||||
|
mockHandler.cache = requestSettings.cache;
|
||||||
|
mockHandler.timeout = requestSettings.timeout;
|
||||||
|
mockHandler.global = requestSettings.global;
|
||||||
|
|
||||||
|
(function(mockHandler, requestSettings, origSettings, origHandler) {
|
||||||
|
mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
|
||||||
|
// Mock the XHR object
|
||||||
|
xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ) }
|
||||||
|
}));
|
||||||
|
})(mockHandler, requestSettings, origSettings, mockHandlers[k]);
|
||||||
|
|
||||||
|
return mockRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't have a mock request, trigger a normal request
|
||||||
|
return _ajax.apply($, [origSettings]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Public
|
||||||
|
|
||||||
|
$.extend({
|
||||||
|
ajax: handleAjax
|
||||||
|
});
|
||||||
|
|
||||||
|
$.mockjaxSettings = {
|
||||||
|
//url: null,
|
||||||
|
//type: 'GET',
|
||||||
|
log: function( msg ) {
|
||||||
|
if ( window[ 'console' ] && window.console.log ) {
|
||||||
|
window.console.log.apply( console, arguments );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
responseTime: 500,
|
||||||
|
isTimeout: false,
|
||||||
|
contentType: 'text/plain',
|
||||||
|
response: '',
|
||||||
|
responseText: '',
|
||||||
|
responseXML: '',
|
||||||
|
proxy: '',
|
||||||
|
proxyType: 'GET',
|
||||||
|
|
||||||
|
lastModified: null,
|
||||||
|
etag: '',
|
||||||
|
headers: {
|
||||||
|
etag: 'IJF@H#@923uf8023hFO@I#H#',
|
||||||
|
'content-type' : 'text/plain'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.mockjax = function(settings) {
|
||||||
|
var i = mockHandlers.length;
|
||||||
|
mockHandlers[i] = settings;
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
$.mockjaxClear = function(i) {
|
||||||
|
if ( arguments.length == 1 ) {
|
||||||
|
mockHandlers[i] = null;
|
||||||
|
} else {
|
||||||
|
mockHandlers = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$.mockjax.handler = function(i) {
|
||||||
|
if ( arguments.length == 1 ) {
|
||||||
|
return mockHandlers[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
|
@ -5,12 +5,12 @@ $left-width: 250px
|
||||||
html, body
|
html, body
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
||||||
body > div
|
.application
|
||||||
width: 100%
|
width: 100%
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
// ouch. ember injects additional divs that somehow don't inherit the actual dimensions
|
// ouch. ember injects additional divs that somehow don't inherit the actual dimensions
|
||||||
body > div, body > div > div
|
.application, .application > div
|
||||||
width: 100%
|
width: 100%
|
||||||
min-height: 100%
|
min-height: 100%
|
||||||
@include display-box
|
@include display-box
|
||||||
|
|
|
@ -8,6 +8,7 @@ module Travis
|
||||||
|
|
||||||
TYPES = [:styles, :scripts, :images, :static, :vendor]
|
TYPES = [:styles, :scripts, :images, :static, :vendor]
|
||||||
VENDOR_ORDER = %w(jquery.min minispade handlebars ember)
|
VENDOR_ORDER = %w(jquery.min minispade handlebars ember)
|
||||||
|
SPEC_VENDOR_ORDER = %w(jasmine jasmine-html jasmine-runner sinon)
|
||||||
|
|
||||||
attr_reader :roots, :env
|
attr_reader :roots, :env
|
||||||
|
|
||||||
|
@ -28,6 +29,10 @@ module Travis
|
||||||
VENDOR_ORDER.map { |name| "vendor/#{name}.js" }
|
VENDOR_ORDER.map { |name| "vendor/#{name}.js" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def spec_vendor_order
|
||||||
|
SPEC_VENDOR_ORDER.map { |name| "spec/vendor/#{name}.js" }
|
||||||
|
end
|
||||||
|
|
||||||
def setup_compass
|
def setup_compass
|
||||||
Compass.configuration.images_path = images.first
|
Compass.configuration.images_path = images.first
|
||||||
styles.each do |path|
|
styles.each do |path|
|
||||||
|
|
|
@ -10,6 +10,13 @@ class Travis::Web::App
|
||||||
super([public_dir, index])
|
super([public_dir, index])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
status, headers, body = super(env)
|
||||||
|
# TODO: temporary hack to make specs work, remove this later properly
|
||||||
|
headers.delete 'Last-Modified' if env['PATH_INFO'] == '/spec.html'
|
||||||
|
[status, headers, body]
|
||||||
|
end
|
||||||
|
|
||||||
def public_dir
|
def public_dir
|
||||||
Rack::File.new('public')
|
Rack::File.new('public')
|
||||||
end
|
end
|
||||||
|
|
File diff suppressed because one or more lines are too long
21
public/scripts/app.min.js
vendored
21
public/scripts/app.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8867
public/scripts/specs.js
Normal file
8867
public/scripts/specs.js
Normal file
File diff suppressed because it is too large
Load Diff
35
public/spec.html
Normal file
35
public/spec.html
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta rel="travis.api_endpoint" href="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Travis CI - Distributed Continuous Integration Platform for the Open Source Community</title>
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.ico">
|
||||||
|
<link rel="stylesheet" href="/styles/app.css">
|
||||||
|
<link rel="stylesheet" href="/styles/jasmine.css">
|
||||||
|
<link rel="stylesheet" href="/styles/jasmine-ext.css">
|
||||||
|
<script src="/scripts/app.js"></script>
|
||||||
|
<script>
|
||||||
|
minispade.require('travis')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="/scripts/specs.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
window.cachedSearch = window.location.search;
|
||||||
|
//for(key in minispade.modules)
|
||||||
|
// if(key.match(/_spec$/))
|
||||||
|
// minispade.require(key);
|
||||||
|
|
||||||
|
var console_reporter = new jasmine.ConsoleReporter();
|
||||||
|
jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
|
||||||
|
jasmine.getEnv().addReporter(console_reporter);
|
||||||
|
jasmine.getEnv().execute();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="application">
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -2526,13 +2526,13 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 8, /Users/sven/Development/projects/travis/travis-web/assets/styles/layout.sass */
|
/* line 8, /Users/sven/Development/projects/travis/travis-web/assets/styles/layout.sass */
|
||||||
body > div {
|
.application {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 13, /Users/sven/Development/projects/travis/travis-web/assets/styles/layout.sass */
|
/* line 13, /Users/sven/Development/projects/travis/travis-web/assets/styles/layout.sass */
|
||||||
body > div, body > div > div {
|
.application, .application > div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
|
11
public/styles/jasmine-ext.css
Normal file
11
public/styles/jasmine-ext.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#HTMLReporter {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
width: 50%;
|
||||||
|
height: 150px;
|
||||||
|
z-index: 1000;
|
||||||
|
background-color: white;
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px solid #A80000;
|
||||||
|
}
|
79
public/styles/jasmine.css
Normal file
79
public/styles/jasmine.css
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
|
||||||
|
#HTMLReporter a { text-decoration: none; }
|
||||||
|
#HTMLReporter a:hover { text-decoration: underline; }
|
||||||
|
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
|
||||||
|
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
|
||||||
|
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
|
||||||
|
#HTMLReporter .version { color: #aaaaaa; }
|
||||||
|
#HTMLReporter .banner { margin-top: 14px; }
|
||||||
|
#HTMLReporter .duration { color: #aaaaaa; float: right; }
|
||||||
|
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
|
||||||
|
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
|
||||||
|
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
|
||||||
|
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
|
||||||
|
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
|
||||||
|
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
|
||||||
|
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
|
||||||
|
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
|
||||||
|
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
|
||||||
|
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
|
||||||
|
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
|
||||||
|
#HTMLReporter .runningAlert { background-color: #666666; }
|
||||||
|
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
|
||||||
|
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
|
||||||
|
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
|
||||||
|
#HTMLReporter .passingAlert { background-color: #a6b779; }
|
||||||
|
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
|
||||||
|
#HTMLReporter .failingAlert { background-color: #cf867e; }
|
||||||
|
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
|
||||||
|
#HTMLReporter .results { margin-top: 14px; }
|
||||||
|
#HTMLReporter #details { display: none; }
|
||||||
|
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
|
||||||
|
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
|
||||||
|
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
|
||||||
|
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
|
||||||
|
#HTMLReporter.showDetails .summary { display: none; }
|
||||||
|
#HTMLReporter.showDetails #details { display: block; }
|
||||||
|
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
|
||||||
|
#HTMLReporter .summary { margin-top: 14px; }
|
||||||
|
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
|
||||||
|
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
|
||||||
|
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
|
||||||
|
#HTMLReporter .description + .suite { margin-top: 0; }
|
||||||
|
#HTMLReporter .suite { margin-top: 14px; }
|
||||||
|
#HTMLReporter .suite a { color: #333333; }
|
||||||
|
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
|
||||||
|
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
|
||||||
|
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
|
||||||
|
#HTMLReporter .resultMessage span.result { display: block; }
|
||||||
|
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
|
||||||
|
|
||||||
|
#TrivialReporter { padding: 8px 13px; clear: both; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
|
||||||
|
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
|
||||||
|
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
|
||||||
|
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
|
||||||
|
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
|
||||||
|
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
|
||||||
|
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
|
||||||
|
#TrivialReporter .runner.running { background-color: yellow; }
|
||||||
|
#TrivialReporter .options { text-align: right; font-size: .8em; }
|
||||||
|
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
|
||||||
|
#TrivialReporter .suite .suite { margin: 5px; }
|
||||||
|
#TrivialReporter .suite.passed { background-color: #dfd; }
|
||||||
|
#TrivialReporter .suite.failed { background-color: #fdd; }
|
||||||
|
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
|
||||||
|
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
|
||||||
|
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
|
||||||
|
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
|
||||||
|
#TrivialReporter .spec.skipped { background-color: #bbb; }
|
||||||
|
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
|
||||||
|
#TrivialReporter .passed { background-color: #cfc; display: none; }
|
||||||
|
#TrivialReporter .failed { background-color: #fbb; }
|
||||||
|
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
|
||||||
|
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
|
||||||
|
#TrivialReporter .resultMessage .mismatch { color: black; }
|
||||||
|
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
|
||||||
|
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
|
||||||
|
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
|
||||||
|
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
|
||||||
|
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
|
|
@ -1 +1 @@
|
||||||
6250e20b
|
4b27d9a7
|
|
@ -1,25 +0,0 @@
|
||||||
minispade.require 'app'
|
|
||||||
|
|
||||||
@reset = ->
|
|
||||||
Em.run ->
|
|
||||||
if Travis.app
|
|
||||||
if Travis.app.store
|
|
||||||
Travis.app.store.destroy()
|
|
||||||
if views = Travis.app.get('_connectedOutletViews')
|
|
||||||
views.forEach (v) -> v.destroy()
|
|
||||||
Travis.app.destroy()
|
|
||||||
|
|
||||||
waits(500) # TODO not sure what we need to wait for here
|
|
||||||
$('#content').remove()
|
|
||||||
$('body').append('<div id="content"></div>')
|
|
||||||
|
|
||||||
@app = (url) ->
|
|
||||||
reset()
|
|
||||||
Em.run ->
|
|
||||||
Travis.run(rootElement: $('#content'))
|
|
||||||
Em.routes.set('location', url)
|
|
||||||
|
|
||||||
_Date = Date
|
|
||||||
@Date = (date) ->
|
|
||||||
new _Date(date || '2012-07-02T00:03:00Z')
|
|
||||||
@Date.UTC = _Date.UTC
|
|
Loading…
Reference in New Issue
Block a user