bloc 0.0.10 → 0.1.0

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.
data/bin/bloc CHANGED
@@ -4,11 +4,12 @@ require "rubygems"
4
4
  require "bloc"
5
5
 
6
6
  commands = {
7
- 'validate' => proc { Bloc::Command::Validate.run },
8
- 'create' => proc { Bloc::Command::Create.run },
9
- 'test' => proc { Bloc::Command::Test.run },
10
- 'patch' => proc { Bloc::Command::Patch.run }
7
+ 'validate' => proc { Bloc::Command::Validate.run },
8
+ 'test' => proc { Bloc::Command::Test.run },
9
+ 'authenticate' => proc { Bloc::Command::Authenticate.run },
10
+ 'tasks' => proc { Bloc::Command::Tasks.run }
11
11
  }
12
+
12
13
  if commands.keys.include?(ARGV.first.downcase)
13
14
  begin
14
15
  commands[ARGV.first.downcase].call
@@ -25,6 +26,7 @@ else
25
26
  create["Course name"] Create a course manifest with the specified name prefilled
26
27
  test [chapter-number] If chapter number is specified, run tests for that chapter. If not, run all tests in order.
27
28
  patch [chapter-number] Same as "test", except apply patches first (if present)
29
+ authenticate Authenticate by entering your Bloc email and password
28
30
  eos
29
31
  puts helpstring
30
32
  end
@@ -21,4 +21,6 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency "ruby-debug19"
22
22
  s.add_runtime_dependency "json"
23
23
  s.add_runtime_dependency "colorize"
24
+ s.add_runtime_dependency "rest-client"
25
+ s.add_runtime_dependency "hashie"
24
26
  end
@@ -1,11 +1,14 @@
1
- $:.push File.expand_path("../lib", __FILE__)
1
+ $:.push File.expand_path("./lib")
2
2
 
3
3
  require "colorize"
4
4
  require "json"
5
+ require "hashie"
5
6
 
6
7
  require "bloc/version"
7
8
  require "bloc/command"
8
- require "bloc/models"
9
+ require "bloc/client"
10
+ require "bloc/manifest"
11
+ require "bloc/runner"
9
12
 
10
13
  module Bloc
11
14
  end
