et 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b39aed635bf95f14c089d17488dcde13d1a85ea2
4
- data.tar.gz: 680174f609918e638266301b381d5ac5d74d8f84
3
+ metadata.gz: 44921ec7a8dc12f41fa49bac47557a76f75de660
4
+ data.tar.gz: 074a87d6f612a8ac878f8608222f2a69b0eb6b34
5
5
  SHA512:
6
- metadata.gz: efca6c830ff04b4be2414c83c062462a9d0d532c1b0621693d6f97f52f7d156b681421a3bf25ed0760a4548c0fa40ef36d0c21e6c151e8fb2f8026f6237bf72b
7
- data.tar.gz: 5a52aa3f094bc58460a9834c7a2f09a004e834a53f0e580f344d71ddb538f7b168f029732921a2013fba2fa5235b76c29d71ea206c9c0993a240a161026fcd7e
6
+ metadata.gz: d5a6d4ac016be8a94adb73d46880ff5da19266734d6d41b814312d638d5a84ce3d832d3f114da3212b7e509bfbc181d7ec123edb7c5da7936addfc0257bf4ce4
7
+ data.tar.gz: 13b8218ceccd48c032c2ab8b158fa597b4505de41309c87b28796a0faafc6b80733cec84aad3d08467b6adacaedd5222f5860e6b9a3f8fec2dfa27b27a1aebda
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.1.3
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
3
+ - 2.1.3
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- et (0.3.0)
4
+ et (0.5.0)
5
5
  gli (= 2.11.0)
6
6
  rest-client (~> 1.7)
7
7
 
@@ -10,8 +10,8 @@ GEM
10
10
  specs:
11
11
  diff-lcs (1.2.5)
12
12
  gli (2.11.0)
13
- mime-types (2.3)
14
- netrc (0.7.7)
13
+ mime-types (2.4.3)
14
+ netrc (0.8.0)
15
15
  rake (10.3.2)
16
16
  rest-client (1.7.2)
17
17
  mime-types (>= 1.16, < 3.0)
data/lib/et.rb CHANGED
@@ -3,4 +3,6 @@ require "et/runner"
3
3
  require "et/api"
4
4
  require "et/config"
5
5
  require "et/formatter"
6
+ require "et/lesson"
6
7
  require "et/challenge"
8
+ require "et/exercise"
@@ -13,13 +13,13 @@ module ET
13
13
  @token = options[:token]
14
14
  end
15
15
 
16
- def list_challenges
17
- response = RestClient.get(challenges_url)
16
+ def list_lessons
17
+ response = RestClient.get(lessons_url)
18
18
  JSON.parse(response, symbolize_names: true)[:lessons]
19
19
  end
20
20
 
21
- def get_challenge(slug)
22
- response = RestClient.get(challenge_url(slug))
21
+ def get_lesson(slug)
22
+ response = RestClient.get(lesson_url(slug))
23
23
  body = JSON.parse(response, symbolize_names: true)
24
24
  body[:lesson]
25
25
  end
@@ -41,21 +41,21 @@ module ET
41
41
  dest
42
42
  end
43
43
 
