cm_quiz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b05cd24b052e990f291c22473aef0e934b97036c
4
+ data.tar.gz: 5b36e76983e7e4c0b6e8fce097d2c4a9ceee5da2
5
+ SHA512:
6
+ metadata.gz: b17e359ef50450552ea190d5715092a42680caae1c5e4d0f736c0eb8569319d1255ca9ab62be8c007787f82ec8e8f45fe3c10cdc9721dd3f8070d235dbe0941b
7
+ data.tar.gz: a22c7ecb03e6fa494aec8aad9bd56683c00339c7aea06a284a60171c2b1aa79f52fce9f5f230bcc75eaf15f1ba51e8f907c88eb6c6fe85e91ef5353ce6a4052e
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'pry'
5
+ end
6
+
7
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cm_quiz (0.0.1)
5
+ httparty
6
+ rspec
7
+ thor (~> 0.19.4)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.5.2)
13
+ public_suffix (>= 2.0.2, < 4.0)
14
+ coderay (1.1.2)
15
+ crack (0.4.3)
16
+ safe_yaml (~> 1.0.0)
17
+ diff-lcs (1.3)
18
+ hashdiff (0.3.6)
19
+ httparty (0.15.6)
20
+ multi_xml (>= 0.5.2)
21
+ method_source (0.8.2)
22
+ multi_xml (0.6.0)
23
+ pry (0.10.4)
24
+ coderay (~> 1.1.0)
25
+ method_source (~> 0.8.1)
26
+ slop (~> 3.4)
27
+ public_suffix (3.0.0)
28
+ rspec (3.6.0)
29
+ rspec-core (~> 3.6.0)
30
+ rspec-expectations (~> 3.6.0)
31
+ rspec-mocks (~> 3.6.0)
32
+ rspec-core (3.6.0)
33
+ rspec-support (~> 3.6.0)
34
+ rspec-expectations (3.6.0)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.6.0)
37
+ rspec-mocks (3.6.0)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.6.0)
40
+ rspec-support (3.6.0)
41
+ safe_yaml (1.0.4)
42
+ slop (3.6.0)
43
+ thor (0.19.4)
44
+ webmock (3.0.1)
45
+ addressable (>= 2.3.6)
46
+ crack (>= 0.3.2)
47
+ hashdiff
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ cm_quiz!
54
+ pry
55
+ webmock
56
+
57
+ BUNDLED WITH
58
+ 1.15.0
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # cm-quiz
data/bin/cm-quiz ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_dir = File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
4
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
5
+
6
+ require 'cm_quiz/cli'
7
+
8
+ CmQuiz::CLI.start(ARGV)
data/cm_quiz.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
2
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
3
+ require 'cm_quiz/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'cm_quiz'
7
+ s.version = CmQuiz::VERSION
8
+ s.date = '2017-09-12'
9
+ s.summary = "Review your codementor quiz"
10
+ s.description = "Review your codementor quiz1"
11
+ s.authors = ["ben"]
12
+ s.email = 'ben@codementor.ios'
13
+ s.executables = ["cm-quiz"]
14
+ s.files = `git ls-files`.split($/)
15
+ s.homepage =
16
+ 'https://github.com/codementordev/cm_quiz'
17
+ s.license = 'MIT'
18
+ s.required_ruby_version = '>= 2.3'
19
+
20
+ s.add_dependency('thor', ["~> 0.19.4"])
21
+ s.add_dependency("rspec", ["~> 3.6"])
22
+ s.add_dependency("httparty", ["~> 0.15.6"])
23
+ s.add_development_dependency("webmock", ["~> 3.0"])
24
+ end
@@ -0,0 +1,22 @@
1
+ require 'thor'
2
+ require 'cm_quiz'
3
+
4
+ module CmQuiz
5
+ class CLI< Thor
6
+ map '--version' => :version
7
+
8
+ desc 'version', 'Prints the cm_quiz version'
9
+ def version
10
+ puts "#{File.basename($0)} #{VERSION}"
11
+ end
12
+
13
+ desc 'test', 'Test your api implement'
14
+ option :endpoint, required: true, banner: "your-test-endpoint.com"
15
+ def test
16
+ endpoint = options[:endpoint]
17
+ puts "Start test #{endpoint}"
18
+ message = CmQuiz::ReviewQuiz.new('http://localhost:6000').perform
19
+ puts message
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ require 'securerandom'
2
+
3
+ module CmQuiz
4
+ module Factory
5
+ class Idea
6
+ def initialize(project_api:, jwt:, idea_params: {})
7
+ @project_api = project_api
8
+ @jwt = jwt
9
+ @idea_params = idea_params
10
+ end
11
+
12
+ def create
13
+ default_idea_params = {
14
+ content: 'the-content',
15
+ impact: 7,
16
+ ease: 8,
17
+ confidence: 9
18
+ }
19
+
20
+ options = {
21
+ headers: {
22
+ 'x-access-token' => @jwt
23
+ },
24
+ body: default_idea_params.merge(@idea_params)
25
+ }
26
+
27
+ res = @project_api.request(:post, '/ideas', options)
28
+ JSON.parse(res.body)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ require 'securerandom'
2
+
3
+ module CmQuiz
4
+ module Factory
5
+ class User
6
+ def initialize(project_api:, name: nil, email: nil, password: nil)
7
+ @project_api = project_api
8
+ @name = name || "codementor-test-#{SecureRandom.hex(5)}"
9
+ @email = email || "#{@name}@codementor.io"
10
+ @password = password || "pAssw0rd!"
11
+ end
12
+
13
+ def create
14
+ options = {
15
+ body: {
16
+ email: @email,
17
+ name: @name,
18
+ password: @password
19
+ }
20
+ }
21
+
22
+ res = @project_api.request(:post, '/users', options)
23
+ payload = JSON.parse(res.body)
24
+ [payload['jwt'], payload['refresh_token']]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ require 'httparty'
2
+
3
+ module CmQuiz
4
+ class ProjectAPI
5
+ REQUEST_TIMEOUT = 5
6
+
7
+ class PerformFailed < StandardError
8
+ attr_reader :response
9
+
10
+ def initialize(message, response)
11
+ @response = response
12
+ super(message)
13
+ end
14
+ end
15
+
16
+ def initialize(endpoint)
17
+ @endpoint = endpoint
18
+ end
19
+
20
+ def request(verb, path, options = {})
21
+ url = @endpoint + path
22
+
23
+ query = options[:query]
24
+ body = options[:body].to_json
25
+ headers = { 'Content-Type' => 'application/json' }.merge(options[:headers] || {})
26
+
27
+ http_options = {
28
+ query: query,
29
+ body: body,
30
+ headers: headers,
31
+ timeout: REQUEST_TIMEOUT
32
+ }
33
+ res = HTTParty.send(verb, url, http_options)
34
+
35
+ raise PerformFailed.new("[#{res.code}]: #{res.body}", res) unless res.success?
36
+
37
+ res
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ require 'cm_quiz/review_helper'
2
+
3
+ module CmQuiz
4
+ module Review
5
+ class BaseReview
6
+ include ReviewHelper
7
+
8
+ def perform
9
+ run
10
+ build_test_result(test_request)
11
+ rescue RSpec::Expectations::ExpectationNotMetError => e
12
+ build_test_result(test_request, false, e.message)
13
+ rescue => e
14
+ build_test_result(test_request, false, e.message)
15
+ end
16
+
17
+ def run
18
+ raise "Method `run` should be implemented on class #{self.class}"
19
+ end
20
+
21
+ def test_request
22
+ {
23
+ verb: @verb,
24
+ path: @path,
25
+ options: @options
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ module CmQuiz
2
+ module Review
3
+ class CreateIdea < BaseReview
4
+ def initialize(project_api:)
5
+ @project_api = project_api
6
+ @verb = :post
7
+ @path = '/ideas'
8
+ end
9
+
10
+ def run
11
+ jwt, _ = Factory::User.new({
12
+ project_api: @project_api
13
+ }).create
14
+
15
+ res = send_create_idea_request({
16
+ jwt: jwt,
17
+ content: 'test-content',
18
+ impact: 7,
19
+ ease: 8,
20
+ confidence: 9
21
+ })
22
+ payload = JSON.parse(res.body)
23
+
24
+ expect(payload['impact']).to eq(7), "expect impact equal 7, but got #{payload['impact']}"
25
+ expect(payload['ease']).to eq(8), "expect ease equal 8, but got #{payload['ease']}"
26
+ expect(payload['confidence']).to eq(9), "expect confidence equal 9, but got #{payload['confidence']}"
27
+ expect(payload['average_score']).to eq(8.0), "expect average_score equal 8, but got #{payload['average_score']}"
28
+ end
29
+
30
+ private
31
+
32
+ def send_create_idea_request(jwt:, content:, impact:, ease:, confidence:)
33
+ options = {
34
+ headers: {
35
+ 'x-access-token' => jwt
36
+ },
37
+ body: {
38
+ content: content,
39
+ impact: impact,
40
+ ease: ease,
41
+ confidence: confidence
42
+ }
43
+ }
44
+
45
+ @project_api.request(@verb, @path, options)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ module CmQuiz
2
+ module Review
3
+ class DeleteIdea < BaseReview
4
+ def initialize(project_api:)
5
+ @project_api = project_api
6
+ @verb = :delete
7
+ @path = '/ideas/:idea_id'
8
+ end
9
+
10
+ def run
11
+ jwt, _ = Factory::User.new({
12
+ project_api: @project_api
13
+ }).create
14
+ idea_payload = Factory::Idea.new({
15
+ project_api: @project_api,
16
+ jwt: jwt
17
+ }).create
18
+ idea_id = idea_payload['id']
19
+
20
+ send_delete_idea_request(jwt: jwt, idea_id: idea_id)
21
+
22
+ res = send_get_ideas_request(jwt: jwt)
23
+ res_hash = JSON.parse(res.body)
24
+ expect(res_hash.size).to eq(0)
25
+ end
26
+
27
+ private
28
+
29
+ def send_delete_idea_request(jwt:, idea_id:)
30
+ options = {
31
+ headers: {
32
+ 'x-access-token' => jwt
33
+ }
34
+ }
35
+
36
+ @project_api.request(:delete, "/ideas/#{idea_id}", options)
37
+ end
38
+
39
+ def send_get_ideas_request(jwt:)
40
+ options = {
41
+ headers: {
42
+ 'x-access-token' => jwt
43
+ }
44
+ }
45
+
46
+ @project_api.request(:get, "/ideas", options)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,73 @@
1
+ require 'date'
2
+
3
+ module CmQuiz
4
+ module Review
5
+ class GetIdeas < BaseReview
6
+ VALID_TIME_DIFF = 60 * 5
7
+
8
+ def initialize(project_api:)
9
+ @project_api = project_api
10
+ @verb = :get
11
+ @path = '/ideas'
12
+ @now = Time.now
13
+ end
14
+
15
+ def run
16
+ jwt, _ = Factory::User.new({
17
+ project_api: @project_api
18
+ }).create
19
+ idea_payloads = 3.times.map do |i|
20
+ Factory::Idea.new({
21
+ project_api: @project_api,
22
+ jwt: jwt,
23
+ idea_params: {
24
+ confidence: (3 + i) % 10 + 1
25
+ }
26
+ }).create
27
+ end
28
+
29
+ res = send_get_ideas_request(jwt: jwt)
30
+ res_hash = JSON.parse(res.body)
31
+
32
+ idea_payloads.each do |idea_payload|
33
+ item = res_hash.find { |item| item['id'] == idea_payload['id'] }
34
+ raise StandardError, "idea not found" unless item
35
+
36
+ expect(item['content']).to eq(idea_payload['content'])
37
+ expect(item['impact']).to eq(idea_payload['impact'])
38
+ expect(item['ease']).to eq(idea_payload['ease'])
39
+ expect(item['confidence']).to eq(idea_payload['confidence'])
40
+ average_score = (idea_payload['impact'] + idea_payload['ease'] + idea_payload['confidence'])/ 3.0
41
+ expect(item['average_score']).to be_within(0.1).of(average_score)
42
+ diff = Time.now - Time.new(item['created_at'])
43
+ expect(diff).to be <= VALID_TIME_DIFF
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def send_delete_idea_request(jwt:, idea_id:)
50
+ options = {
51
+ headers: {
52
+ 'x-access-token' => jwt
53
+ }
54
+ }
55
+
56
+ @project_api.request(:delete, "/ideas/#{idea_id}", options)
57
+ end
58
+
59
+ def send_get_ideas_request(jwt:, page: 1)
60
+ options = {
61
+ headers: {
62
+ 'x-access-token' => jwt
63
+ },
64
+ query: {
65
+ page: page
66
+ }
67
+ }
68
+
69
+ @project_api.request(@verb, @path, options)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,43 @@
1
+ require 'securerandom'
2
+
3
+ module CmQuiz
4
+ module Review
5
+ class GetUserInfo < BaseReview
6
+ def initialize(project_api:)
7
+ @project_api = project_api
8
+ @verb = :get
9
+ @path = '/me'
10
+ end
11
+
12
+ def run
13
+ name = "codementor-test-#{SecureRandom.hex(5)}"
14
+ email = "#{name}@codementor.io"
15
+ password = "pAssw0rd!"
16
+ jwt, _refresh_token = Factory::User.new({
17
+ project_api: @project_api,
18
+ name: name,
19
+ email: email,
20
+ password: password
21
+ }).create
22
+
23
+ res = send_get_user_info_request(jwt: jwt)
24
+ payload = JSON.parse(res.body)
25
+
26
+ expect(payload['email']).to eq(email)
27
+ expect(payload['name']).to eq(name)
28
+ end
29
+
30
+ private
31
+
32
+ def send_get_user_info_request(jwt:)
33
+ options = {
34
+ headers: {
35
+ 'x-access-token' => jwt
36
+ }
37
+ }
38
+
39
+ @project_api.request(@verb, @path, options)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,47 @@
1
+ require 'securerandom'
2
+
3
+ module CmQuiz
4
+ module Review
5
+ class LoginUser < BaseReview
6
+ def initialize(project_api:)
7
+ @project_api = project_api
8
+ @verb = :post
9
+ @path = '/access-tokens'
10
+ end
11
+
12
+ def run
13
+ name = "codementor-test-#{SecureRandom.hex(5)}"
14
+ email = "#{name}@codementor.io"
15
+ password = "pAssw0rd!"
16
+ Factory::User.new({
17
+ project_api: @project_api,
18
+ name: name,
19
+ email: email,
20
+ password: password
21
+ }).create
22
+
23
+ @options = build_options(email: email, password: password)
24
+ res = send_request(@options)
25
+ payload = JSON.parse(res.body)
26
+
27
+ expect(payload['jwt'].class).to eq(String), '`jwt` should be string'
28
+ expect(payload['refresh_token'].class).to eq(String), '`refresh_token` should be string'
29
+ end
30
+
31
+ private
32
+
33
+ def build_options(email:, password:)
34
+ options = {
35
+ body: {
36
+ email: email,
37
+ password: password
38
+ }
39
+ }
40
+ end
41
+
42
+ def send_request(options)
43
+ @project_api.request(@verb, @path, options)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,43 @@
1
+ require 'securerandom'
2
+
3
+ module CmQuiz
4
+ module Review
5
+ class SignUpUser < BaseReview
6
+ def initialize(project_api:)
7
+ @project_api = project_api
8
+ @verb = :post
9
+ @path = '/users'
10
+ end
11
+
12
+ def run
13
+ name = "codementor-test-#{SecureRandom.hex(5)}"
14
+ email = "#{name}@codementor.io"
15
+ password = "pAssw0rd!"
16
+ res = send_sign_up_user_request(email: email, name: name, password: password)
17
+ payload = JSON.parse(res.body)
18
+
19
+ expect(payload['jwt'].class).to eq(String), '`jwt` should be string'
20
+ expect(payload['refresh_token'].class).to eq(String), '`refresh_token` should be string'
21
+ build_test_result(self.class)
22
+ rescue RSpec::Expectations::ExpectationNotMetError => e
23
+ build_test_result(self.class, false, e.message)
24
+ rescue => e
25
+ build_test_result(self.class, false, e.message)
26
+ end
27
+
28
+ private
29
+
30
+ def send_sign_up_user_request(email:, name:, password:)
31
+ options = {
32
+ body: {
33
+ email: email,
34
+ name: name,
35
+ password: password
36
+ }
37
+ }
38
+
39
+ @project_api.request(@verb, @path, options)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ module CmQuiz
2
+ module Review
3
+ class UpdateIdea < BaseReview
4
+ def initialize(project_api:)
5
+ @project_api = project_api
6
+ @verb = :put
7
+ @path = '/ideas/:idea_id'
8
+ end
9
+
10
+ def run
11
+ jwt, _ = Factory::User.new({
12
+ project_api: @project_api
13
+ }).create
14
+ idea_payload = Factory::Idea.new({
15
+ project_api: @project_api,
16
+ jwt: jwt
17
+ }).create
18
+ idea_id = idea_payload['id']
19
+
20
+ res = send_update_idea_request({
21
+ jwt: jwt,
22
+ idea_id: idea_id,
23
+ content: 'test-new-content',
24
+ impact: 6,
25
+ ease: 7,
26
+ confidence: 8
27
+ })
28
+
29
+ payload = JSON.parse(res.body)
30
+ expect(payload['content']).to eq('test-new-content')
31
+ expect(payload['impact']).to eq(6)
32
+ expect(payload['ease']).to eq(7)
33
+ expect(payload['confidence']).to eq(8)
34
+ expect(payload['average_score']).to eq(7.0)
35
+ end
36
+
37
+ private
38
+
39
+ def send_delete_idea_request(jwt:, idea_id:)
40
+ options = {
41
+ headers: {
42
+ 'x-access-token' => jwt
43
+ }
44
+ }
45
+
46
+ @project_api.request(:delete, "/ideas/#{idea_id}", options)
47
+ end
48
+
49
+ def send_update_idea_request(jwt:, idea_id:, content: nil, impact: nil,
50
+ ease: nil, confidence: nil)
51
+
52
+ options = {
53
+ headers: {
54
+ 'x-access-token' => jwt
55
+ },
56
+ body: {
57
+ content: content,
58
+ impact: impact,
59
+ ease: ease,
60
+ confidence: confidence
61
+ }
62
+ }
63
+
64
+ @project_api.request(:put, "/ideas/#{idea_id}", options)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ require 'rspec'
2
+
3
+ module CmQuiz
4
+ module ReviewHelper
5
+ def expect(target)
6
+ RSpec::Expectations::ExpectationTarget.new(target)
7
+ end
8
+
9
+ def eq(obj)
10
+ RSpec::Matchers::BuiltIn::Eq.new(obj)
11
+ end
12
+
13
+ def be
14
+ RSpec::Matchers::BuiltIn::Be.new
15
+ end
16
+
17
+ def be_within(delta)
18
+ RSpec::Matchers::BuiltIn::BeWithin.new(delta)
19
+ end
20
+
21
+ def build_test_result(test_case, passed = true, message = nil)
22
+ [test_case, passed, message]
23
+ end
24
+ end
25
+ end