lexile 0.0.2
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 +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +14 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +93 -0
- data/Rakefile +30 -0
- data/lexile.gemspec +25 -0
- data/lib/lexile/api/books.rb +26 -0
- data/lib/lexile/api/client.rb +105 -0
- data/lib/lexile/api/endpoints.rb +20 -0
- data/lib/lexile/api/resource.rb +27 -0
- data/lib/lexile/book.rb +41 -0
- data/lib/lexile/configuration.rb +73 -0
- data/lib/lexile/errors.rb +27 -0
- data/lib/lexile/model.rb +103 -0
- data/lib/lexile/version.rb +3 -0
- data/lib/lexile.rb +22 -0
- data/spec/lexile/api/books_spec.rb +113 -0
- data/spec/lexile/api/client_spec.rb +97 -0
- data/spec/lexile/configuration_spec.rb +51 -0
- data/spec/lexile/errors_spec.rb +18 -0
- data/spec/lexile/model_spec.rb +41 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/lexile_helper.rb +29 -0
- data/spec/vcr_tapes/books.yml +342 -0
- data/spec/vcr_tapes/errors.yml +410 -0
- metadata +107 -0
data/lib/lexile.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'hashie/mash'
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
require 'lexile/configuration'
|
6
|
+
require 'lexile/version'
|
7
|
+
require 'lexile/api/client'
|
8
|
+
require 'lexile/errors'
|
9
|
+
|
10
|
+
# Data Models
|
11
|
+
require 'lexile/model'
|
12
|
+
require 'lexile/book'
|
13
|
+
|
14
|
+
#API Operations
|
15
|
+
require 'lexile/api/resource'
|
16
|
+
require 'lexile/api/books'
|
17
|
+
require 'lexile/api/endpoints'
|
18
|
+
|
19
|
+
module Lexile
|
20
|
+
extend Configuration
|
21
|
+
extend Api::Endpoints
|
22
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lexile::Api::Books, :vcr => { :cassette_name => "books" } do
|
4
|
+
|
5
|
+
before { set_testing_configuration }
|
6
|
+
|
7
|
+
|
8
|
+
context '#show' do
|
9
|
+
let(:book){ Lexile.books.show(lexile_book_id) }
|
10
|
+
|
11
|
+
it "should return result" do
|
12
|
+
expect(book).to_not be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should be book' do
|
16
|
+
expect(book).to be_an_instance_of( Lexile::Book )
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have id key' do
|
20
|
+
expect(book).to respond_to(:id)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have lexile key' do
|
24
|
+
expect(book).to respond_to(:lexile)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should have lexile_display key' do
|
28
|
+
expect(book).to respond_to(:lexile_display)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should have pages key' do
|
32
|
+
expect(book).to respond_to(:pages)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context '#find_by_isbn13' do
|
37
|
+
let(:books){ Lexile.books.find_by_isbn13(lexile_book_isbn13) }
|
38
|
+
|
39
|
+
it "should return not empty array" do
|
40
|
+
expect(books).to_not be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should be array' do
|
44
|
+
expect(books).to be_an_instance_of( Array )
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'length should be > 0' do
|
48
|
+
expect(books.length).to_not be_zero
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should be array of Lexile::Book' do
|
52
|
+
books.each do |book|
|
53
|
+
expect(book).to be_an_instance_of( Lexile::Book )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should have id key' do
|
58
|
+
expect(books[0]).to respond_to(:id)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should have lexile key' do
|
62
|
+
expect(books[0]).to respond_to(:lexile)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should have lexile_display key' do
|
66
|
+
expect(books[0]).to respond_to(:lexile_display)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should have pages key' do
|
70
|
+
expect(books[0]).to respond_to(:pages)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context '#find_by_title' do
|
75
|
+
let(:books){ Lexile.books.find_by_title(lexile_book_title) }
|
76
|
+
|
77
|
+
it "should return not empty array" do
|
78
|
+
expect(books).to_not be_nil
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should be array' do
|
82
|
+
expect(books).to be_an_instance_of( Array )
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'length should be > 0' do
|
86
|
+
expect(books.length).to_not be_zero
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should be array of Lexile::Book' do
|
90
|
+
books.each do |book|
|
91
|
+
expect(book).to be_an_instance_of( Lexile::Book )
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should have id key' do
|
96
|
+
expect(books[0]).to respond_to(:id)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should have lexile key' do
|
100
|
+
expect(books[0]).to respond_to(:lexile)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should have lexile_display key' do
|
104
|
+
expect(books[0]).to respond_to(:lexile_display)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should have pages key' do
|
108
|
+
expect(books[0]).to respond_to(:pages)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lexile::API::Client do
|
4
|
+
|
5
|
+
let(:client){
|
6
|
+
set_testing_configuration
|
7
|
+
Lexile::API::Client.new( Lexile )
|
8
|
+
}
|
9
|
+
|
10
|
+
it "should have a VERSION" do
|
11
|
+
Lexile::VERSION.should_not be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'initialization' do
|
15
|
+
describe 'via configure' do
|
16
|
+
context "should be initialized by config" do
|
17
|
+
before do
|
18
|
+
set_testing_configuration
|
19
|
+
@cli = Lexile.configure do |c |
|
20
|
+
c.username = lexile_username
|
21
|
+
c.password = lexile_password
|
22
|
+
c.testing = true
|
23
|
+
end
|
24
|
+
@options_hash = @cli.class.default_options
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(@cli).to_not be_nil }
|
28
|
+
it { expect(@options_hash[:base_uri]).to eq Lexile.api_url }
|
29
|
+
it { expect(@options_hash[:default_params]).to be_nil }
|
30
|
+
it { expect(@options_hash[:debug_output]).to_not be_nil }
|
31
|
+
it { expect(@options_hash[:headers]).to_not be_nil }
|
32
|
+
it { expect(@options_hash[:headers]['User-Agent']).to_not be_nil }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'should be initialized via hash' do
|
37
|
+
before do
|
38
|
+
configuration_hash = {
|
39
|
+
endpoint: 'https://example.com',
|
40
|
+
api_version: 'v52',
|
41
|
+
username: 'my_lexile_username',
|
42
|
+
password: 'my_lexile_password',
|
43
|
+
testing: true
|
44
|
+
}
|
45
|
+
@options_hash = client.class.default_options
|
46
|
+
@client = Lexile::API::Client.new( configuration_hash )
|
47
|
+
end
|
48
|
+
|
49
|
+
it{ expect(@client).to_not be_nil }
|
50
|
+
it{ expect(@options_hash[:base_uri]).to eq 'https://example.com/v52' }
|
51
|
+
it{ expect(@options_hash[:default_params]).to be_nil }
|
52
|
+
it{ expect(@options_hash[:debug_output]).to_not be_nil }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "get" do
|
57
|
+
it "should not raise an exception with response status 200" do
|
58
|
+
VCR.use_cassette("errors") do
|
59
|
+
expect{ client.get("/book") }.not_to raise_error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
it "should raise Lexile::AuthenticationFailed with response status is 401" do
|
65
|
+
VCR.use_cassette("errors") do
|
66
|
+
expect{ client.get("/401") }.to raise_error Lexile::AuthenticationFailed
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
it "should raise Lexile::NotFound with response status is 404" do
|
72
|
+
VCR.use_cassette("errors") do
|
73
|
+
expect{ client.get("/404") }.to raise_error Lexile::NotFound
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
[
|
80
|
+
{status: 400, ex: Lexile::BadRequest },
|
81
|
+
{status: 401, ex: Lexile::AuthenticationFailed},
|
82
|
+
{status: 404, ex: Lexile::NotFound},
|
83
|
+
{status: 500, ex: Lexile::ServerError},
|
84
|
+
{status: 502, ex: Lexile::Unavailable},
|
85
|
+
{status: 503, ex: Lexile::RateLimited},
|
86
|
+
{status: 504, ex: Lexile::RateLimited},
|
87
|
+
{status: 999, ex: Lexile::UnknownStatusCode}
|
88
|
+
].each do |test_args|
|
89
|
+
it "should raise #{test_args[:ex].name} when status code is #{test_args[:status]}" do
|
90
|
+
client.class.stub(:get){ mock = double; mock.stub(:code){test_args[:status]}; mock }
|
91
|
+
expect{
|
92
|
+
client.get("/something")
|
93
|
+
}.to raise_error test_args[:ex]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lexile::Configuration do
|
4
|
+
|
5
|
+
before do
|
6
|
+
set_testing_configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.configure' do
|
10
|
+
Lexile::Configuration::VALID_CONFIG_KEYS.each do |key|
|
11
|
+
it "should set the #{key}" do
|
12
|
+
Lexile.configure do |config|
|
13
|
+
if key == :timeout
|
14
|
+
config.send("#{key}=", 10)
|
15
|
+
expect(Lexile.send(key)).to eq 10
|
16
|
+
else
|
17
|
+
config.send("#{key}=", key)
|
18
|
+
expect(Lexile.send(key)).to eq key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
it "should configure the client with this configuration" do
|
24
|
+
client = Lexile.configure do |config|
|
25
|
+
config.api_version = "V74_5_5"
|
26
|
+
end
|
27
|
+
client.should_not be_nil
|
28
|
+
client.class.default_options[:base_uri].should match /V74_5_5/
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return a cliend configured with this configuration" do
|
32
|
+
client = Lexile.configure do |config|
|
33
|
+
config.api_version = "V74_5_5"
|
34
|
+
end
|
35
|
+
client = Lexile.send(:client)
|
36
|
+
client.should_not be_nil
|
37
|
+
client.class.default_options[:base_uri].should match /V74_5_5/
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "default values" do
|
42
|
+
before{ Lexile.reset! }
|
43
|
+
Lexile::Configuration::VALID_CONFIG_KEYS.each do |key|
|
44
|
+
describe ".#{key}" do
|
45
|
+
it 'should return the default value' do
|
46
|
+
expect(Lexile.send(key)).to eq Lexile::Configuration.const_get("DEFAULT_#{key.upcase}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lexile::HTTPError do
|
4
|
+
let(:response){
|
5
|
+
mock_response = double()
|
6
|
+
mock_response.stub(:code){ 259 }
|
7
|
+
mock_response.stub(:body){"<html><head></head><body>Hello World!</body></html>"}
|
8
|
+
mock_response
|
9
|
+
}
|
10
|
+
|
11
|
+
subject{ Lexile::HTTPError.new( response )}
|
12
|
+
|
13
|
+
it "should format correctly as a string" do
|
14
|
+
subject.to_s.should match /Lexile::HTTPError/
|
15
|
+
subject.to_s.should match /259/
|
16
|
+
subject.to_s.should match /Hello World/
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lexile::Model do
|
4
|
+
|
5
|
+
|
6
|
+
describe "#parse" do
|
7
|
+
# We will use a Lexile::Book which is a model to test model properties
|
8
|
+
let(:single_object_response){ { 'a' => 'ONE', 'b' => 'TWO', 'c' => 'THREE'} }
|
9
|
+
let(:multi_object_response){{ 'objects' =>[{ 'a' => 'ONE', 'b' => 'TWO', 'c' => 'THREE'},{ 'a' => 'UNO', 'b' => 'DOS', 'c' => 'TRES'},{ 'a' => 'UNE', 'b' => 'DEUX', 'c' => 'TROIS'}] }}
|
10
|
+
let(:invalid_json){ "{\"objects\":\"Most Definetly not an array of objects\"}" }
|
11
|
+
|
12
|
+
it "should raise an exception if a mult-object response does not contain an array" do
|
13
|
+
expect{
|
14
|
+
Lexile::Book.parse( invalid_json )
|
15
|
+
}.to raise_error Lexile::CannotProcessResponse, /is present in response but it does not contain an Array/
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse a single object response" do
|
19
|
+
soj = Lexile::Book.parse( single_object_response.to_json )
|
20
|
+
single_object_response.each do |key|
|
21
|
+
soj[key].should eq single_object_response[key]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should parse a multi object response" do
|
26
|
+
books = Lexile::Book.parse( multi_object_response.to_json )
|
27
|
+
objs = multi_object_response['objects']
|
28
|
+
books.length.should eq objs.length
|
29
|
+
#deep compare of books
|
30
|
+
objs.each do |obj|
|
31
|
+
index = books.find_index{|book| book['a']== obj['a']}
|
32
|
+
index.should_not be_nil
|
33
|
+
book = books[index]
|
34
|
+
obj.each do |key|
|
35
|
+
book[key].should eq obj[key]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require "codeclimate-test-reporter"
|
5
|
+
CodeClimate::TestReporter.start
|
6
|
+
|
7
|
+
require 'rspec'
|
8
|
+
require 'vcr'
|
9
|
+
require 'webmock/rspec'
|
10
|
+
require 'hashie'
|
11
|
+
require 'lexile'
|
12
|
+
|
13
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
14
|
+
|
15
|
+
WebMock.disable_net_connect!
|
16
|
+
|
17
|
+
VCR.configure do |c|
|
18
|
+
c.cassette_library_dir = 'spec/vcr_tapes'
|
19
|
+
c.hook_into :webmock
|
20
|
+
c.configure_rspec_metadata!
|
21
|
+
c.default_cassette_options = {
|
22
|
+
#record: (ENV['TRAVIS'] ? :none : :once)
|
23
|
+
#record: :new_episodes
|
24
|
+
#record: :all
|
25
|
+
record: :none
|
26
|
+
}
|
27
|
+
|
28
|
+
c.ignore_hosts 'codeclimate.com'
|
29
|
+
c.filter_sensitive_data("<USERNAME>") { Lexile.options[:username] }
|
30
|
+
c.filter_sensitive_data("<PASSWORD>") { Lexile.options[:password] }
|
31
|
+
end
|
32
|
+
|
33
|
+
RSpec.configure do |config|
|
34
|
+
config.include LexileHelper
|
35
|
+
config.color = true
|
36
|
+
config.tty = true
|
37
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
38
|
+
config.order = "random"
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module LexileHelper
|
2
|
+
def set_testing_configuration
|
3
|
+
Lexile.reset!
|
4
|
+
Lexile.username = lexile_username
|
5
|
+
Lexile.password = lexile_password
|
6
|
+
Lexile.testing = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def lexile_username
|
10
|
+
'AUSERNAME'
|
11
|
+
end
|
12
|
+
|
13
|
+
def lexile_password
|
14
|
+
'APASSWORD'
|
15
|
+
end
|
16
|
+
|
17
|
+
def lexile_book_id
|
18
|
+
315833 #ISBN 9780062012722 Title: It Happened to Nancy: By An Anonymous Teenager: A True Story from Her Diary
|
19
|
+
end
|
20
|
+
|
21
|
+
def lexile_book_isbn13
|
22
|
+
9780062012722 #id: 315833 Title: It Happened to Nancy: By An Anonymous Teenager: A True Story from Her Diary
|
23
|
+
end
|
24
|
+
|
25
|
+
def lexile_book_title
|
26
|
+
"Malala"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|