44
- def submit_challenge(challenge)
45
- submission_file = challenge.archive!
46
- RestClient.post(submission_url(challenge.slug),
44
+ def submit_lesson(lesson)
45
+ submission_file = lesson.archive!
46
+ RestClient.post(submission_url(lesson.slug),
47
47
  { submission: { archive: File.new(submission_file) }},
48
48
  { "Authorization" => auth_header })
49
49
  end
50
50
 
51
51
  private
52
52
 
53
- def challenge_url(slug)
53
+ def lesson_url(slug)
54
54
  URI.join(host, "lessons/#{slug}.json").to_s
55
55
  end
56
56
 
57
- def challenges_url
58
- URI.join(host, "lessons.json?type=challenge").to_s
57
+ def lessons_url
58
+ URI.join(host, "lessons.json?submittable=1").to_s
59
59
  end
60
60
 
61
61
  def submission_url(slug)
@@ -1,72 +1,7 @@
1
- require "pathname"
2
- require "securerandom"
3
-
4
1
  module ET
5
- class Challenge
6
- attr_reader :cwd
7
-
8
- def initialize(cwd)
9
- @cwd = cwd
10
- end
11
-
12
- def archive!
13
- if exists?
14
- filepath = random_archive_path
15
-
16
- cmd = "tar zcf #{filepath} -C #{dir}"
17
-
18
- ignored_files.each do |file|
19
- cmd += " --exclude='#{file}'"
20
- end
21
-
22
- cmd += " ."
23
-
24
- if system(cmd)
25
- filepath
26
- else
27
- nil
28
- end
29
- else
30
- nil
31
- end
32
- end
33
-
34
- def dir
35
- @dir ||= find_challenge_dir(cwd)
36
- end
37
-
38
- def slug
39
- File.basename(dir)
40
- end
41
-
2
+ class Challenge < Lesson
42
3
  def exists?
43
- !dir.nil?
44
- end
45
-
46
- def ignored_files
47
- (config["ignore"] || []) + [".lesson.yml"]
48
- end
49
-
50
- private
51
-
52
- def config
53
- @config ||= YAML.load(File.read(File.join(dir, ".lesson.yml")))
54
- end
55
-
56
- def random_archive_path
57
- File.join(Dir.mktmpdir, "#{SecureRandom.hex}.tar.gz")
58
- end
59
-
60
- def find_challenge_dir(current_dir)
61
- path = File.join(current_dir, ".lesson.yml")
62
-
63
- if File.exists?(path)
64
- current_dir
65
- elsif current_dir == "." || Pathname.new(current_dir).root?
66
- nil
67
- else
68
- find_challenge_dir(File.dirname(current_dir))
69
- end
4
+ !dir.nil? && config["type"] == "challenge"
70
5
  end
71
6
  end
72
7
  end
@@ -1,3 +1,4 @@
1
+ require "yaml"
1
2
  require "pathname"
2
3
 
3
4
  module ET
@@ -36,9 +37,12 @@ module ET
36
37
  options[key]
37
38
  end
38
39
 
39
- def update(options)
40
- @options = options
41
- File.write(path, options.to_yaml)
40
+ def save!(options)
41
+ if exists?
42
+ File.write(path, options.to_yaml)
43
+ else
44
+ File.write(File.join(current_dir, ".et"), options.to_yaml)
45
+ end
42
46
  end
43
47
 
44
48
  private
@@ -0,0 +1,15 @@
1
+ module ET
2
+ class Exercise < Lesson
3
+ def run_tests
4
+ system("rspec", "--color", "--fail-fast", spec_file)
5
+ end
6
+
7
+ def exists?
8
+ !dir.nil? && config["type"] == "exercise"
9
+ end
10
+
11
+ def spec_file
12
+ File.join(dir, "test", "#{slug.gsub("-", "_")}_test.rb")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,72 @@
1
+ require "pathname"
2
+ require "securerandom"
3
+
4
+ module ET
5
+ class Lesson
6
+ attr_reader :cwd
7
+
8
+ def initialize(cwd)
9
+ @cwd = cwd
10
+ end
11
+
12
+ def archive!
13
+ if exists?
14
+ filepath = random_archive_path
15
+
16
+ cmd = "tar zcf #{filepath} -C #{dir}"
17
+
18
+ ignored_files.each do |file|
19
+ cmd += " --exclude='#{file}'"
20
+ end
21
+
22
+ cmd += " ."
23
+
24
+ if system(cmd)
25
+ filepath
26
+ else
27
+ nil
28
+ end
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def dir
35
+ @dir ||= find_lesson_dir(cwd)
36
+ end
37
+
38
+ def slug
39
+ File.basename(dir)
40
+ end
41
+
42
+ def exists?
43
+ !dir.nil?
44
+ end
45
+
46
+ def ignored_files
47
+ (config["ignore"] || []) + [".lesson.yml"]
48
+ end
49
+
50
+ protected
51
+
52
+ def config
53
+ @config ||= YAML.load_file(File.join(dir, ".lesson.yml"))
54
+ end
55
+
56
+ def random_archive_path
57
+ File.join(Dir.mktmpdir, "#{SecureRandom.hex}.tar.gz")
58
+ end
59
+
60
+ def find_lesson_dir(current_dir)
61
+ path = File.join(current_dir, ".lesson.yml")
62
+
63
+ if File.exists?(path)
64
+ current_dir
65
+ elsif current_dir == "." || Pathname.new(current_dir).root?
66
+ nil
67
+ else
68
+ find_lesson_dir(File.dirname(current_dir))
69
+ end
70
+ end
71
+ end
72
+ end
@@ -16,12 +16,12 @@ module ET
16
16
 
17
17
  pre { |_, _, _, _| check_config! }
18
18
 
19
- desc "Initialize current directory as challenge work area."
19
+ desc "Initialize current directory as a work area."
20
20
  skips_pre
21
21
  command :init do |c|
22
22
  c.flag [:u, :user], desc: "Username"
23
23
  c.flag [:t, :token], desc: "Login token"
24
- c.flag [:h, :host], desc: "Server hosting the challenges"
24
+ c.flag [:h, :host], desc: "Server hosting the lessons"
25
25
 
26
26
  c.action do |_global_options, options, _cmdargs|
27
27
  settings = {
@@ -31,25 +31,25 @@ module ET
31
31
  }
32
32
 
33
33
  settings = prompt_for_missing(settings)
34
- save_config(settings)
34
+ config.save!(settings)
35
35
 
36
36
  puts "Saved configuration to #{config.path}"
37
37
  end
38
38
  end
39
39
 
40
- desc "List available challenges."
40
+ desc "List available lessons."
41
41
  command :list do |c|
42
42
  c.action do |_global_options, _options, _cmdargs|
43
- Formatter.print_table(api.list_challenges, :slug, :title)
43
+ Formatter.print_table(api.list_lessons, :slug, :title, :type)
44
44
  end
45
45
  end
46
46
 
47
- desc "Download challenge to your working area."
47
+ desc "Download lesson to your working area."
48
48
  command :get do |c|
49
49
  c.action do |_global_options, _options, cmdargs|
50
50
  cmdargs.each do |slug|
51
- challenge = api.get_challenge(slug)
52
- archive = api.download_file(challenge[:archive_url])
51
+ lesson = api.get_lesson(slug)
52
+ archive = api.download_file(lesson[:archive_url])
53
53
 
54
54
  if system("tar zxf #{archive} -C #{cwd}")
55
55
  system("rm #{archive}")
@@ -62,16 +62,29 @@ module ET
62
62
  end
63
63
  end
64
64
 
65
- desc "Submit the challenge in this directory."
65
+ desc "Submit the lesson in this directory."
66
66
  command :submit do |c|
67
67
  c.action do |_global_options, _options, _cmdargs|
68
- challenge = Challenge.new(cwd)
68
+ lesson = Lesson.new(cwd)
69
69
 
70
- if challenge.exists?
71
- api.submit_challenge(challenge)
72
- puts "Challenge submitted"
70
+ if lesson.exists?
71
+ api.submit_lesson(lesson)
72
+ puts "Lesson submitted"
73
73
  else
74
- raise StandardError.new("Not in a challenge directory.")
74
+ raise StandardError.new("Not in a lesson directory.")
75
+ end
76
+ end
77
+ end
78
+
79
+ desc "Run an exercise test suite."
80
+ command :test do |c|
81
+ c.action do |_global_options, _options, _cmdargs|
82
+ exercise = Exercise.new(cwd)
83
+
84
+ if exercise.exists?
85
+ exercise.run_tests
86
+ else
87
+ raise StandardError.new("Not in an exercise directory.")
75
88
  end
76
89
  end
77
90
  end
@@ -137,13 +150,5 @@ module ET
137
150
  "Run `et init` to create one.")
