learn-co 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +45 -0
- data/Rakefile +2 -0
- data/bin/learn +76 -0
- data/learn-0.0.6.gem +0 -0
- data/learn-co.gemspec +30 -0
- data/lib/learn.rb +26 -0
- data/lib/learn/file_finder.rb +12 -0
- data/lib/learn/github_interactor.rb +23 -0
- data/lib/learn/jasmine/boot.js +184 -0
- data/lib/learn/jasmine/console.js +161 -0
- data/lib/learn/jasmine/formatters/jasmine2-junit.js +199 -0
- data/lib/learn/jasmine/helpers/ConsoleHelper.js +12 -0
- data/lib/learn/jasmine/helpers/ConsoleHelperNoColor.js +12 -0
- data/lib/learn/jasmine/initializer.rb +27 -0
- data/lib/learn/jasmine/jasmine-html.js +360 -0
- data/lib/learn/jasmine/jasmine-jquery.js +813 -0
- data/lib/learn/jasmine/jasmine.css +56 -0
- data/lib/learn/jasmine/jasmine.js +2403 -0
- data/lib/learn/jasmine/jasmine_favicon.png +0 -0
- data/lib/learn/jasmine/jquery-1.8.0.min.js +2 -0
- data/lib/learn/jasmine/jquery-ui-1.8.23.custom.min.js +125 -0
- data/lib/learn/jasmine/phantom_checker.rb +33 -0
- data/lib/learn/jasmine/runner.rb +129 -0
- data/lib/learn/jasmine/runners/SpecRunner.html +35 -0
- data/lib/learn/jasmine/runners/run-jasmine.js +228 -0
- data/lib/learn/jasmine/templates/SpecRunnerTemplate.html.erb +35 -0
- data/lib/learn/jasmine/templates/SpecRunnerTemplateNoColor.html.erb +35 -0
- data/lib/learn/jasmine/templates/requires.yml.example +7 -0
- data/lib/learn/jasmine/vendor/require.js +2077 -0
- data/lib/learn/netrc_interactor.rb +18 -0
- data/lib/learn/python_unittest/nose_installer.rb +35 -0
- data/lib/learn/python_unittest/requirements_checker.rb +57 -0
- data/lib/learn/python_unittest/runner.rb +89 -0
- data/lib/learn/repo_parser.rb +22 -0
- data/lib/learn/rspec/runner.rb +113 -0
- data/lib/learn/spec_type_parser.rb +26 -0
- data/lib/learn/user_id_parser.rb +9 -0
- data/lib/learn/username_parser.rb +19 -0
- data/lib/learn/version.rb +3 -0
- data/spec/features/jasmine_jquery_fixtures_spec.rb +10 -0
- data/spec/features/rspec_unit_spec.rb +10 -0
- data/spec/fixtures/jasmine-jquery-fixtures/index.html +10 -0
- data/spec/fixtures/jasmine-jquery-fixtures/requires.yml +4 -0
- data/spec/fixtures/jasmine-jquery-fixtures/spec/jasmine-jquery-fixtures-spec.js +11 -0
- data/spec/fixtures/rspec-unit-spec/.rspec +2 -0
- data/spec/fixtures/rspec-unit-spec/lib/dog.rb +2 -0
- data/spec/fixtures/rspec-unit-spec/spec/dog_spec.rb +7 -0
- data/spec/fixtures/rspec-unit-spec/spec/spec_helper.rb +93 -0
- data/spec/repo_parser_spec.rb +25 -0
- data/spec/spec_helper.rb +10 -0
- metadata +237 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'netrc'
|
2
|
+
|
3
|
+
module Learn
|
4
|
+
class NetrcInteractor
|
5
|
+
attr_reader :username, :user_id, :netrc
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@netrc = Netrc.read
|
9
|
+
@username, @user_id = netrc["flatiron-push"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(username, user_id)
|
13
|
+
netrc["flatiron-push"] = username, user_id
|
14
|
+
netrc.save
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Learn
|
2
|
+
module PythonUnittest
|
3
|
+
class NoseInstaller
|
4
|
+
def self.install
|
5
|
+
new.install
|
6
|
+
end
|
7
|
+
|
8
|
+
def install
|
9
|
+
install_nose
|
10
|
+
install_nose_json
|
11
|
+
end
|
12
|
+
|
13
|
+
def install_nose
|
14
|
+
if !nose_installed?
|
15
|
+
`pip install nose`
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def nose_installed?
|
20
|
+
!`which nosetests`.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def install_nose_json
|
24
|
+
if !nose_json_installed?
|
25
|
+
`pip install nose-json`
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def nose_json_installed?
|
30
|
+
!`pip show nose-json`.empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Learn
|
4
|
+
module PythonUnittest
|
5
|
+
class RequirementsChecker
|
6
|
+
def self.check_installation
|
7
|
+
new.check_installation
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_installation
|
11
|
+
PythonChecker.check
|
12
|
+
PipChecker.check
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class PythonChecker
|
17
|
+
def self.check
|
18
|
+
new.check
|
19
|
+
end
|
20
|
+
|
21
|
+
def check
|
22
|
+
if !python_installed? || !correct_python_version?
|
23
|
+
puts "Please install python 2.7.x or 3.x.x"
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def python_installed?
|
29
|
+
!`which python`.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def correct_python_version?
|
33
|
+
output = Open3.popen3('python', '--version')
|
34
|
+
version = output[2].read.strip
|
35
|
+
!!version.match(/ 2.7.*| 3.*/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class PipChecker
|
40
|
+
def self.check
|
41
|
+
new.check
|
42
|
+
end
|
43
|
+
|
44
|
+
def check
|
45
|
+
if !pip_installed?
|
46
|
+
puts "Please ensure pip is installed"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def pip_installed?
|
52
|
+
!`which pip`.empty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Learn
|
2
|
+
module PythonUnittest
|
3
|
+
class Runner
|
4
|
+
attr_accessor :parsed_output, :json_output, :formatted_results
|
5
|
+
attr_reader :username, :user_id, :repo_name, :options, :connection
|
6
|
+
|
7
|
+
def initialize(username, user_id, repo_name, options)
|
8
|
+
@username = username
|
9
|
+
@user_id = user_id
|
10
|
+
@repo_name = repo_name
|
11
|
+
@options = options
|
12
|
+
@json_output = ""
|
13
|
+
@parsed_output = nil
|
14
|
+
@formatted_results = {}
|
15
|
+
@connection = Faraday.new(url: SERVICE_URL) do |faraday|
|
16
|
+
faraday.adapter Faraday.default_adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
run_nose
|
22
|
+
if !options.include?('-h') && !options.include?('--help')
|
23
|
+
set_json_output
|
24
|
+
jsonify
|
25
|
+
format_results
|
26
|
+
push_results
|
27
|
+
cleanup
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_nose
|
32
|
+
system("nosetests #{options.join(' ')} --verbose --with-json --json-file='./.results.json'")
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_json_output
|
36
|
+
self.json_output = File.read('.results.json')
|
37
|
+
end
|
38
|
+
|
39
|
+
def jsonify
|
40
|
+
self.parsed_output = Oj.load(json_output, symbol_keys: true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def format_results
|
44
|
+
self.formatted_results.merge!({
|
45
|
+
username: username,
|
46
|
+
github_user_id: user_id,
|
47
|
+
repo_name: repo_name,
|
48
|
+
build: {
|
49
|
+
test_suite: [{
|
50
|
+
framework: 'unittest',
|
51
|
+
formatted_output: parsed_output,
|
52
|
+
duration: calculate_duration
|
53
|
+
}]
|
54
|
+
},
|
55
|
+
examples: parsed_output[:stats][:total],
|
56
|
+
passing_count: parsed_output[:stats][:passes],
|
57
|
+
pending_count: parsed_output[:stats][:skipped],
|
58
|
+
failure_count: parsed_output[:stats][:errors],
|
59
|
+
failure_descriptions: concat_failure_descriptions
|
60
|
+
})
|
61
|
+
end
|
62
|
+
|
63
|
+
def calculate_duration
|
64
|
+
parsed_output[:results].map do |example|
|
65
|
+
example[:time]
|
66
|
+
end.inject(:+)
|
67
|
+
end
|
68
|
+
|
69
|
+
def concat_failure_descriptions
|
70
|
+
parsed_output[:results].select do |example|
|
71
|
+
example[:type] == 'failure'
|
72
|
+
end.map { |ex| ex[:tb] }.join(';')
|
73
|
+
end
|
74
|
+
|
75
|
+
def push_results
|
76
|
+
connection.post do |req|
|
77
|
+
req.url SERVICE_ENDPOINT
|
78
|
+
req.headers['Content-Type'] = 'application/json'
|
79
|
+
req.body = Oj.dump(formatted_results, mode: :compat)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def cleanup
|
84
|
+
FileUtils.rm('.results.json')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module Learn
|
4
|
+
class RepoParser
|
5
|
+
def self.get_repo
|
6
|
+
begin
|
7
|
+
repo = Git.open(FileUtils.pwd)
|
8
|
+
rescue
|
9
|
+
puts "Not a valid Git repository"
|
10
|
+
die
|
11
|
+
end
|
12
|
+
|
13
|
+
url = repo.remote.url
|
14
|
+
url.match(/(?:https:\/\/|git@).*\/(.+?)(?:\.git)?$/)[1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.die
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Learn
|
2
|
+
module RSpec
|
3
|
+
class Runner
|
4
|
+
attr_accessor :parsed_output, :json_output, :formatted_results
|
5
|
+
attr_reader :username, :user_id, :repo_name, :options, :connection
|
6
|
+
|
7
|
+
def initialize(username, user_id, repo_name, options)
|
8
|
+
@username = username
|
9
|
+
@user_id = user_id
|
10
|
+
@repo_name = repo_name
|
11
|
+
@options = options
|
12
|
+
@json_output = ""
|
13
|
+
@parsed_output = nil
|
14
|
+
@formatted_results = {}
|
15
|
+
@connection = Faraday.new(url: SERVICE_URL) do |faraday|
|
16
|
+
faraday.adapter Faraday.default_adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
check_options
|
22
|
+
run_rspec
|
23
|
+
if !options.include?('-h') && !options.include?('--help')
|
24
|
+
set_json_output
|
25
|
+
jsonify
|
26
|
+
format_results
|
27
|
+
push_results
|
28
|
+
cleanup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_options
|
33
|
+
options_has_format = options.include?('--format') || options.include?('-f')
|
34
|
+
if dot_rspec = read_dot_rspec
|
35
|
+
if options_has_format
|
36
|
+
if dot_rspec.any? {|dot_opt| dot_opt.match(/--format|-f/)}
|
37
|
+
options << dot_rspec.reject {|dot_opt| dot_opt.match(/--format|-f/)}
|
38
|
+
else
|
39
|
+
options << dot_rspec
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if options_has_format
|
45
|
+
self.options.flatten!
|
46
|
+
else
|
47
|
+
options.unshift('--format documentation')
|
48
|
+
end
|
49
|
+
|
50
|
+
# Don't pass the test/local flag from learn binary to rspec runner.
|
51
|
+
options.delete("--test")
|
52
|
+
options.delete("-t")
|
53
|
+
options.delete("-l")
|
54
|
+
options.delete("--local")
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_dot_rspec
|
58
|
+
if File.exist?('.rspec')
|
59
|
+
File.readlines('.rspec').map(&:strip)
|
60
|
+
else
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_rspec
|
66
|
+
system("rspec #{options.join(' ')} --format j --out .results.json")
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_json_output
|
70
|
+
self.json_output = File.read('.results.json')
|
71
|
+
end
|
72
|
+
|
73
|
+
def jsonify
|
74
|
+
self.parsed_output = Oj.load(json_output, symbol_keys: true)
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_results
|
78
|
+
self.formatted_results.merge!({
|
79
|
+
username: username,
|
80
|
+
github_user_id: user_id,
|
81
|
+
repo_name: repo_name,
|
82
|
+
build: {
|
83
|
+
test_suite: [{
|
84
|
+
framework: 'rspec',
|
85
|
+
formatted_output: parsed_output,
|
86
|
+
duration: parsed_output[:summary][:duration]
|
87
|
+
}]
|
88
|
+
},
|
89
|
+
examples: parsed_output[:summary][:example_count],
|
90
|
+
passing_count: parsed_output[:summary][:example_count] - parsed_output[:summary][:failure_count] - parsed_output[:summary][:pending_count],
|
91
|
+
pending_count: parsed_output[:summary][:pending_count],
|
92
|
+
failure_count: parsed_output[:summary][:failure_count],
|
93
|
+
failure_descriptions: parsed_output[:examples].select do |example|
|
94
|
+
example[:status] == "failed"
|
95
|
+
end.map { |ex| ex[:full_description] }.join(";")
|
96
|
+
})
|
97
|
+
end
|
98
|
+
|
99
|
+
def push_results
|
100
|
+
connection.post do |req|
|
101
|
+
req.url SERVICE_ENDPOINT
|
102
|
+
req.headers['Content-Type'] = 'application/json'
|
103
|
+
req.body = Oj.dump(formatted_results, mode: :compat)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def cleanup
|
108
|
+
FileUtils.rm('.results.json')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Learn
|
2
|
+
class SpecTypeParser
|
3
|
+
attr_reader :spec_type
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@spec_type = parse_spec_type
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def parse_spec_type
|
12
|
+
files = Dir.entries('.')
|
13
|
+
|
14
|
+
if files.include?('requires.yml')
|
15
|
+
'jasmine'
|
16
|
+
elsif files.any? {|f| f.match(/.*.py$/) }
|
17
|
+
'python_unittest'
|
18
|
+
elsif files.include?('spec')
|
19
|
+
spec_files = Dir.entries('./spec')
|
20
|
+
if spec_files.include?('spec_helper.rb') || spec_files.include?('rails_helper.rb')
|
21
|
+
'rspec'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Learn
|
2
|
+
class UsernameParser
|
3
|
+
def self.get_username
|
4
|
+
parser = Learn::NetrcInteractor.new
|
5
|
+
username = parser.username
|
6
|
+
user_id = parser.user_id
|
7
|
+
|
8
|
+
if !username || user_id == 'none'
|
9
|
+
print "Enter your github username: "
|
10
|
+
username = gets.strip
|
11
|
+
user_id = Learn::GithubInteractor.get_user_id_for(username)
|
12
|
+
parser.write(username, user_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
username
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe "Running a Jasmine jQuery Specs with Fixtures" do
|
2
|
+
context 'without a browser through PhantomJS' do
|
3
|
+
it 'runs the spec with 0 failures' do
|
4
|
+
output = `cd ./spec/fixtures/jasmine-jquery-fixtures && ./../../../bin/learn --local --test`
|
5
|
+
|
6
|
+
expect(output).to include('1 spec, 0 failures')
|
7
|
+
expect(output).to_not include('1 failures')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe "Running a RSpec Unit Test" do
|
2
|
+
context 'a basic rspec unit test' do
|
3
|
+
it 'runs the spec with 0 failures' do
|
4
|
+
output = `cd ./spec/fixtures/rspec-unit-spec && ./../../../bin/learn --local --test`
|
5
|
+
|
6
|
+
expect(output).to include('1 example, 0 failures')
|
7
|
+
expect(output).to_not include('1 failures')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|