@@ -0,0 +1,29 @@
1
+ require "rest-client"
2
+
3
+ require "bloc/client/authenticate"
4
+ require "bloc/client/course"
5
+ require "bloc/client/enrollment"
6
+
7
+ module Bloc
8
+ class Client
9
+ include Authenticate
10
+
11
+ def self.client
12
+ @client ||= Bloc::Client.new
13
+ end
14
+
15
+ def self.credentials
16
+ @credentials ||= JSON.parse(File.read(Bloc::Command::Authenticate::CREDENTIALS_PATH))
17
+ end
18
+
19
+ def self.credentials=(credentials)
20
+ @credentials = credentials
21
+ end
22
+
23
+ private
24
+
25
+ def bloc_url(path)
26
+ "http://www.trybloc.com/api/v1#{path}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ require "json"
2
+
3
+ module Bloc
4
+ class Client
5
+ module Authenticate
6
+ def authenticate(options)
7
+ raise "Must Provide an Email" unless options[:email]
8
+ raise "Must Provide a Password" unless options[:password]
9
+
10
+ response = RestClient.post(bloc_url("/api_keys"), {
11
+ :email => options[:email],
12
+ :password => options[:password]
13
+ })
14
+
15
+ credentials = JSON.parse(response.body)
16
+
17
+ Bloc::Client.credentials = credentials
18
+
19
+ credentials
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module Bloc
2
+ class Client
3
+ class Course
4
+ def self.find(options={})
5
+ response = RestClient.get "http://www.trybloc.com/api/v1/courses/find", :params => options.merge(:api_key => Bloc::Client.credentials["api_key"])
6
+ self.new JSON.parse(response.body)
7
+ end
8
+
9
+ def initialize(attributes)
10
+ @attributes = attributes
11
+ end
12
+
13
+ def method_missing(method)
14
+ method = method.to_s
15
+
16
+ if @attributes[method]
17
+ return @attributes[method]
18
+ else
19
+ super(method)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ module Bloc
2
+ class Client
3
+ class Enrollment
4
+ def self.create(attributes)
5
+ raise "Must Provide a Course Id" unless attributes[:course_id]
6
+ course_id = attributes.delete(:course_id)
7
+
8
+ response = RestClient.post("http://www.trybloc.com/api/v1/courses/#{course_id}/enrollments", {
9
+ :enrollment => attributes,
10
+ :api_key => Bloc::Client.credentials["api_key"]
11
+ })
12
+
13
+ self.new JSON.parse(response.body)
14
+ end
15
+
16
+ def initialize(attributes)
17
+ @attributes = attributes
18
+ end
19
+
20
+ def update(attributes)
21
+ response = RestClient.put("http://www.trybloc.com/api/v1/courses/#{course_id}/enrollments/#{id}", {
22
+ :enrollment => attributes,
23
+ :api_key => Bloc::Client.credentials["api_key"]
24
+ })
25
+
26
+ @attributes = JSON.parse(response.body)
27
+ end
28
+
29
+ def method_missing(method)
30
+ method = method.to_s
31
+
32
+ if @attributes[method]
33
+ return @attributes[method]
34
+ else
35
+ super(method)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,13 +1,10 @@
1
- require "bloc/command/validate.rb"
2
- require "bloc/command/create.rb"
3
- require "bloc/command/test.rb"
4
- require "bloc/command/patch.rb"
5
- require "bloc/models.rb"
6
- require "bloc/manifest.rb"
1
+ require "bloc/command/validate"
2
+ require "bloc/command/test"
3
+ require "bloc/command/tasks"
4
+ require "bloc/command/authenticate"
7
5
 
8
6
  module Bloc
9
7
  module Command
10
- end
11
-
12
8
 
9
+ end
13
10
  end
@@ -0,0 +1,43 @@
1
+ require "colorize"
2
+
3
+ module Bloc
4
+ module Command
5
+ class Authenticate
6
+ CREDENTIALS_PATH = File.join(ENV["HOME"], ".bloc", "credentials.json")
7
+ def self.run(*args)
8
+ login
9
+ end
10
+
11
+ def self.login
12
+ print "Email: "
13
+ email = $stdin.gets.chomp
14
+
15
+ print "Password: "
16
+ system "stty -echo"
17
+ password = $stdin.gets.chomp
18
+ system "stty echo"
19
+
20
+ print "\n"
21
+
22
+ client = Bloc::Client.new
23
+
24
+ begin
25
+ credentials = client.authenticate(:email => email, :password => password)
26
+ write_credentials(credentials)
27
+ puts "saved your credentials".green
28
+ rescue
29
+ puts "invalid email or password".red
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def self.write_credentials(credentials)
36
+ FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
37
+ FileUtils.touch(CREDENTIALS_PATH)
38
+
39
+ File.open(CREDENTIALS_PATH, "w+") { |file| file << credentials.to_json }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,37 @@
1
+ require "bloc/command/tasks/formatter"
2
+
3
+ module Bloc
4
+ module Command
5
+ class Tasks
6
+ def self.run
7
+ course = Client::Course.find(:scaffold_clone_url => git_remotes.first)
8
+ enrollment = Client::Enrollment.create(:course_id => course.id)
9
+
10
+ manifest = Manifest.parse
11
+
12
+ puts "Running Chapter #{enrollment.current_step} Tasks".green
13
+
14
+ results = Runner.run(manifest.chapters[enrollment.current_step - 1].command)
15
+
16
+ puts Formatter.format(results["tests"])
17
+
18
+ if results["tests"].all? {|result| result["passed"] }
19
+ puts "Chapter #{enrollment.current_step} Complete!"
20
+
21
+ if manifest.chapters.size == enrollment.current_step
22
+ enrollment.update(:completed => true)
23
+ else
24
+ enrollment.update(:current_step => enrollment.current_step + 1)
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.git_remotes
30
+ `git remote -v`.split("\n").map do |remote|
31
+ name, url, method = remote.split(/\s/)
32
+ url
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ module Bloc
2
+ module Command
3
+ class Tasks
4
+ module Formatter
5
+ def self.format(results)
6
+ results.to_yaml
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,11 +3,7 @@ module Bloc
3
3
  class Test