138
151
  end
139
152
  end
140
-
141
- def save_config(settings)
142
- if config.exists?
143
- config.update(settings)
144
- else
145
- File.write(File.join(cwd, ".et"), settings.to_yaml)
146
- end
147
- end
148
153
  end
149
154
  end
@@ -1,3 +1,3 @@
1
1
  module ET
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -1,5 +1,5 @@
1
- describe "get challenge" do
2
- let(:challenge_info) do
1
+ describe "get lesson" do
2
+ let(:lesson_info) do
3
3
  {
4
4
  title: "Some Challenge",
5
5
  slug: "some-challenge",
@@ -12,13 +12,13 @@ describe "get challenge" do
12
12
  end
13
13
 
14
14
  context "when in a working area" do
15
- it "downloads and extracts the challenge" do
15
+ it "downloads and extracts the lesson" do
16
16
  tmp_archive_path = File.join(Dir.tmpdir, "some-challenge.tar.gz")
17
- system("cp #{sample_archive_path} #{tmp_archive_path}")
17
+ system("cp", sample_archive_path.to_s, tmp_archive_path)
18
18
 
19
- expect_any_instance_of(ET::API).to receive(:get_challenge).
19
+ expect_any_instance_of(ET::API).to receive(:get_lesson).
20
20
  with("some-challenge").
21
- and_return(challenge_info)
21
+ and_return(lesson_info)
22
22
 
23
23
  expect_any_instance_of(ET::API).to receive(:download_file).
24
24
  with("http://localhost:3000/some-challenge.tar.gz").
@@ -0,0 +1,29 @@
1
+ describe "list lessons" do
2
+ let(:sample_lessons_file) { project_root.join("spec/data/lessons.json") }
3
+
4
+ let(:sample_lessons) do
5
+ JSON.parse(File.read(sample_lessons_file), symbolize_names: true)[:lessons]
6
+ end
7
+
8
+ it "prints the titles and slug" do
9
+ expect_any_instance_of(ET::API).to receive(:list_lessons).
10
+ and_return(sample_lessons)
11
+
12
+ Dir.mktmpdir("test") do |tmpdir|
13
+ write_sample_config_to(tmpdir)
14
+
15
+ runner = ET::Runner.new(tmpdir)
16
+ stdout, _ = capture_output do
17
+ expect(runner.go(["list"])).to eq(0)
18
+ end
19
+
20
+ expect(stdout).to include("Max Number")
21
+ expect(stdout).to include("max-number")
22
+ expect(stdout).to include("exercise")
23
+
24
+ expect(stdout).to include("Optimal Guesser")
25
+ expect(stdout).to include("optimal-guesser")
26
+ expect(stdout).to include("challenge")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ describe "run exercise test suite" do
2
+ context "when in an exercise directory" do
3
+ it "runs the test suite" do
4
+ Dir.mktmpdir("test") do |tmpdir|
5
+ write_sample_config_to(tmpdir)
6
+ exercise_dir = add_sample_exercise(tmpdir)
7
+
8
+ expect_any_instance_of(ET::Exercise).to receive(:run_tests).and_return(true)
9
+
10
+ runner = ET::Runner.new(exercise_dir)
11
+ _, _ = capture_output do
12
+ expect(runner.go(["test"])).to eq(0)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ context "when not in an exercise directory" do
19
+ it "fails to run the test suite" do
20
+ Dir.mktmpdir("test") do |tmpdir|
21
+ write_sample_config_to(tmpdir)
22
+ expect_any_instance_of(ET::Exercise).to_not receive(:run_tests)
23
+
24
+ runner = ET::Runner.new(tmpdir)
25
+ _, _ = capture_output do
26
+ expect(runner.go(["test"])).to eq(1)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ describe "submit lesson" do
2
+ let(:sample_archive_path) do
3
+ project_root.join("spec/data/archive.tar.gz")
4
+ end
5
+
6
+ context "when in a working area" do
7
+ it "packages and uploads a challenge directory" do
8
+ Dir.mktmpdir("test") do |tmpdir|
9
+ write_sample_config_to(tmpdir)
10
+ challenge_dir = add_sample_challenge(tmpdir)
11
+
12
+ expect_any_instance_of(ET::API).to receive(:submit_lesson).
13
+ and_return(true)
14
+
15
+ runner = ET::Runner.new(challenge_dir)
16
+ _, _ = capture_output do
17
+ expect(runner.go(["submit"])).to eq(0)
18
+ end
19
+ end
20
+ end
21
+
22
+ it "packages and uploads an exercise directory" do
23
+ Dir.mktmpdir("test") do |tmpdir|
24
+ write_sample_config_to(tmpdir)
25
+ exercise_dir = add_sample_exercise(tmpdir)
26
+
27
+ expect_any_instance_of(ET::API).to receive(:submit_lesson).
28
+ and_return(true)
29
+
30
+ runner = ET::Runner.new(exercise_dir)
31
+ _, _ = capture_output do
32
+ expect(runner.go(["submit"])).to eq(0)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1 +1,8 @@
1
- {"lesson":{"slug":"rock-paper-scissors","title":"Rock, Paper, Scissors","body":"body goes here...","archive_url":"http://example.com/rock-paper-scissors.tar.gz"}}
1
+ {
2
+ "lesson": {
3
+ "archive_url": "http://example.com/rock-paper-scissors.tar.gz",
4
+ "body": "body goes here...",
5
+ "slug": "rock-paper-scissors",
6
+ "title": "Rock, Paper, Scissors"
7
+ }
8
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "lessons": [
3
+ {
4
+ "slug": "max-number",
5
+ "title": "Max Number",
6
+ "type": "exercise"
7
+ },
8
+ {
9
+ "slug": "guess-the-number",
10
+ "title": "Guess the Number",
11
+ "type": "challenge"
12
+ },
13
+ {
14
+ "slug": "optimal-guesser",
15
+ "title": "Optimal Guesser",
16
+ "type": "challenge"
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Sample Challenge"
3
+ type: "challenge"
4
+ description: "Some description."
5
+ ignore:
6
+ - "sample-challenge.md"
@@ -0,0 +1 @@
1
+ # YOUR CODE GOES HERE
@@ -0,0 +1,3 @@
1
+ ### Instructions
2
+
3
+ Do something.
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Sample Exercise"
3
+ type: "exercise"
4
+ description: "Some description here."
5
+ ignore:
6
+ - "sample-exercise.md"
@@ -0,0 +1,3 @@
1
+ ### Instructions
2
+
3
+ Do something.
@@ -0,0 +1,7 @@
1
+ require_relative "../lib/sample_exercise"
2
+
3
+ describe "something" do
4
+ it "works" do
5
+ expect(true).to eq(true)
6
+ end
7
+ end
@@ -1,33 +1,34 @@
1
1
  describe ET::API do
2
2
  let(:api) { ET::API.new(host: "http://localhost:3000") }
3
3
 
4
- describe "challenges" do
5
- let(:challenges_response) do
6
- File.read("spec/data/challenges.json")
4
+ describe "lessons" do
5
+ let(:lessons_response) do
6
+ File.read("spec/data/lessons.json")
7
7
  end
8
8
 
9
- it "queries for a list of challenges" do
9
+ it "queries for a list of lessons" do
10
10
  expect(RestClient).to receive(:get).
11
- with("http://localhost:3000/lessons.json?type=challenge").
12
- and_return(challenges_response)
11
+ with("http://localhost:3000/lessons.json?submittable=1").
12
+ and_return(lessons_response)
13
13
 
14
- results = api.list_challenges
14
+ results = api.list_lessons
15
15
 
16
- expect(results.count).to eq(2)
17
- expect(results[0][:title]).to eq("Auto-Guesser")
18
- expect(results[0][:slug]).to eq("auto-guesser")
16
+ expect(results.count).to eq(3)
17
+ expect(results[0][:title]).to eq("Max Number")
18
+ expect(results[0][:slug]).to eq("max-number")
19
+ expect(results[0][:type]).to eq("exercise")
19
20
  end
20
21
 
21
- let(:challenge_response) do
22
+ let(:lesson_response) do
22
23
  File.read("spec/data/challenge.json")
23
24
  end
24
25
 
25
- it "queries for a single challenge" do
26
+ it "queries for a single lesson" do
26
27
  expect(RestClient).to receive(:get).
27
28
  with("http://localhost:3000/lessons/rock-paper-scissors.json").
28
- and_return(challenge_response)
29
+ and_return(lesson_response)
29
30
 
30
- result = api.get_challenge("rock-paper-scissors")
31
+ result = api.get_lesson("rock-paper-scissors")
31
32
 
32
33
  expect(result[:title]).to eq("Rock, Paper, Scissors")
33
34
  expect(result[:archive_url]).to eq("http://example.com/rock-paper-scissors.tar.gz")
@@ -1,18 +1,10 @@
1
1
  require "yaml"
2
2
 
3
3
  describe ET::Challenge do
4
- let(:challenge_info) do
5
- {
6
- "title" => "Guess the Number",
7
- "ignore" => ["README.md"]
8
- }
9
- end
10
-
11
4
  describe "#dir" do
12
5
  it "selects the directory containing the challenge file" do
13
- Dir.mktmpdir do |challenge_dir|
14
- challenge_path = File.join(challenge_dir, ".lesson.yml")
15
- File.write(challenge_path, challenge_info.to_yaml)
6
+ Dir.mktmpdir do |tmpdir|
7
+ challenge_dir = add_sample_challenge(tmpdir)
16
8
 
17
9
  challenge = ET::Challenge.new(challenge_dir)
18
10
  expect(challenge.dir).to eq(challenge_dir)
@@ -20,20 +12,22 @@ describe ET::Challenge do
20
12
  end
21
13
 
22
14
  it "checks parent directories for the challenge file" do
23
- Dir.mktmpdir do |parent_dir|
24
- challenge_path = File.join(parent_dir, ".lesson.yml")
25
- File.write(challenge_path, challenge_info.to_yaml)
15
+ Dir.mktmpdir do |tmpdir|
16
+ challenge_dir = add_sample_challenge(tmpdir)
26
17
 
27
- child_dir = File.join(parent_dir, "foobar")
18
+ child_dir = File.join(challenge_dir, "child")
19
+ Dir.mkdir(child_dir)
28
20
 
29
21
  challenge = ET::Challenge.new(child_dir)
30
- expect(challenge.dir).to eq(parent_dir)
22
+ expect(challenge.dir).to eq(challenge_dir)
31
23
  end
32
24
  end
33
25
 
34
26
  it "returns nil if no challenge file found" do
35
- challenge = ET::Challenge.new(Dir.tmpdir)
36
- expect(challenge.dir).to eq(nil)
27
+ Dir.mktmpdir do |tmpdir|
28
+ challenge = ET::Challenge.new(tmpdir)
29
+ expect(challenge.dir).to eq(nil)
30
+ end
37
31
  end
38
32
  end
39
33
 
@@ -42,18 +36,14 @@ describe ET::Challenge do
42
36
  archive_path = nil
43
37
 
44
38
  begin
45
- Dir.mktmpdir do |challenge_dir|
46
- challenge_path = File.join(challenge_dir, ".lesson.yml")
47
- File.write(challenge_path, challenge_info.to_yaml)
48
-
49
- file_path = File.join(challenge_dir, "file.rb")
50
- File.write(file_path, "2 + 2 == 5")
39
+ Dir.mktmpdir do |tmpdir|
40
+ challenge_dir = add_sample_challenge(tmpdir)
51
41
 
52
42
  challenge = ET::Challenge.new(challenge_dir)
53
43
  archive_path = challenge.archive!
54
44
 
55
- contents = read_file_from_gzipped_archive(archive_path, "./file.rb")
56
- expect(contents).to eq("2 + 2 == 5")
45
+ contents = read_file_from_gzipped_archive(archive_path, "./problem.rb")
46
+ expect(contents).to eq("# YOUR CODE GOES HERE\n")
57
47
  end
58
48
  ensure
59
49
  if archive_path && File.exist?(archive_path)
@@ -66,18 +56,16 @@ describe ET::Challenge do
66
56
  archive_path = nil
67
57
 
68
58
  begin
69
- Dir.mktmpdir do |dir|
70
- File.write(File.join(dir, ".lesson.yml"), challenge_info.to_yaml)
71
- File.write(File.join(dir, "file.rb"), "2 + 2 == 5")
72
- File.write(File.join(dir, "README.md"), "Ignore me!")
59
+ Dir.mktmpdir do |tmpdir|
60
+ challenge_dir = add_sample_challenge(tmpdir)
73
61
 
74
- challenge = ET::Challenge.new(dir)
62
+ challenge = ET::Challenge.new(challenge_dir)
75
63
  archive_path = challenge.archive!
76
64
 
77
65
  files = list_files_in_gzipped_archive(archive_path)
78
66
 
79
- expect(files).to include("./file.rb")
80
- expect(files).to_not include("./README.md")
67
+ expect(files).to include("./problem.rb")
68
+ expect(files).to_not include("./sample-challenge.md")
81
69
  expect(files).to_not include("./.lesson.yml")
82
70
  end
83
71
  ensure
@@ -1,4 +1,51 @@
1
+ require "yaml"
2
+
1
3
  describe ET::Config do
4
+ describe "#save" do
5
+ let(:options) do
6
+ {
7
+ "username" => "foobar",
8
+ "token" => "supersecret",
9
+ "host" => "http://example.com"
10
+ }
11
+ end
12
+
13
+ it "writes a new config file if doesn't exist" do
14
+ Dir.mktmpdir("test") do |tmpdir|
15
+ config = ET::Config.new(tmpdir)
16
+ config.save!(options)
17
+
18
+ config_file = File.join(tmpdir, ".et")
19
+ expect(File.exists?(config_file)).to eq(true)
20
+
21
+ saved_options = YAML.load_file(config_file)
22
+
23
+ options.each do |key, value|
24
+ expect(saved_options[key]).to eq(value)
25
+ end
26
+ end
27
+ end
28
+
29
+ it "updates an existing config file with new options" do
30
+ Dir.mktmpdir("test") do |parent_dir|
31
+ nested_dir = File.join(parent_dir, "nested")
32
+ Dir.mkdir(nested_dir)
33
+
34
+ write_sample_config_to(parent_dir)
35
+
36
+ config = ET::Config.new(nested_dir)
37
+ config.save!(options)
38
+
39
+ expect(File.exists?(File.join(nested_dir, ".et"))).to eq(false)
40
+
41
+ saved_options = YAML.load_file(File.join(parent_dir, ".et"))
42
+ options.each do |key, value|
43
+ expect(saved_options[key]).to eq(value)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
2
49
  describe "#path" do
3
50
  it "finds the config file in the given directory" do
4
51
  Dir.mktmpdir("test") do |tmpdir|
@@ -37,7 +84,7 @@ describe ET::Config do
37
84
  end
38
85
  end
39
86
 
40
- it "preprends http if scheme not provided" do
87
+ it "prepends http if scheme not provided" do
41
88
  Dir.mktmpdir("test") do |tmpdir|
42
89
  write_sample_config_to(tmpdir, "host" => "example.com")
43
90
 
@@ -0,0 +1,28 @@
1
+ describe ET::Exercise do
2
+ describe "#exists?" do
3
+ it "is true if within an exercise directory" do
4
+ Dir.mktmpdir do |tmpdir|
5
+ exercise_dir = add_sample_exercise(tmpdir)
6
+ exercise = ET::Exercise.new(exercise_dir)
7
+
8
+ expect(exercise.exists?).to eq(true)
9
+ end
10
+ end
11
+
12
+ it "is false when in a challenge directory" do
13
+ Dir.mktmpdir do |tmpdir|
14
+ challenge_dir = add_sample_challenge(tmpdir)
15
+ exercise = ET::Exercise.new(challenge_dir)
16
+
17
+ expect(exercise.exists?).to eq(false)
18
+ end
19
+ end
20
+
21
+ it "is false when not in a lesson dir" do
22
+ Dir.mktmpdir do |tmpdir|
23
+ exercise = ET::Exercise.new(tmpdir)
24
+ expect(exercise.exists?).to eq(false)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -2,29 +2,27 @@ require "yaml"
2
2
 
3
3
  module SampleFiles
4
4
  def write_sample_config_to(dir, additional_settings = nil)
5
- config = {
5
+ settings = {
6
6
  "username" => "bob",
7
7
  "token" => "1234",
8
8
  "host" => "http://localhost:3000"
9
9
  }
10
10
 
11
11
  if additional_settings
12
- config = config.merge(additional_settings)
12
+ settings = settings.merge(additional_settings)
13
13
  end
14
14
 
15
- path = File.join(dir, ".et")
16
- File.write(path, config.to_yaml)
15
+ config = ET::Config.new(dir)
16
+ config.save!(settings)
17
17
  end
18
18
 
19
- def write_sample_challenge_to(working_dir, slug)
20
- options = { "title" => slug.capitalize, "slug" => slug }
21
-
22
- dir = File.join(working_dir, slug)
23
- system("mkdir #{dir}")
24
-
25
- File.write(File.join(dir, "README.md"), "# README")
26
- File.write(File.join(dir, ".lesson.yml"), options.to_yaml)
19
+ def add_sample_exercise(dir)
20
+ system("cp", "-r", project_root.join("spec/data/sample-exercise").to_s, dir)
21
+ File.join(dir, "sample-exercise")
22
+ end
27
23
 
28
- dir
24
+ def add_sample_challenge(dir)
25
+ system("cp", "-r", project_root.join("spec/data/sample-challenge").to_s, dir)
26
+ File.join(dir, "sample-challenge")
29
27
  end
30
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: et
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Sheehan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-03 00:00:00.000000000 Z
11
+ date: 2014-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -104,19 +104,30 @@ files:
104
104
  - lib/et/api.rb
105
105
  - lib/et/challenge.rb
106
106
  - lib/et/config.rb
107
+ - lib/et/exercise.rb
107
108
  - lib/et/formatter.rb
109
+ - lib/et/lesson.rb
108
110
  - lib/et/runner.rb
109
111
  - lib/et/version.rb
110
- - spec/cli/get_challenge_spec.rb
112
+ - spec/cli/get_lesson_spec.rb
111
113
  - spec/cli/init_spec.rb
112
- - spec/cli/list_challenges_spec.rb
113
- - spec/cli/submit_challenge_spec.rb
114
+ - spec/cli/list_lessons_spec.rb
115
+ - spec/cli/run_exercise_test_suite_spec.rb
116
+ - spec/cli/submit_lesson_spec.rb
114
117
  - spec/data/challenge.json
115
- - spec/data/challenges.json
118
+ - spec/data/lessons.json
119
+ - spec/data/sample-challenge/.lesson.yml
120
+ - spec/data/sample-challenge/problem.rb
121
+ - spec/data/sample-challenge/sample-challenge.md
122
+ - spec/data/sample-exercise/.lesson.yml
123
+ - spec/data/sample-exercise/lib/sample_exercise.rb
124
+ - spec/data/sample-exercise/sample-exercise.md
125
+ - spec/data/sample-exercise/test/sample_exercise_test.rb
116
126
  - spec/data/some-challenge.tar.gz
117
127
  - spec/lib/api_spec.rb
118
128
  - spec/lib/challenge_spec.rb
119
129
  - spec/lib/config_spec.rb
130
+ - spec/lib/exercise_spec.rb
120
131
  - spec/spec_helper.rb
121
132
  - spec/support/helpers/archive_helper.rb
122
133
  - spec/support/helpers/output_catcher.rb
@@ -1,25 +0,0 @@
1
- describe "list challenges" do
2
- let(:sample_challenges) do
3
- JSON.parse(File.read("spec/data/challenges.json"), symbolize_names: true)[:lessons]
4
- end
5
-
6
- it "prints the titles and slug" do
7
- expect_any_instance_of(ET::API).to receive(:list_challenges).
8
- and_return(sample_challenges)
9
-
10
- Dir.mktmpdir("test") do |tmpdir|
11
- write_sample_config_to(tmpdir)
12
-
13
- runner = ET::Runner.new(tmpdir)
14
- stdout, _ = capture_output do
15
- expect(runner.go(["list"])).to eq(0)
16
- end
17
-
18
- expect(stdout).to include("Guess the Number")
19
- expect(stdout).to include("guess-the-number")
20
-
21
- expect(stdout).to include("Auto-Guesser")
22
- expect(stdout).to include("auto-guesser")
23
- end
24
- end
25
- end
@@ -1,22 +0,0 @@
1
- describe "submit challenge" do
2
- let(:sample_archive_path) do
3
- project_root.join("spec/data/archive.tar.gz")
4
- end
5
-
6
- context "when in a working area" do
7
- it "packages and uploads directory" do
8
- Dir.mktmpdir("test") do |tmpdir|
9
- write_sample_config_to(tmpdir)
10
- challenge_dir = write_sample_challenge_to(tmpdir, "some-challenge")
11
-
12
- expect_any_instance_of(ET::API).to receive(:submit_challenge).
13
- and_return(true)
14
-
15
- runner = ET::Runner.new(challenge_dir)
16
- _, _ = capture_output do
17
- expect(runner.go(["submit"])).to eq(0)
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1 +0,0 @@
1
- {"lessons":[{"title":"Auto-Guesser","slug":"auto-guesser"},{"title":"Guess the Number","slug":"guess-the-number"}]}