et 0.4.0 → 0.5.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.
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"}]}