4
4
  def self.run(*args)
5
5
  manifest = Manifest.parse
6
- if ARGV[1].nil?
7
- manifest.run_tests
8
- else
9
- manifest.run_tests(:chapter => ARGV[1].to_i)
10
- end
6
+ results = Runner.run(manifest.chapters.first.command)
11
7
  end
12
8
  end
13
9
  end
@@ -47,7 +47,9 @@ module Bloc
47
47
  def self.check_patches(manifest)
48
48
  # TODO: ensure all chapters have patches
49
49
  manifest.chapters.each do |chapter|
50
- if chapter.patch_exists?
50
+ if chapter.patch.nil?
51
+
52
+ elsif File.exists? chapter.patch
51
53
  puts PATCH_EXISTS % chapter.patch
52
54
  else
53
55
  raise NO_SUCH_PATCH % chapter.patch
@@ -1,40 +1,12 @@
1
- require "bloc/hash_constructed.rb"
2
- require "bloc/temp_git.rb"
3
- require "bloc/models.rb"
4
-
5
1
  module Bloc
6
- class Manifest
2
+ class Manifest < Hashie::Mash
7
3
  MANIFEST_NOT_FOUND = "Unable to find Bloc Manifest in bloc/bloc_manifest.json".red
8
4
  MANIFEST_PATH = File.join("bloc", "bloc_manifest.json")
9
5
  INVALID_MANIFEST = "Invalid JSON in Bloc Manifest: #{MANIFEST_PATH}".red
10
6
  VALID_MANIFEST = "Valid Bloc Manifest".green
11
7
  NO_SUCH_CHAPTER = "No such chapter.".red
12
-
13
- include TempGit
14
-
15
- attr_accessor :course, :chapters, :deployable
16
-
17
- def initialize(options)
18
- @course = options["course"]
19
- @chapters = options["chapters"]
20
- end
21
-
22
- def write
23
- Dir.mkdir(File.dirname(MANIFEST_PATH))
24
- File.open(MANIFEST_PATH, "w") do |file|
25
- file.write(JSON.pretty_generate(to_h))
26
- end
27
- end
28
-
29
- def to_h
30
- hash = {}
31
- hash["course"] = @course.to_h
32
- hash["chapters"] = []
33
- @chapters.each do |chapter|
34
- hash["chapters"] << chapter.to_h
35
- end
36
- hash
37
- end
8
+ NO_COURSE = "Missing: course".red
9
+ NO_CHAPTERS = "Missing: chapters".red
38
10
 
39
11
  def self.parse
40
12
  raise MANIFEST_NOT_FOUND unless File.exists?(MANIFEST_PATH)
@@ -46,30 +18,16 @@ module Bloc
46
18
  rescue
47
19
  raise INVALID_MANIFEST
48
20
  end
49
- course = Bloc::Models::Course.new(manifest["course"])
50
- chapters = []
51
- manifest["chapters"].each do |chapter|
52
- chapters << Bloc::Models::Chapter.new(chapter)
53
- end
54
- Manifest.new({"course" => course, "chapters" => chapters})
21
+ Manifest.new(manifest)
55
22
  end
56
23
 
