magi 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +12 -3
- data/Procfile +4 -0
- data/README.md +25 -1
- data/app/assets/stylesheets/application.css +1 -0
- data/app/assets/stylesheets/builds.scss +35 -0
- data/app/assets/stylesheets/common.scss +69 -0
- data/app/assets/stylesheets/jobs.scss +121 -0
- data/app/assets/stylesheets/layout.scss +19 -0
- data/app/assets/stylesheets/mixin.scss +6 -0
- data/app/controllers/application_controller.rb +16 -0
- data/app/controllers/builds_controller.rb +45 -0
- data/app/controllers/jobs_controller.rb +43 -0
- data/app/models/build.rb +39 -0
- data/app/models/job.rb +88 -0
- data/app/views/builds/show.html.slim +36 -0
- data/app/views/jobs/_form.html.slim +27 -0
- data/app/views/jobs/edit.html.slim +9 -0
- data/app/views/jobs/index.html.slim +19 -0
- data/app/views/jobs/new.html.slim +7 -0
- data/app/views/jobs/show.html.slim +24 -0
- data/app/views/layouts/application.html.slim +10 -0
- data/app/workers/build_worker.rb +8 -0
- data/bin/magi +6 -0
- data/config/application.rb +1 -1
- data/config/database.yml +21 -17
- data/config/routes.rb +4 -55
- data/db/migrate/20130531143239_create_jobs.rb +10 -0
- data/db/migrate/20130531155155_create_builds.rb +14 -0
- data/db/schema.rb +35 -0
- data/lib/magi/command.rb +53 -0
- data/lib/magi/executer.rb +31 -0
- data/lib/magi/scheduler.rb +55 -0
- data/lib/magi/version.rb +1 -1
- data/lib/magi.rb +1 -4
- data/magi.gemspec +29 -1
- data/script/clock.rb +5 -0
- data/spec/factories/build.rb +6 -0
- data/spec/factories/job.rb +7 -0
- data/spec/models/build_spec.rb +35 -0
- data/spec/models/job_spec.rb +54 -0
- data/spec/requests/builds_spec.rb +68 -0
- data/spec/requests/jobs_spec.rb +93 -0
- data/spec/spec_helper.rb +28 -0
- metadata +324 -50
- data/.gitignore +0 -19
- data/app/mailers/.gitkeep +0 -0
- data/app/models/.gitkeep +0 -0
- data/app/views/layouts/application.html.erb +0 -14
- data/doc/README_FOR_APP +0 -2
- data/lib/assets/.gitkeep +0 -0
- data/lib/tasks/.gitkeep +0 -0
- data/log/.gitkeep +0 -0
- data/public/index.html +0 -241
- data/test/fixtures/.gitkeep +0 -0
- data/test/functional/.gitkeep +0 -0
- data/test/integration/.gitkeep +0 -0
- data/test/performance/browsing_test.rb +0 -12
- data/test/test_helper.rb +0 -13
- data/test/unit/.gitkeep +0 -0
- data/vendor/assets/javascripts/.gitkeep +0 -0
- data/vendor/assets/stylesheets/.gitkeep +0 -0
- data/vendor/plugins/.gitkeep +0 -0
data/bin/magi
ADDED
data/config/application.rb
CHANGED
@@ -16,7 +16,7 @@ module Magi
|
|
16
16
|
# -- all .rb files in that directory are automatically loaded.
|
17
17
|
|
18
18
|
# Custom directories with classes and modules you want to be autoloadable.
|
19
|
-
|
19
|
+
config.autoload_paths += %W(#{config.root}/lib)
|
20
20
|
|
21
21
|
# Only load the plugins named here, in the order given (default is alphabetical).
|
22
22
|
# :all can be used as a placeholder for all plugins not explicitly named.
|
data/config/database.yml
CHANGED
@@ -1,25 +1,29 @@
|
|
1
|
-
# SQLite version 3.x
|
2
|
-
# gem install sqlite3
|
3
|
-
#
|
4
|
-
# Ensure the SQLite 3 gem is defined in your Gemfile
|
5
|
-
# gem 'sqlite3'
|
6
1
|
development:
|
7
|
-
adapter:
|
8
|
-
|
2
|
+
adapter: mysql2
|
3
|
+
encoding: utf8
|
4
|
+
reconnect: false
|
5
|
+
database: magi_development
|
9
6
|
pool: 5
|
10
|
-
|
7
|
+
username: root
|
8
|
+
password:
|
9
|
+
host: localhost
|
11
10
|
|
12
|
-
# Warning: The database defined as "test" will be erased and
|
13
|
-
# re-generated from your development database when you run "rake".
|
14
|
-
# Do not set this db to the same as development or production.
|
15
11
|
test:
|
16
|
-
adapter:
|
17
|
-
|
12
|
+
adapter: mysql2
|
13
|
+
encoding: utf8
|
14
|
+
reconnect: false
|
15
|
+
database: magi_test
|
18
16
|
pool: 5
|
19
|
-
|
17
|
+
username: root
|
18
|
+
password:
|
19
|
+
host: localhost
|
20
20
|
|
21
21
|
production:
|
22
|
-
adapter:
|
23
|
-
|
22
|
+
adapter: mysql2
|
23
|
+
encoding: utf8
|
24
|
+
reconnect: false
|
25
|
+
database: magi_production
|
24
26
|
pool: 5
|
25
|
-
|
27
|
+
username: root
|
28
|
+
password:
|
29
|
+
host: localhost
|
data/config/routes.rb
CHANGED
@@ -1,58 +1,7 @@
|
|
1
1
|
Magi::Application.routes.draw do
|
2
|
-
|
3
|
-
# first created -> highest priority.
|
2
|
+
root to: "jobs#index"
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# Sample of named route:
|
10
|
-
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
11
|
-
# This route can be invoked with purchase_url(:id => product.id)
|
12
|
-
|
13
|
-
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
14
|
-
# resources :products
|
15
|
-
|
16
|
-
# Sample resource route with options:
|
17
|
-
# resources :products do
|
18
|
-
# member do
|
19
|
-
# get 'short'
|
20
|
-
# post 'toggle'
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# collection do
|
24
|
-
# get 'sold'
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
|
28
|
-
# Sample resource route with sub-resources:
|
29
|
-
# resources :products do
|
30
|
-
# resources :comments, :sales
|
31
|
-
# resource :seller
|
32
|
-
# end
|
33
|
-
|
34
|
-
# Sample resource route with more complex sub-resources
|
35
|
-
# resources :products do
|
36
|
-
# resources :comments
|
37
|
-
# resources :sales do
|
38
|
-
# get 'recent', :on => :collection
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
|
42
|
-
# Sample resource route within a namespace:
|
43
|
-
# namespace :admin do
|
44
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
45
|
-
# # (app/controllers/admin/products_controller.rb)
|
46
|
-
# resources :products
|
47
|
-
# end
|
48
|
-
|
49
|
-
# You can have the root of your site routed with "root"
|
50
|
-
# just remember to delete public/index.html.
|
51
|
-
# root :to => 'welcome#index'
|
52
|
-
|
53
|
-
# See how all your routes lay out with "rake routes"
|
54
|
-
|
55
|
-
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
56
|
-
# Note: This route will make all actions in every controller accessible via GET requests.
|
57
|
-
# match ':controller(/:action(/:id))(.:format)'
|
4
|
+
resources :jobs do
|
5
|
+
resources :builds, only: [:index, :show, :create, :update, :destroy]
|
6
|
+
end
|
58
7
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateBuilds < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :builds do |t|
|
4
|
+
t.boolean :status
|
5
|
+
t.datetime :started_at
|
6
|
+
t.datetime :finished_at
|
7
|
+
t.references :job
|
8
|
+
t.text :output
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
add_index :builds, :job_id
|
13
|
+
end
|
14
|
+
end
|
data/db/schema.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended to check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(:version => 20130531155155) do
|
15
|
+
|
16
|
+
create_table "builds", :force => true do |t|
|
17
|
+
t.boolean "status"
|
18
|
+
t.datetime "started_at"
|
19
|
+
t.datetime "finished_at"
|
20
|
+
t.integer "job_id"
|
21
|
+
t.text "output"
|
22
|
+
t.datetime "created_at", :null => false
|
23
|
+
t.datetime "updated_at", :null => false
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index "builds", ["job_id"], :name => "index_builds_on_job_id"
|
27
|
+
|
28
|
+
create_table "jobs", :force => true do |t|
|
29
|
+
t.string "name"
|
30
|
+
t.text "config"
|
31
|
+
t.datetime "created_at", :null => false
|
32
|
+
t.datetime "updated_at", :null => false
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/magi/command.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Provides command line interface for Magi.
|
2
|
+
#
|
3
|
+
# Examples
|
4
|
+
#
|
5
|
+
# # Takes ARGV and invokes a job.
|
6
|
+
# Magi::Command.call(ARGV)
|
7
|
+
#
|
8
|
+
# # Invokes "setup" command to set up your database.
|
9
|
+
# Magi::Command.call(["setup"])
|
10
|
+
#
|
11
|
+
# # Invokes "start" command to start redis, rails, and sidekiq processes.
|
12
|
+
# Magi::Command.call(["start"])
|
13
|
+
#
|
14
|
+
module Magi
|
15
|
+
class Command
|
16
|
+
def self.call(*args)
|
17
|
+
new(*args).call
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(argv)
|
21
|
+
@argv = argv
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
case name
|
26
|
+
when "setup"
|
27
|
+
setup
|
28
|
+
when "start"
|
29
|
+
start
|
30
|
+
else
|
31
|
+
puts "Usage: magi {setup|start}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def name
|
38
|
+
@argv[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
system("cd #{root_path} && bundle exec rake db:create db:migrate")
|
43
|
+
end
|
44
|
+
|
45
|
+
def start
|
46
|
+
system("cd #{root_path} && bundle exec foreman start")
|
47
|
+
end
|
48
|
+
|
49
|
+
def root_path
|
50
|
+
File.expand_path("../../..", __FILE__)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
3
|
+
module Magi
|
4
|
+
class Executer
|
5
|
+
def self.execute(*args)
|
6
|
+
new(*args).execute
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(script)
|
10
|
+
@script = script
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
{ status: status, output: output }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def tempfile
|
20
|
+
@tempfile ||= Tempfile.new("")
|
21
|
+
end
|
22
|
+
|
23
|
+
def status
|
24
|
+
system(@script, out: tempfile, err: tempfile)
|
25
|
+
end
|
26
|
+
|
27
|
+
def output
|
28
|
+
tempfile.tap(&:close).open.read
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Magi
|
2
|
+
class Scheduler
|
3
|
+
CRON_REGEXP = /\A(\d+|\*) (\d+|\*) (\d+|\*) (\d+|\*) (\d+|\*)\s*\z/
|
4
|
+
|
5
|
+
# Takes a schedule as a String.
|
6
|
+
def initialize(schedule)
|
7
|
+
@result, @min, @hour, @day, @month, @wday = *schedule.match(CRON_REGEXP)
|
8
|
+
validate
|
9
|
+
end
|
10
|
+
|
11
|
+
def scheduled?
|
12
|
+
[:min, :hour, :day, :month, :wday].all? do |key|
|
13
|
+
send(key).nil? || send(key) == now.send(key)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def min
|
20
|
+
@min.to_i if @min != "*"
|
21
|
+
end
|
22
|
+
|
23
|
+
def hour
|
24
|
+
@hour.to_i if @hour != "*"
|
25
|
+
end
|
26
|
+
|
27
|
+
def day
|
28
|
+
@day.to_i if @day != "*"
|
29
|
+
end
|
30
|
+
|
31
|
+
def month
|
32
|
+
@month.to_i if @month != "*"
|
33
|
+
end
|
34
|
+
|
35
|
+
def wday
|
36
|
+
@wday.to_i if @wday != "*"
|
37
|
+
end
|
38
|
+
|
39
|
+
def now
|
40
|
+
@now ||= Time.now
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate
|
44
|
+
raise_argument_error unless valid?
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid?
|
48
|
+
!!@result
|
49
|
+
end
|
50
|
+
|
51
|
+
def raise_argument_error
|
52
|
+
raise ArgumentError, "Input must match with #{CRON_REGEXP}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/magi/version.rb
CHANGED
data/lib/magi.rb
CHANGED
data/magi.gemspec
CHANGED
@@ -12,11 +12,39 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.homepage = "https://github.com/r7kamura/magi"
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
|
-
spec.files =
|
15
|
+
spec.files = Dir["{app,bin,config,db,lib,public,script,spec}/**/*"]
|
16
|
+
spec.files += %w[
|
17
|
+
Gemfile
|
18
|
+
LICENSE.txt
|
19
|
+
Procfile
|
20
|
+
README.md
|
21
|
+
Rakefile
|
22
|
+
config.ru
|
23
|
+
magi.gemspec
|
24
|
+
]
|
16
25
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
26
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
27
|
spec.require_paths = ["lib"]
|
19
28
|
|
29
|
+
spec.add_dependency "clockwork"
|
30
|
+
spec.add_dependency "coffee-rails", "~> 3.2.1"
|
31
|
+
spec.add_dependency "font-awesome-rails"
|
32
|
+
spec.add_dependency "foreman"
|
33
|
+
spec.add_dependency "jquery-rails"
|
34
|
+
spec.add_dependency "mysql2"
|
35
|
+
spec.add_dependency "quiet_assets"
|
36
|
+
spec.add_dependency "rails", "3.2.13"
|
37
|
+
spec.add_dependency "sass-rails", "~> 3.2.3"
|
38
|
+
spec.add_dependency "sidekiq"
|
39
|
+
spec.add_dependency "slim"
|
40
|
+
spec.add_dependency "uglifier", ">= 1.0.3"
|
20
41
|
spec.add_development_dependency "bundler", "~> 1.3"
|
42
|
+
spec.add_development_dependency "factory_girl_rails"
|
43
|
+
spec.add_development_dependency "pry-rails"
|
21
44
|
spec.add_development_dependency "rake"
|
45
|
+
spec.add_development_dependency "response_code_matchers"
|
46
|
+
spec.add_development_dependency "rspec-json_matcher"
|
47
|
+
spec.add_development_dependency "rspec-rails"
|
48
|
+
spec.add_development_dependency "simplecov"
|
49
|
+
spec.add_development_dependency "thin"
|
22
50
|
end
|
data/script/clock.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Build do
|
4
|
+
let(:build) do
|
5
|
+
FactoryGirl.create(:build, job: job)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:job) do
|
9
|
+
FactoryGirl.create(:job, config: { "script" => "true" })
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#start" do
|
13
|
+
context "with success" do
|
14
|
+
it "starts its job and sets status with true" do
|
15
|
+
build.start
|
16
|
+
build.started_at.should be_present
|
17
|
+
build.finished_at.should be_present
|
18
|
+
build.status.should == true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with failure" do
|
23
|
+
before do
|
24
|
+
build.job.config["script"] = "false"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "starts its job and sets status with false" do
|
28
|
+
build.start
|
29
|
+
build.started_at.should be_present
|
30
|
+
build.finished_at.should be_present
|
31
|
+
build.status.should == false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Job do
|
4
|
+
let(:job) do
|
5
|
+
FactoryGirl.create(:job)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#start" do
|
9
|
+
context "without script" do
|
10
|
+
it "raises Job::ScriptNotFound" do
|
11
|
+
expect { job.start }.to raise_error(Job::ScriptNotFound)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with script" do
|
16
|
+
before do
|
17
|
+
job.config["script"] = "true"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "starts its job" do
|
21
|
+
Magi::Executer.should_receive(:execute).with("true")
|
22
|
+
job.start
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#scheduled?" do
|
28
|
+
context "without schedule" do
|
29
|
+
it "returns false" do
|
30
|
+
job.should_not be_scheduled
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with matched schedule" do
|
35
|
+
before do
|
36
|
+
job.config["schedule"] = "* * * * *"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns true" do
|
40
|
+
job.should be_scheduled
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "without matched schedule" do
|
45
|
+
before do
|
46
|
+
job.config["schedule"] = "0 0 0 0 0"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns false" do
|
50
|
+
job.should_not be_scheduled
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Builds" do
|
4
|
+
let(:params) do
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:env) do
|
9
|
+
{ "HTTP_ACCEPT" => "application/json" }
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:job) do
|
13
|
+
FactoryGirl.create(:job)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:build) do
|
17
|
+
job.builds.create(id: 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "GET /jobs/:job_id/builds" do
|
21
|
+
before do
|
22
|
+
build
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns builds of the job" do
|
26
|
+
get "/jobs/#{job.id}/builds", params, env
|
27
|
+
response.status.should == 200
|
28
|
+
response.body.should be_json([Hash])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "GET /jobs/:job_id/builds/:id" do
|
33
|
+
it "returns the build" do
|
34
|
+
get "/jobs/#{job.id}/builds/#{build.id}", params, env
|
35
|
+
response.status.should == 200
|
36
|
+
response.body.should be_json(Hash)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "POST /jobs/:job_id/builds" do
|
41
|
+
it "creates a new build and queue it" do
|
42
|
+
post "/jobs/#{job.id}/builds", params, env
|
43
|
+
response.status.should == 201
|
44
|
+
response.body.should be_json(Hash)
|
45
|
+
BuildWorker.jobs.should have(1).queue
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "PUT /jobs/:job_id/builds/:id" do
|
50
|
+
before do
|
51
|
+
params[:build] = { status: true }
|
52
|
+
end
|
53
|
+
|
54
|
+
it "updates the build" do
|
55
|
+
put "/jobs/#{job.id}/builds/#{build.id}", params, env
|
56
|
+
response.status.should == 204
|
57
|
+
build.reload.status.should == true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "DELETE /jobs/:job_id/builds/:id" do
|
62
|
+
it "deletes the build" do
|
63
|
+
delete "/jobs/#{job.id}/builds/#{build.id}", params, env
|
64
|
+
response.status.should == 204
|
65
|
+
Build.should have(0).build
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Jobs" do
|
4
|
+
let(:params) do
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:env) do
|
9
|
+
{ "HTTP_ACCEPT" => "application/json" }
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:job) do
|
13
|
+
FactoryGirl.create(:job)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "GET /jobs" do
|
17
|
+
before do
|
18
|
+
job
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns jobs" do
|
22
|
+
get "/jobs", params, env
|
23
|
+
response.status.should == 200
|
24
|
+
response.body.should be_json([Hash])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "GET /jobs/:id" do
|
29
|
+
it "returns the job" do
|
30
|
+
get "/jobs/#{job.id}", params, env
|
31
|
+
response.status.should == 200
|
32
|
+
response.body.should be_json(Hash)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "POST /jobs" do
|
37
|
+
before do
|
38
|
+
params[:job] = { name: "name" }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with invalid params" do
|
42
|
+
before do
|
43
|
+
params.delete(:job)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns 400" do
|
47
|
+
post "/jobs", params, env
|
48
|
+
response.status.should == 400
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with valid condition" do
|
53
|
+
it "creates a new job" do
|
54
|
+
post "/jobs", params, env
|
55
|
+
response.status.should == 201
|
56
|
+
Job.should have(1).job
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "PUT /jobs/:id" do
|
62
|
+
before do
|
63
|
+
params[:job] = { name: "name" }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with invalid params" do
|
67
|
+
before do
|
68
|
+
params.delete(:job)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns 400" do
|
72
|
+
put "/jobs/#{job.id}", params, env
|
73
|
+
response.status.should == 400
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with valid condition" do
|
78
|
+
it "updates the job" do
|
79
|
+
put "/jobs/#{job.id}", params, env
|
80
|
+
response.status.should == 204
|
81
|
+
job.reload.name.should == "name"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "DELETE /jobs/:id" do
|
87
|
+
it "deletes the job" do
|
88
|
+
delete "/jobs/#{job.id}", params, env
|
89
|
+
response.status.should == 204
|
90
|
+
Job.should_not be_exist(job.id)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|