diff --git a/README.md b/README.md index 5db0c21..717a400 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,45 @@ TextRazor.phrases('api_key', 'text') ``` +### Dictionaries + +You can manage dictionaries and their entries through the dictionary API. + +#### Creating a dictionary + +``` +client = TextRazor::Client.new('api_key') + +client.create_dictionary('my-dictionary', case_insensitive: true) +``` + +#### Adding entries to a dictionary + +``` +client.create_dictionary_entries('my-dictionary', [{id: 'my-entry', text: 'Text to be matched'}]) +``` + +#### Getting entries from a dictionary + +``` +client.get_dictionary_entries('my-dictionary') + +# Using pagination +client.get_dictionary_entries('my-dictionary', limit: 20, offset: 0) +``` + +#### Deleting a dictionary entry + +``` +client.delete_dictionary_entry('my-dictionary', 'my-entry') +``` + +#### Deleting a dctionary + +``` +client.delete_dictionary('my-dictionary') +``` + ## Next steps Only implemented this for topics, entities, words and phrases. Also, implement diff --git a/lib/textrazor.rb b/lib/textrazor.rb index b7202c8..3ce6246 100644 --- a/lib/textrazor.rb +++ b/lib/textrazor.rb @@ -1,8 +1,11 @@ require "textrazor/version" require "textrazor/configuration" require "textrazor/util" +require "textrazor/dictionary" +require "textrazor/dictionary_entry" require "textrazor/client" require "textrazor/request" +require "textrazor/api_response" require "textrazor/response" require "textrazor/category" require "textrazor/topic" diff --git a/lib/textrazor/api_response.rb b/lib/textrazor/api_response.rb new file mode 100644 index 0000000..5000af6 --- /dev/null +++ b/lib/textrazor/api_response.rb @@ -0,0 +1,54 @@ +require 'json' + +module TextRazor + + class ApiResponse + + BadRequest = Class.new(StandardError) + Unauthorised = Class.new(StandardError) + RequestEntityTooLong = Class.new(StandardError) + + attr_reader :raw_response, :time + + def initialize(http_response) + code = http_response.code + body = http_response.body + + raise BadRequest.new(body) if bad_request?(code) + raise Unauthorised.new(body) if unauthorised?(code) + raise RequestEntityTooLong.new(body) if request_entity_too_long?(code) + + json_body = ::JSON::parse(body, symbolize_names: true) + + @time = json_body[:time].to_f + @ok = json_body[:ok] + @raw_response = json_body[:response] + end + + def ok? + @ok + end + + #TODO: Not in a successful response + #def error + #end + + #def message + #end + + private + + def bad_request?(code) + code == 400 + end + + def unauthorised?(code) + code == 401 + end + + def request_entity_too_long?(code) + code == 413 + end + end + +end diff --git a/lib/textrazor/client.rb b/lib/textrazor/client.rb index c35878f..9f45e73 100644 --- a/lib/textrazor/client.rb +++ b/lib/textrazor/client.rb @@ -8,6 +8,9 @@ class Client UnsupportedExtractor = Class.new(StandardError) UnsupportedCleanupMode = Class.new(StandardError) + InvalidDictionary = Class.new(StandardError) + InvalidDictionaryEntry = Class.new(StandardError) + DEFAULT_EXTRACTORS = ['entities', 'topics', 'words', 'phrases', 'dependency-trees', 'relations', 'entailments', 'senses'] @@ -30,11 +33,36 @@ def initialize(api_key, options = {}) def analyse(text) assert_text(text) - options = { - api_key: api_key - }.merge(request_options) + Response.new(Request.post(api_key, text, **request_options)) + end + + def create_dictionary(id, **options) + dictionary = Dictionary.new(id: id, **options) + assert_dictionary(dictionary) + Request.create_dictionary(api_key, dictionary) + end - Response.new(Request.post(text, options)) + def get_dictionary_entries(dictionary_id, limit: 0, offset: 0) + response = ApiResponse.new( + Request.get_dictionary_entries(api_key, dictionary_id, limit: limit, offset: offset) + ) + return [] unless response.raw_response.key?(:entries) + response.raw_response[:entries].map { |hash| DictionaryEntry.create_from_hash(hash) } + end + + def delete_dictionary(dictionary_id) + Request.delete_dictionary(api_key, dictionary_id) + end + + def create_dictionary_entries(dictionary_id, dictionary_entry_hashes) + dictionary_entries = dictionary_entry_hashes.map do |entry_hash| + DictionaryEntry.new(entry_hash).tap { |e| assert_dictionary_entry(e) } + end + Request.create_dictionary_entries(api_key, dictionary_id, dictionary_entries) + end + + def delete_dictionary_entry(dictionary_id, dictionary_entry_id) + Request.delete_dictionary_entry(api_key, dictionary_id, dictionary_entry_id) end def self.topics(api_key, text, options = {}) @@ -126,6 +154,14 @@ def is_text_bigger_than_200_kb?(text) text.bytesize/1024.0 > 200 end + def assert_dictionary(dictionary) + raise InvalidDictionary, "Dictionary is invalid" unless dictionary.valid? + end + + def assert_dictionary_entry(entry) + raise InvalidDictionaryEntry, "Entry is invalid" unless entry.valid? + end + end end diff --git a/lib/textrazor/dictionary.rb b/lib/textrazor/dictionary.rb new file mode 100644 index 0000000..9a2161a --- /dev/null +++ b/lib/textrazor/dictionary.rb @@ -0,0 +1,27 @@ +module TextRazor + + class Dictionary + + include Util + + attr_reader :id, :match_type, :case_insensitive, :language + + def initialize(params = {}) + initialize_params params + end + + def to_h + { + "matchType" => match_type, + "caseInsensitive" => case_insensitive, + "language" => language + }.reject { |_, v| v.nil? } + end + + def valid? + !id.nil? && !id.empty? + end + + end + +end diff --git a/lib/textrazor/dictionary_entry.rb b/lib/textrazor/dictionary_entry.rb new file mode 100644 index 0000000..5a25bfb --- /dev/null +++ b/lib/textrazor/dictionary_entry.rb @@ -0,0 +1,27 @@ +module TextRazor + + class DictionaryEntry + + include Util + + attr_reader :id, :text, :data + + def initialize(params = {}) + initialize_params params + end + + def to_h + { + "id" => id, + "text" => text, + "data" => data + }.reject { |_, v| v.nil? || v.empty? } + end + + def valid? + !text.nil? && !text.empty? + end + + end +end + diff --git a/lib/textrazor/entity.rb b/lib/textrazor/entity.rb index fb8e7d2..06454b7 100644 --- a/lib/textrazor/entity.rb +++ b/lib/textrazor/entity.rb @@ -6,7 +6,7 @@ class Entity attr_reader :id, :type, :matching_tokens, :entity_id, :freebase_types, :confidence_score, :wiki_link, :matched_text, :freebase_id, :relevance_score, :entity_english_id, - :starting_pos, :ending_pos, :data, :wikidata_id + :starting_pos, :ending_pos, :data, :wikidata_id, :source_id def initialize(params = {}) @type = [] diff --git a/lib/textrazor/request.rb b/lib/textrazor/request.rb index f069e19..f0aeeff 100644 --- a/lib/textrazor/request.rb +++ b/lib/textrazor/request.rb @@ -18,18 +18,63 @@ class Request classifiers: 'classifiers' } - def self.post(text, options) + def self.post(api_key, text, **options) ::RestClient.post( TextRazor.configuration.url, build_query(text, options), - accept_encoding: 'gzip' + build_headers(api_key) ) end + def self.create_dictionary(api_key, dictionary, **options) + ::RestClient.put( + url("/entities/#{dictionary.id}"), + dictionary.to_h.to_json, + build_headers(api_key) + ) + dictionary + end + + def self.get_dictionary_entries(api_key, dictionary_id, limit:, offset:) + ::RestClient.get( + url("entities/#{dictionary_id}/_all?limit=#{limit}&offset=#{offset}"), + build_headers(api_key) + ) + end + + def self.delete_dictionary(api_key, dictionary_id) + ::RestClient.delete( + url("entities/#{dictionary_id}"), + build_headers(api_key) + ) + true + end + + def self.create_dictionary_entries(api_key, dictionary_id, dictionary_entries) + ::RestClient.post( + url("entities/#{dictionary_id}/"), + dictionary_entries.map(&:to_h).to_json, + build_headers(api_key) + ) + dictionary_entries + end + + def self.delete_dictionary_entry(api_key, dictionary_id, dictionary_entry_id) + ::RestClient.delete( + url("entities/#{dictionary_id}/#{dictionary_entry_id}"), + build_headers(api_key) + ) + true + end + + def self.url(path = '/') + File.join(TextRazor.configuration.url, path) + end + private def self.build_query(text, options) - query = {"text" => text, "apiKey" => options.delete(:api_key)} + query = { 'text' => text } options.each do |key, value| value = value.join(",") if value.is_a?(Array) @@ -39,6 +84,10 @@ def self.build_query(text, options) query end + def self.build_headers(api_key) + { x_textrazor_key: api_key } + end + end end diff --git a/lib/textrazor/response.rb b/lib/textrazor/response.rb index f7d8fd7..21d504e 100644 --- a/lib/textrazor/response.rb +++ b/lib/textrazor/response.rb @@ -2,39 +2,7 @@ module TextRazor - class Response - - BadRequest = Class.new(StandardError) - Unauthorised = Class.new(StandardError) - RequestEntityTooLong = Class.new(StandardError) - - attr_reader :raw_response, :time - - def initialize(http_response) - code = http_response.code - body = http_response.body - - raise BadRequest.new(body) if bad_request?(code) - raise Unauthorised.new(body) if unauthorised?(code) - raise RequestEntityTooLong.new(body) if request_entity_too_long?(code) - - json_body = ::JSON::parse(body, symbolize_names: true) - - @time = json_body[:time].to_f - @ok = json_body[:ok] - @raw_response = json_body[:response] - end - - def ok? - @ok - end - - #TODO: Not in a successful response - #def error - #end - - #def message - #end + class Response < ApiResponse def custom_annotation_output @custom_annotation_output ||= raw_response[:customAnnotationOutput] @@ -98,18 +66,6 @@ def language_is_reliable? private - def bad_request?(code) - code == 400 - end - - def unauthorised?(code) - code == 401 - end - - def request_entity_too_long?(code) - code == 413 - end - def parse_entailments parse(:entailment, raw_response[:entailments]) end diff --git a/spec/lib/textrazor/api_response_spec.rb b/spec/lib/textrazor/api_response_spec.rb new file mode 100644 index 0000000..5774f47 --- /dev/null +++ b/spec/lib/textrazor/api_response_spec.rb @@ -0,0 +1,110 @@ +require 'spec_helper' + +module TextRazor + + describe ApiResponse do + + let(:http_response) do + ::OpenStruct.new(code: 200, body: body) + end + + let(:response) do + Response.new(http_response) + end + + describe "#initialize" do + + context "when HTTP response code is 200" do + + it "should create an instance of Response" do + body = "{\"response\":\"{}\"}" + http_response = ::OpenStruct.new code: 200, body: body + + expect(JSON).to receive(:parse). + with(body, {symbolize_names: true}). + and_return({"response" => "{}"}) + + Response.new(http_response) + end + + end + + context "when HTTP response code is 400" do + + it "should raise an exception" do + http_response = ::OpenStruct.new code: 400 + + expect{ Response.new(http_response) }. + to raise_error(Response::BadRequest) + end + + end + + context "when HTTP response code is 401" do + + it "should raise an exception" do + http_response = ::OpenStruct.new code: 401 + + expect{ Response.new(http_response) }. + to raise_error(Response::Unauthorised) + end + + end + + context "when HTTP response code is 413" do + + it "should raise an exception" do + http_response = ::OpenStruct.new code: 413 + + expect{ Response.new(http_response) }. + to raise_error(Response::RequestEntityTooLong) + end + + end + + end + + describe '#time' do + + it 'returns time taken to process request' do + body = {time: "0.013219"}.to_json + http_response = ::OpenStruct.new code: 200, body: body + response = Response.new(http_response) + + time = response.time + + expect(time).to eq(0.013219) + end + + end + + describe '#ok?' do + + context 'when successfully analysed' do + + it 'returns true' do + body = {ok: true}.to_json + http_response = ::OpenStruct.new code: 200, body: body + response = Response.new(http_response) + + expect(response).to be_ok + end + + end + + context 'when unsuccessfully analysed' do + + it 'returns false' do + body = {ok: false}.to_json + http_response = ::OpenStruct.new code: 200, body: body + response = Response.new(http_response) + + expect(response).to_not be_ok + end + + end + + end + end + +end diff --git a/spec/lib/textrazor/client_spec.rb b/spec/lib/textrazor/client_spec.rb index 51e14d6..519e63d 100644 --- a/spec/lib/textrazor/client_spec.rb +++ b/spec/lib/textrazor/client_spec.rb @@ -124,10 +124,10 @@ module TextRazor request = BasicObject.new expect(Request).to receive(:post). - with('text', {api_key: 'api_key', extractors: %w(entities topics words), cleanup_mode: 'raw', + with(api_key, 'text', extractors: %w(entities topics words), cleanup_mode: 'raw', cleanup_return_cleaned: true, cleanup_return_raw: true, language: 'fre', filter_dbpedia_types: %w(type1), filter_freebase_types: %w(type2), - allow_overlap: false, dictionaries: %w(test), classifiers: 'textrazor_newscodes'}). + allow_overlap: false, dictionaries: %w(test), classifiers: 'textrazor_newscodes'). and_return(request) expect(Response).to receive(:new).with(request) @@ -170,6 +170,64 @@ module TextRazor end + context "#create_dictionary" do + + it "make correct calls" do + expect(Request).to receive(:create_dictionary). + with(api_key, a_kind_of(Dictionary)) + client.create_dictionary("id") + end + + context "with an invalid dictionary" do + + it "raises an exception" do + expect { client.create_dictionary('') }. + to raise_error(Client::InvalidDictionary) + end + end + end + + context "#delete_dictionary" do + it "make correct calls" do + expect(Request).to receive(:delete_dictionary). + with(api_key, "id") + client.delete_dictionary("id") + end + end + + context "#create_dictionary_entries" do + + let(:dictionary_entries_hash) do + [{text: "text"}] + end + + it "make correct calls" do + expect(Request).to receive(:create_dictionary_entries). + with(api_key, "dictionary_id", all(a_kind_of(DictionaryEntry))) + client.create_dictionary_entries("dictionary_id", dictionary_entries_hash) + end + + context "with an invalid dictionary" do + + let(:dictionary_entries_hash) do + [{ text: '' }] + end + + it "raises an exception" do + expect { client.create_dictionary_entries("dictionary_id", dictionary_entries_hash) }. + to raise_error(Client::InvalidDictionaryEntry) + end + end + end + + context "#delete_dictionary_entry" do + it "make correct calls" do + expect(Request).to receive(:delete_dictionary_entry). + with(api_key, "dictionary_id", "dictionary_entry_id") + client.delete_dictionary_entry("dictionary_id", "dictionary_entry_id") + end + end + context ".topics" do it "makes correct calls" do diff --git a/spec/lib/textrazor/dictionary_entry_spec.rb b/spec/lib/textrazor/dictionary_entry_spec.rb new file mode 100644 index 0000000..6caba1a --- /dev/null +++ b/spec/lib/textrazor/dictionary_entry_spec.rb @@ -0,0 +1,71 @@ +require "spec_helper" + +module TextRazor + + describe DictionaryEntry do + + let(:dictionary_entry) do + DictionaryEntry.create_from_hash(dictionary_entry_hash) + end + + let(:dictionary_entry_hash) do + { + "id" => "some-dictionary-entry", + "text" => "some text", + "data" => { "key" => ["value1", "value2"] } + } + end + + context "#create_from_hash" do + + it "should create a new instance" do + expect(dictionary_entry.id).to eq("some-dictionary-entry") + expect(dictionary_entry.text).to eq("some text") + expect(dictionary_entry.data).to eq("key" => ["value1", "value2"]) + end + end + + + context "#to_h" do + + it "should have the right values" do + expect(dictionary_entry.to_h).to eq(dictionary_entry_hash) + end + + context "with default values" do + + let(:dictionary_entry_hash) do + { + "text" => "some text" + } + end + + it "should not add them" do + expect(dictionary_entry.to_h).to eq("text" => "some text") + end + end + end + + context "#valid?" do + + context "when it is valid" do + + it "should return true" do + expect(dictionary_entry.valid?).to be true + end + + end + + context "when it is not valid" do + let(:dictionary_entry_hash) do + {} + end + + it "should return false" do + expect(dictionary_entry.valid?).to be false + end + end + end + + end +end diff --git a/spec/lib/textrazor/dictionary_spec.rb b/spec/lib/textrazor/dictionary_spec.rb new file mode 100644 index 0000000..2265566 --- /dev/null +++ b/spec/lib/textrazor/dictionary_spec.rb @@ -0,0 +1,77 @@ +require "spec_helper" + +module TextRazor + + describe Dictionary do + + let(:dictionary) do + Dictionary.create_from_hash(dictionary_hash) + end + + let(:dictionary_hash) do + { + "id" => "some-dictionary", + "matchType" => "TOKEN", + "caseInsensitive" => true, + "language" => "eng" + } + end + + context "#create_from_hash" do + + it "should create a new instance" do + expect(dictionary.id).to eq("some-dictionary") + expect(dictionary.match_type).to eq("TOKEN") + expect(dictionary.case_insensitive).to be(true) + expect(dictionary.language).to eq("eng") + end + end + + + context "#to_h" do + + it "should have the right values" do + expect(dictionary.to_h).to eq( + "matchType" => "TOKEN", + "caseInsensitive" => true, + "language" => "eng" + ) + end + + context "with default values" do + + let(:dictionary_hash) do + { + "id" => "some-dictionary" + } + end + + it "should not add them" do + expect(dictionary.to_h).to eq({}) + end + end + end + + context "#valid?" do + + context "when it is valid" do + + it "should return true" do + expect(dictionary.valid?).to be true + end + + end + + context "when it is not valid" do + let(:dictionary_hash) do + {} + end + + it "should return false" do + expect(dictionary.valid?).to be false + end + end + end + + end +end diff --git a/spec/lib/textrazor/entity_spec.rb b/spec/lib/textrazor/entity_spec.rb index 8354a9a..8c12b63 100644 --- a/spec/lib/textrazor/entity_spec.rb +++ b/spec/lib/textrazor/entity_spec.rb @@ -29,6 +29,7 @@ module TextRazor "data" => { "type" => ['person', 'company'] }, + "sourceId" => "some-dictionary", "wikidataId" => 'Q7330070' } end @@ -48,6 +49,7 @@ module TextRazor expect(entity.starting_pos).to eq(3) expect(entity.ending_pos).to eq(20) expect(entity.data['type']).to match_array(['person', 'company']) + expect(entity.source_id).to eq("some-dictionary") expect(entity.wikidata_id).to eq('Q7330070') end end diff --git a/spec/lib/textrazor/request_spec.rb b/spec/lib/textrazor/request_spec.rb index 9b2f826..3573490 100644 --- a/spec/lib/textrazor/request_spec.rb +++ b/spec/lib/textrazor/request_spec.rb @@ -4,18 +4,56 @@ module TextRazor describe Request do + let(:api_key) do + "api_key" + end + + describe ".url" do + after :each do + TextRazor.reset + end + + let(:url) do + TextRazor::Request.url + end + + context "with the config 'secure' set to false" do + before :each do + TextRazor.configure do |config| + config.secure = false + end + end + + it "returns the unsecured URL" do + expect(url).to eq 'http://api.textrazor.com/' + end + end + + context "with the config 'secure' set to true" do + before :each do + TextRazor.configure do |config| + config.secure = true + end + end + + it "returns the unsecured URL" do + expect(url).to eq 'https://api.textrazor.com/' + end + end + end + context ".post" do context "default options" do it "should make correct calls" do - options = {api_key: 'api_key', extractors: %w(entities topics words dependency-trees relations entailments)} + options = { extractors: %w(entities topics words dependency-trees relations entailments) } expect(::RestClient).to receive(:post). - with("https://api.textrazor.com", { "text" => 'text', "apiKey" => 'api_key', - "extractors" => "entities,topics,words,dependency-trees,relations,entailments" }, accept_encoding: 'gzip') + with("https://api.textrazor.com", { "text" => 'text', + "extractors" => "entities,topics,words,dependency-trees,relations,entailments" }, x_textrazor_key: 'api_key') - Request.post('text', options) + Request.post(api_key, 'text', **options) end end @@ -23,25 +61,91 @@ module TextRazor context "custom options" do it "should make correct calls" do - options = {api_key: 'api_key', extractors: %w(entities topics words), cleanup_mode: 'raw', + options = { extractors: %w(entities topics words), cleanup_mode: 'raw', cleanup_return_cleaned: true, cleanup_return_raw: true, language: 'fre', filter_dbpedia_types: %w(type1), filter_freebase_types: %w(type2), allow_overlap: false, enrichment_queries: 'queries', classifiers: 'textrazor_iab'} expect(::RestClient).to receive(:post). - with("https://api.textrazor.com", { "text" => 'text', "apiKey" => 'api_key', "extractors" => "entities,topics,words", - "cleanup.mode" => "raw", "cleanup.returnCleaned" => true, "cleanup.returnRaw" => true, "languageOverride" => 'fre', - "entities.filterDbpediaTypes" => "type1", "entities.filterFreebaseTypes" => "type2" , "entities.allowOverlap" => false, - "entities.enrichmentQueries" => "queries", "classifiers" => 'textrazor_iab'}, - accept_encoding: 'gzip') + with("https://api.textrazor.com", { "text" => 'text', "extractors" => "entities,topics,words", + "cleanup.mode" => "raw", "cleanup.returnCleaned" => true, "cleanup.returnRaw" => true, "languageOverride" => 'fre', + "entities.filterDbpediaTypes" => "type1", "entities.filterFreebaseTypes" => "type2" , "entities.allowOverlap" => false, + "entities.enrichmentQueries" => "queries", "classifiers" => 'textrazor_iab'}, + x_textrazor_key: 'api_key') - Request.post('text', options) + Request.post(api_key, 'text', options) end end end + context ".create_dictionary" do + + let(:dictionary) do + Dictionary.new(id: "id", match_type: "token", case_insensitive: true, language: "eng") + end + + it "should make correct calls" do + expect(::RestClient).to receive(:put). + with("https://api.textrazor.com/entities/id", + { "matchType" => "token", "caseInsensitive" => true, "language" => "eng" }.to_json, + x_textrazor_key: 'api_key') + + Request.create_dictionary(api_key, dictionary) + end + end + + context ".get_dictionary_entries" do + + it "should make correct calls" do + expect(::RestClient).to receive(:get). + with("https://api.textrazor.com/entities/id/_all?limit=10&offset=20", + x_textrazor_key: 'api_key') + + Request.get_dictionary_entries(api_key, 'id', limit: 10, offset: 20) + end + end + + context ".delete_dictionary" do + + it "should make correct calls" do + expect(::RestClient).to receive(:delete). + with("https://api.textrazor.com/entities/id", + x_textrazor_key: 'api_key' + ) + + Request.delete_dictionary(api_key, "id") + end + end + + context ".create_dictionary_entries" do + + let(:dictionary_entries) do + [DictionaryEntry.new(id: "id", text: "text", data: {key: ["value1", "value2"]})] + end + + it "should make correct calls" do + expect(::RestClient).to receive(:post). + with("https://api.textrazor.com/entities/dictionary_id/", + [{ "id" => "id", "text" => "text", "data" => { "key" => ["value1", "value2"] }}].to_json, + x_textrazor_key: 'api_key') + + Request.create_dictionary_entries(api_key, "dictionary_id", dictionary_entries) + end + end + + context ".delete_dictionary_entry" do + + it "should make correct calls" do + expect(::RestClient).to receive(:delete). + with("https://api.textrazor.com/entities/dictionary_id/dictionary_entry_id", + x_textrazor_key: 'api_key' + ) + + Request.delete_dictionary_entry(api_key, "dictionary_id", "dictionary_entry_id") + end + end end end diff --git a/spec/lib/textrazor/response_spec.rb b/spec/lib/textrazor/response_spec.rb index 2c286e3..7a85008 100644 --- a/spec/lib/textrazor/response_spec.rb +++ b/spec/lib/textrazor/response_spec.rb @@ -12,100 +12,6 @@ module TextRazor Response.new(http_response) end - describe "#initialize" do - - context "when HTTP response code is 200" do - - it "should create an instance of Response" do - body = "{\"response\":\"{}\"}" - http_response = ::OpenStruct.new code: 200, body: body - - expect(JSON).to receive(:parse). - with(body, {symbolize_names: true}). - and_return({"response" => "{}"}) - - Response.new(http_response) - end - - end - - context "when HTTP response code is 400" do - - it "should raise an exception" do - http_response = ::OpenStruct.new code: 400 - - expect{ Response.new(http_response) }. - to raise_error(Response::BadRequest) - end - - end - - context "when HTTP response code is 401" do - - it "should raise an exception" do - http_response = ::OpenStruct.new code: 401 - - expect{ Response.new(http_response) }. - to raise_error(Response::Unauthorised) - end - - end - - context "when HTTP response code is 413" do - - it "should raise an exception" do - http_response = ::OpenStruct.new code: 413 - - expect{ Response.new(http_response) }. - to raise_error(Response::RequestEntityTooLong) - end - - end - - end - - describe '#time' do - - it 'returns time taken to process request' do - body = {time: "0.013219"}.to_json - http_response = ::OpenStruct.new code: 200, body: body - response = Response.new(http_response) - - time = response.time - - expect(time).to eq(0.013219) - end - - end - - describe '#ok?' do - - context 'when successfully analysed' do - - it 'returns true' do - body = {ok: true}.to_json - http_response = ::OpenStruct.new code: 200, body: body - response = Response.new(http_response) - - expect(response).to be_ok - end - - end - - context 'when unsuccessfully analysed' do - - it 'returns false' do - body = {ok: false}.to_json - http_response = ::OpenStruct.new code: 200, body: body - response = Response.new(http_response) - - expect(response).to_not be_ok - end - - end - - end - describe '#custom_annotation_output' do it 'returns raw text' do diff --git a/textrazor.gemspec b/textrazor.gemspec index e184cb4..d9e9cd4 100644 --- a/textrazor.gemspec +++ b/textrazor.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_dependency "rest-client" + spec.add_dependency "rest-client", "~> 2.1" spec.add_dependency "fast_open_struct" spec.add_development_dependency "bundler", "~> 1.3"