57
- def run_tests(options = {})
58
- defaults = {:chapter => nil, :apply_patch => false}
59
- options = defaults.merge(options)
60
-
61
- in_tmp_git do
62
- if options[:chapter].nil?
63
- @chapters.each do |chapter|
64
- chapter.apply_patch if options[:apply_patch]
65
- chapter.run_tests
66
- end
67
- else
68
- index = options[:chapter] - 1
69
- raise NO_SUCH_CHAPTER if @chapters[index].nil?
70
- @chapters[index].apply_patch if options[:apply_patch]
71
- @chapters[index].run_tests
72
- end
24
+ def write
25
+ begin
26
+ Dir.mkdir(File.dirname(MANIFEST_PATH))
27
+ rescue
28
+ end
29
+ File.open(MANIFEST_PATH, "w") do |file|
30
+ file.write(JSON.pretty_generate(to_hash))
73
31
  end
74
32
  end
75
33
  end
@@ -0,0 +1,10 @@
1
+ module Bloc
2
+ class Runner
3
+ def self.run(command)
4
+ `#{command}`
5
+ results = JSON.parse(File.read("results.json"))
6
+ File.delete("results.json")
7
+ results
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module Bloc
2
- VERSION = "0.0.10"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1 @@
1
+ bundle exec rspec spec
@@ -0,0 +1,43 @@
1
+ require "./spec/spec_helper"
2
+
3
+ describe Bloc::Client do
4
+ describe "#authenticate" do
5
+ let(:client) { Bloc::Client.new }
6
+ let(:email) { "bob@loblaw.com" }
7
+ let(:password) { "super_secret" }
8
+ let(:fake_response) { RestClient::Response.create(%Q({ "key" : "value" }), nil, nil) }
9
+
10
+ before do
11
+ RestClient.stub(:post).and_return(fake_response)
12
+ end
13
+
14
+ it "raises an error if no email is provided" do
15
+ lambda { client.authenticate(:password => password) }.should raise_error
16
+ end
17
+
18
+ it "raises an error if no password is provided" do
19
+ lambda { client.authenticate(:email => email) }.should raise_error
20
+ end
21
+
22
+ it "POSTs the email and password to the API keys endpoint" do
23
+ RestClient.should_receive(:post).with(anything, {
24
+ :email => email,
25
+ :password => password
26
+ }).and_return(fake_response)
27
+
28
+ client.authenticate(:password => password, :email => email)
29
+ end
30
+
31
+ it "adds the api key as a param to all RestClient calls" do
32
+ Bloc::Client.should_receive(:credentials=).with(JSON.parse(fake_response.body))
33
+ client.authenticate(:password => password, :email => email)
34
+ end
35
+
36
+ it "returns a parsed JSON hash" do
37
+ RestClient.should_receive(:post).and_return(fake_response)
38
+
39
+ result = client.authenticate(:password => password, :email => email)
40
+ result.should be_a(Hash)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ require "./spec/spec_helper"
2
+
3
+ describe Bloc::Client::Course do
4
+ describe ".find" do
5
+ let(:query) { { :scaffold_code_url => "some-url" } }
6
+ let(:fake_response) { RestClient::Response.create(%Q({ "key" : "value" }), nil, nil) }
7
+
8
+ before { RestClient.stub(:get).and_return(fake_response) }
9
+
10
+ it "queries the Bloc API by the conditions passed in" do
11
+ RestClient.should_receive(:get).with(anything, :params => hash_including(query)).and_return(fake_response)
12
+ Bloc::Client::Course.find(query)
13
+ end
14
+
15
+ it "returns a new instance of itself" do
16
+ course = Bloc::Client::Course.find(query)
17
+ course.should be_a(Bloc::Client::Course)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ require "./spec/spec_helper"
2
+
3
+ describe Bloc::Client::Enrollment do
4
+ let(:attributes) { { :id => 1, :current_step => 3, :completed => false , :course_id => 1} }
5
+ let(:fake_response) { RestClient::Response.create(attributes.to_json, nil, nil) }
6
+ before { RestClient.stub(:post).and_return(fake_response) }
7
+
8
+ describe ".create" do
9
+ it "raises an exception if no course_id is provided" do
10
+ lambda { Bloc::Client::Enrollment.create attributes.delete(:course_id) }.should raise_error
11
+ end
12
+
13
+ it "creates an Enrollment through the API" do
14
+ RestClient.should_receive(:post).with(anything, hash_including(:enrollment => attributes)).and_return(fake_response)
15
+ Bloc::Client::Enrollment.create(attributes)
16
+ end
17
+
18
+ it "returns an instance of itself" do
19
+ enrollment = Bloc::Client::Enrollment.create(attributes)
20
+ enrollment.should be_a(Bloc::Client::Enrollment)
21
+ end
22
+ end
23
+
24
+ describe "#update" do
25
+ let(:enrollment) { Bloc::Client::Enrollment.create(attributes) }
26
+ let(:update_attributes) { { "current_step" => "4" } }
27
+ let(:fake_update_response) { RestClient::Response.create(attributes.merge(:current_step => 4).to_json, nil, nil) }
28
+
29
+ before { RestClient.stub(:put).and_return(fake_update_response) }
30
+
31
+ it "updates the enrollment through the API" do
32
+ RestClient.should_receive(:put).with(anything, hash_including(:enrollment => update_attributes)).and_return(fake_response)
33
+ enrollment.update(update_attributes)
34
+ end
35
+
36
+ it "updates the enrollments attributes" do
37
+ enrollment.current_step.should == 3
38
+ enrollment.update(update_attributes)
39
+ enrollment.current_step.should == 4
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ require "./spec/spec_helper"
2
+ require "fakefs"
3
+
4
+ describe Bloc::Command::Authenticate do
5
+ before do
6
+ $stdout = StringIO.new
7
+ $stdin.stub(:gets).and_return(email, password)
8
+ Bloc::Client.any_instance.should_receive(:authenticate).with({
9
+ :email => email, :password => password
10
+ }).and_return(credentials)
11
+ end
12
+
13
+ after { $stdout = STDOUT }
14
+
15
+ let(:email) { "bob@loblaw.com" }
16
+ let(:password) { "super_secret" }
17
+ let(:credentials) { {"credentials" => true} }
18
+
19
+ describe ".login" do
20
+ it "asks for user credentials" do
21
+ STDIN.should_receive(:gets).and_return(email, password)
22
+ Bloc::Command::Authenticate.login
23
+ end
24
+
25
+ it "writes the credentials to a dotfile" do
26
+ Bloc::Command::Authenticate.login
27
+ JSON.parse(File.read(Bloc::Command::Authenticate::CREDENTIALS_PATH)).should == credentials
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,57 @@
1
+ require "./spec/spec_helper"
2
+ require "stringio"
3
+ require "fakefs"
4
+
5
+ module Bloc
6
+ describe Bloc::Command::Tasks do
7
+ describe ".run" do
8
+ let(:enrollment) { Client::Enrollment.new("id" => 1, "current_step" => 1, "completed" => false) }
9
+ let(:course) { Client::Course.new({"id" => "1", "slug" => "url-shortener" }) }
10
+ let(:git_remote) { "git://github.com/Bloc/URL-Shortener.git" }
11
+ let(:passed_results) { { "tests" => [{"passed" => true }, { "passed" => true }] } }
12
+ let(:failed_results) { { "tests" => [{"passed" => false }, { "passed" => true }] } }
13
+
14
+ before do
15
+ FileUtils.mkdir_p(File.dirname(Manifest::MANIFEST_PATH))
16
+ File.open(Manifest::MANIFEST_PATH, "w+") do |f|
17
+ f << %Q({"course": {"name" : "CatNap"}, "chapters": [{ "command": "whatever" }, {"command": "stuff"}]})
18
+ end
19
+ Command::Tasks.stub(:git_remotes).and_return([git_remote])
20
+ Client::Course.stub(:find).and_return(course)
21
+ Client::Enrollment.stub(:create).and_return(enrollment)
22
+ Runner.stub(:run).and_return(failed_results)
23
+
24
+ $stdout = StringIO.new
25
+ end
26
+
27
+ after { $stdout = STDOUT }
28
+
29
+ it "runs the tasks command for the current chapter" do
30
+ Runner.should_receive(:run).with("whatever")
31
+ Command::Tasks.run
32
+ end
33
+
34
+ context "if the tests pass" do
35
+ before do
36
+ Runner.stub(:run).and_return(passed_results)
37
+ Client::Course.stub(:find).with(:scaffold_clone_url => git_remote).and_return(course)
38
+ Client::Enrollment.stub(:create).with(:course_id => course.id).and_return(enrollment)
39
+ end
40
+
41
+ it "increments the current chapter of the enrollment" do
42
+ enrollment.should_receive(:update).with(:current_step => (enrollment.current_step + 1))
43
+ Command::Tasks.run
44
+ end
45
+
46
+ context "on the last chapter" do
47
+ let(:enrollment) { Client::Enrollment.new("id" => 1, "current_step" => 2, "completed" => false) }
48
+
49
+ it "sets the enrollment to 'completed' if there are no more chapters" do
50
+ enrollment.should_receive(:update).with(:completed => true)
51
+ Command::Tasks.run
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -5,25 +5,33 @@ require "stringio"
5
5
  module Bloc::Command
6
6
  describe Validate do
7
7
  it "raises an exception if the Bloc manifest can not be found" do
8
- lambda { Validate.run() }.should raise_error(Validate::MANIFEST_NOT_FOUND)
8
+ lambda { Validate.run() }.should raise_error(Bloc::Manifest::MANIFEST_NOT_FOUND)
9
9
  end
10
10
 
11
11
  it "raises an exception if the Bloc manifest has invalid JSON" do
12
12
  FileUtils.mkdir_p("bloc")
13
- File.open(Validate::MANIFEST_PATH, 'w+') {|f| f.write "<<invalid json>>" }
13
+ File.open(Bloc::Manifest::MANIFEST_PATH, 'w+') {|f| f.write "<<invalid json>>" }
14
14
 
15
- lambda { Validate.run() }.should raise_error(Validate::INVALID_MANIFEST)
15
+ lambda { Validate.run() }.should raise_error(Bloc::Manifest::INVALID_MANIFEST)
16
16
  end
17
17
 
18
18
  it "prints a success message if the manifest is valid" do
19
19
  FileUtils.mkdir_p("bloc")
20
- File.open(Validate::MANIFEST_PATH, 'w+') {|f| f.write %Q({"json": "true" }) }
20
+ File.open(Bloc::Manifest::MANIFEST_PATH, 'w+') {|f| f.write <<-eos
21
+ {
22
+ "course": {
23
+ "name": "Foobar",
24
+ "description": ""
25
+ },
26
+ "chapters": []
27
+ }
28
+ eos
29
+ }
21
30
 
22
31
  out = StringIO.new
23
32
  $stdout = out
24
33
  Validate.run()
25
34
  $stdout = STDOUT
26
- out.string.chomp.should == Validate::VALID_MANIFEST
27
35
  end
28
36
  end
29
37
  end
@@ -0,0 +1,39 @@
1
+ require './spec/spec_helper.rb'
2
+ require 'fakefs/safe'
3
+
4
+ module Bloc
5
+ describe Manifest do
6
+ it "writes valid JSON" do
7
+ FakeFS do
8
+ Bloc::Manifest.new(@options).write
9
+ lambda { JSON.parse File.read(Bloc::Manifest::MANIFEST_PATH) }.should_not raise_error
10
+ end
11
+ end
12
+
13
+ it "can parse its own output" do
14
+ FakeFS do
15
+ Bloc::Manifest.new(@options).write
16
+ lambda { Bloc::Manifest.parse }.should_not raise_error
17
+ end
18
+ end
19
+
20
+ it "parses a valid manifest" do
21
+ valid_manifests = Dir['spec/valid_manifests/*'].map {|path| File.read(path)}
22
+ valid_manifests.each do |manifest|
23
+ FakeFS do
24
+ FileUtils.mkdir_p 'bloc'
25
+ File.open(Bloc::Manifest::MANIFEST_PATH, "w") do |file|
26
+ file.write manifest
27
+ end
28
+ STDOUT.should_receive(:puts).and_return(Bloc::Manifest::VALID_MANIFEST)
29
+ lambda { Bloc::Manifest.parse }.should_not raise_error
30
+ end
31
+ end
32
+ end
33
+
34
+ it "to_hash produces a valid ruby hash" do
35
+ manifest = Bloc::Manifest.new(@options)
36
+ manifest.to_hash.class.should be(Hash)
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,21 @@
1
1
  $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  require "bloc"
4
+
5
+ module Helpers
6
+ # Replace standard input with faked one StringIO.
7
+ def fake_stdin(text)
8
+ begin
9
+ $stdin = StringIO.new
10
+ $stdin.puts(text)
11
+ $stdin.rewind
12
+ yield
13
+ ensure
14
+ $stdin = STDIN
15
+ end
16
+ end
17
+ end
18
+
19
+ RSpec.configure do |conf|
20
+ conf.include(Helpers)
21
+ end
@@ -0,0 +1,7 @@
1
+ {
2
+ "course": {
3
+ "name": "Foobar",
4
+ "description": ""
5
+ },
6
+ "chapters": []
7
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bloc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-03-06 00:00:00.000000000Z
13
+ date: 2012-03-10 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
17
- requirement: &70339116316320 !ruby/object:Gem::Requirement
17
+ requirement: &70122279915300 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *70339116316320
25
+ version_requirements: *70122279915300
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: fakefs
28
- requirement: &70339116315900 !ruby/object:Gem::Requirement
28
+ requirement: &70122279914880 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *70339116315900
36
+ version_requirements: *70122279914880
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: ruby-debug19
39
- requirement: &70339116315480 !ruby/object:Gem::Requirement
39
+ requirement: &70122279914460 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70339116315480
47
+ version_requirements: *70122279914460
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: json
50
- requirement: &70339116315060 !ruby/object:Gem::Requirement
50
+ requirement: &70122279914040 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70339116315060
58
+ version_requirements: *70122279914040
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: colorize
61
- requirement: &70339116314640 !ruby/object:Gem::Requirement
61
+ requirement: &70122279913620 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,7 +66,29 @@ dependencies:
66
66
  version: '0'
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70339116314640
69
+ version_requirements: *70122279913620
70
+ - !ruby/object:Gem::Dependency
71
+ name: rest-client
72
+ requirement: &70122279913200 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: *70122279913200
81
+ - !ruby/object:Gem::Dependency
82
+ name: hashie
83
+ requirement: &70122279912780 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: *70122279912780
70
92
  description: A command-line tool for Bloc
71
93
  email:
72
94
  - roshan.choxi@gmail.com
@@ -85,19 +107,31 @@ files:
85
107
  - bin/bloc
86
108
  - bloc.gemspec
87
109
  - lib/bloc.rb
110
+ - lib/bloc/client.rb
111
+ - lib/bloc/client/authenticate.rb
112
+ - lib/bloc/client/course.rb
113
+ - lib/bloc/client/enrollment.rb
88
114
  - lib/bloc/command.rb
89
- - lib/bloc/command/create.rb
90
- - lib/bloc/command/patch.rb
115
+ - lib/bloc/command/authenticate.rb
116
+ - lib/bloc/command/tasks.rb
117
+ - lib/bloc/command/tasks/formatter.rb
91
118
  - lib/bloc/command/test.rb
92
119
  - lib/bloc/command/validate.rb
93
- - lib/bloc/hash_constructed.rb
94
120
  - lib/bloc/manifest.rb
95
- - lib/bloc/models.rb
121
+ - lib/bloc/runner.rb
96
122
  - lib/bloc/temp_git.rb
97
123
  - lib/bloc/to_hash.rb
98
124
  - lib/bloc/version.rb
125
+ - script/test
126
+ - spec/client/authenticate_spec.rb
127
+ - spec/client/course_spec.rb
128
+ - spec/client/enrollment_spec.rb
129
+ - spec/command/authenticate_spec.rb
130
+ - spec/command/tasks_spec.rb
99
131
  - spec/command/validate_spec.rb
132
+ - spec/manifest_spec.rb
100
133
  - spec/spec_helper.rb
134
+ - spec/valid_manifests/1.json
101
135
  homepage:
102
136
  licenses: []
103
137
  post_install_message:
@@ -123,5 +157,12 @@ signing_key:
123
157
  specification_version: 3
124
158
  summary: A CLI For Bloc
125
159
  test_files:
160
+ - spec/client/authenticate_spec.rb
161
+ - spec/client/course_spec.rb
162
+ - spec/client/enrollment_spec.rb
163
+ - spec/command/authenticate_spec.rb
164
+ - spec/command/tasks_spec.rb
126
165
  - spec/command/validate_spec.rb
166
+ - spec/manifest_spec.rb
127
167
  - spec/spec_helper.rb
168
+ - spec/valid_manifests/1.json
@@ -1,21 +0,0 @@
1
- module Bloc
2
- module Command
3
- class Create
4
- def self.run(*args)
5
- name = ARGV[1]
6
- if name.nil?
7
- raise "Please specify a name.".red
8
- end
9
- course = Bloc::Models::Course.new(:name => name, :description => "")
10
- chapters = []
11
- manifest = Bloc::Manifest.new({"course" => course, "chapters" => chapters})
12
- begin
13
- manifest.write
14
- puts "Wrote manifest.".green
15
- rescue Exception => e
16
- raise e.to_s.red
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,14 +0,0 @@
1
- module Bloc
2
- module Command
3
- class Patch
4
- def self.run(*args)
5
- manifest = Manifest.parse
6
- if ARGV[1].nil?
7
- manifest.run_tests(:apply_patch => true)
8
- else
9
- manifest.run_tests(:chapter => ARGV[1].to_i, :apply_patch => true)
10
- end
11
- end
12
- end
13
- end
14
- end
@@ -1,5 +0,0 @@
1
- module HashConstructed
2
- def initialize(h)
3
- h.each {|k,v| send("#{k}=",v)}
4
- end
5
- end
@@ -1,55 +0,0 @@
1
- require 'bloc/hash_constructed.rb'
2
- require 'bloc/to_hash.rb'
3
-
4
- module Bloc
5
- module Models
6
- class Course
7
- include HashConstructed
8
- include ToHash
9
- attr_accessor :name, :description, :default_file
10
-
11
-
12
- end
13
-
14
- class Chapter
15
- include HashConstructed
16
- include ToHash
17
- attr_accessor :name, :command, :markdown, :default_file, :patch, :cursor_row, :cursor_column
18
-
19
- TEST_FAILURE = "Failed test:\n%s".red
20
- TEST_PASSED = "Passed: %s".green
21
-
22
- def run_tests
23
- unless @patch.nil?
24
- results = test
25
- results["tests"].each do |test_result|
26
- if test_result["passed"]
27
- puts TEST_PASSED % test_result["name"]
28
- else
29
- raise TEST_FAILURE % test_result["name"]
30
- end
31
- end
32
- end
33
- end
34
-
35
- def patch_exists?
36
- File.exists?("bloc/#{@patch}")
37
- end
38
-
39
- def apply_patch
40
- unless @patch.nil?
41
- `patch < bloc/#{@patch}`
42
- end
43
- end
44
-
45
- private
46
-
47
- def test
48
- `#{@command}`
49
- results = JSON.parse(File.read("results.json"))
50
- File.delete("results.json")
51
- results
52
- end
53
- end
54
- end
55
- end