deepl-rb 2.2.1 → 2.5.3
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 +5 -5
- data/.circleci/config.yml +1 -13
- data/.rubocop.yml +8 -4
- data/Gemfile +6 -0
- data/README.md +133 -25
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/deepl-rb.gemspec +38 -10
- data/lib/deepl/api.rb +2 -0
- data/lib/deepl/configuration.rb +4 -2
- data/lib/deepl/exceptions/authorization_failed.rb +2 -0
- data/lib/deepl/exceptions/bad_request.rb +4 -0
- data/lib/deepl/exceptions/error.rb +2 -0
- data/lib/deepl/exceptions/limit_exceeded.rb +2 -0
- data/lib/deepl/exceptions/not_found.rb +13 -0
- data/lib/deepl/exceptions/not_supported.rb +11 -0
- data/lib/deepl/exceptions/quota_exceeded.rb +2 -0
- data/lib/deepl/exceptions/request_entity_too_large.rb +12 -0
- data/lib/deepl/exceptions/request_error.rb +4 -1
- data/lib/deepl/glossary_api.rb +35 -0
- data/lib/deepl/requests/base.rb +23 -11
- data/lib/deepl/requests/glossary/create.rb +45 -0
- data/lib/deepl/requests/glossary/destroy.rb +30 -0
- data/lib/deepl/requests/glossary/entries.rb +30 -0
- data/lib/deepl/requests/glossary/find.rb +31 -0
- data/lib/deepl/requests/glossary/language_pairs.rb +31 -0
- data/lib/deepl/requests/glossary/list.rb +30 -0
- data/lib/deepl/requests/languages.rb +30 -0
- data/lib/deepl/requests/translate.rb +8 -2
- data/lib/deepl/requests/usage.rb +2 -0
- data/lib/deepl/resources/base.rb +2 -0
- data/lib/deepl/resources/glossary.rb +25 -0
- data/lib/deepl/resources/language.rb +27 -0
- data/lib/deepl/resources/language_pair.rb +20 -0
- data/lib/deepl/resources/text.rb +2 -0
- data/lib/deepl/resources/usage.rb +2 -0
- data/lib/deepl/utils/exception_builder.rb +29 -0
- data/lib/deepl.rb +28 -0
- data/spec/api/api_spec.rb +2 -0
- data/spec/api/configuration_spec.rb +4 -2
- data/spec/api/deepl_spec.rb +213 -0
- data/spec/fixtures/vcr_cassettes/deepl_glossaries.yml +374 -0
- data/spec/fixtures/vcr_cassettes/deepl_languages.yml +43 -0
- data/spec/fixtures/vcr_cassettes/deepl_translate.yml +215 -5
- data/spec/fixtures/vcr_cassettes/deepl_usage.yml +12 -7
- data/spec/fixtures/vcr_cassettes/glossaries.yml +480 -0
- data/spec/fixtures/vcr_cassettes/languages.yml +114 -0
- data/spec/fixtures/vcr_cassettes/translate_texts.yml +199 -33
- data/spec/fixtures/vcr_cassettes/usage.yml +12 -7
- data/spec/requests/glossary/create_spec.rb +55 -0
- data/spec/requests/glossary/destroy_spec.rb +50 -0
- data/spec/requests/glossary/entries_spec.rb +48 -0
- data/spec/requests/glossary/find_spec.rb +54 -0
- data/spec/requests/glossary/language_pairs_spec.rb +30 -0
- data/spec/requests/glossary/list_spec.rb +44 -0
- data/spec/requests/languages_spec.rb +58 -0
- data/spec/requests/translate_spec.rb +139 -4
- data/spec/requests/usage_spec.rb +2 -0
- data/spec/resources/glossary_spec.rb +35 -0
- data/spec/resources/language_pair_spec.rb +20 -0
- data/spec/resources/language_spec.rb +42 -0
- data/spec/resources/text_spec.rb +4 -2
- data/spec/resources/usage_spec.rb +5 -3
- data/spec/spec_helper.rb +6 -4
- metadata +49 -8
- data/Gemfile.lock +0 -113
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class Create < Base
|
|
7
|
+
attr_reader :name, :source_lang, :target_lang, :entries, :entries_format
|
|
8
|
+
|
|
9
|
+
def initialize(api, name, source_lang, target_lang, entries, options = {})
|
|
10
|
+
super(api, options)
|
|
11
|
+
@name = name
|
|
12
|
+
@source_lang = source_lang
|
|
13
|
+
@target_lang = target_lang
|
|
14
|
+
@entries = entries
|
|
15
|
+
@entries_format = delete_option(:entries_format) || 'tsv'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def request
|
|
19
|
+
payload = {
|
|
20
|
+
name: name, source_lang: source_lang, target_lang: target_lang, entries: entries_to_tsv,
|
|
21
|
+
entries_format: entries_format
|
|
22
|
+
}
|
|
23
|
+
build_glossary(*post(payload))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def entries_to_tsv
|
|
29
|
+
return entries if entries.is_a?(String)
|
|
30
|
+
|
|
31
|
+
entries.reduce('') { |tsv, entry| "#{tsv}#{entry.first}\t#{entry.last}\n" }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def build_glossary(request, response)
|
|
35
|
+
glossary = JSON.parse(response.body)
|
|
36
|
+
Resources::Glossary.new(glossary, request, response)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def path
|
|
40
|
+
'glossaries'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class Destroy < Base
|
|
7
|
+
attr_reader :id
|
|
8
|
+
|
|
9
|
+
def initialize(api, id, options = {})
|
|
10
|
+
super(api, options)
|
|
11
|
+
@id = id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def request
|
|
15
|
+
build_response(*delete)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def build_response(_, _)
|
|
21
|
+
id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def path
|
|
25
|
+
"glossaries/#{id}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class Entries < Base
|
|
7
|
+
attr_reader :id
|
|
8
|
+
|
|
9
|
+
def initialize(api, id, options = {})
|
|
10
|
+
super(api, options)
|
|
11
|
+
@id = id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def request
|
|
15
|
+
build_entries(*get)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def build_entries(_, response)
|
|
21
|
+
response.body.split("\n").map { |entry| entry.split("\t") }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def path
|
|
25
|
+
"glossaries/#{id}/entries"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class Find < Base
|
|
7
|
+
attr_reader :id
|
|
8
|
+
|
|
9
|
+
def initialize(api, id, options = {})
|
|
10
|
+
super(api, options)
|
|
11
|
+
@id = id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def request
|
|
15
|
+
build_glossary(*get)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def build_glossary(request, response)
|
|
21
|
+
glossary = JSON.parse(response.body)
|
|
22
|
+
Resources::Glossary.new(glossary, request, response)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def path
|
|
26
|
+
"glossaries/#{id}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class LanguagePairs < Base
|
|
7
|
+
def initialize(api, options = {})
|
|
8
|
+
super(api, options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def request
|
|
12
|
+
build_language_pair_list(*get)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def build_language_pair_list(request, response)
|
|
18
|
+
data = JSON.parse(response.body)
|
|
19
|
+
data['supported_languages'].map do |language_pair|
|
|
20
|
+
Resources::LanguagePair.new(language_pair['source_lang'], language_pair['target_lang'],
|
|
21
|
+
request, response)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def path
|
|
26
|
+
'glossary-language-pairs'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
module Glossary
|
|
6
|
+
class List < Base
|
|
7
|
+
def initialize(api, options = {})
|
|
8
|
+
super(api, options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def request
|
|
12
|
+
build_glossary_list(*get)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def build_glossary_list(request, response)
|
|
18
|
+
data = JSON.parse(response.body)
|
|
19
|
+
data['glossaries'].map do |glossary|
|
|
20
|
+
Resources::Glossary.new(glossary, request, response)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def path
|
|
25
|
+
'glossaries'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Requests
|
|
5
|
+
class Languages < Base
|
|
6
|
+
def initialize(api, options = {})
|
|
7
|
+
super(api, options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def request
|
|
11
|
+
build_languages(*get)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def build_languages(request, response)
|
|
17
|
+
data = JSON.parse(response.body)
|
|
18
|
+
data.map do |language|
|
|
19
|
+
Resources::Language.new(language['language'], language['name'],
|
|
20
|
+
language['supports_formality'],
|
|
21
|
+
request, response)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def path
|
|
26
|
+
'languages'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module DeepL
|
|
2
4
|
module Requests
|
|
3
5
|
class Translate < Base
|
|
4
6
|
BOOLEAN_CONVERSION = { true => '1', false => '0' }.freeze
|
|
5
|
-
ARRAY_CONVERSION = ->(value) { value.is_a?(Array) ? value.join(',
|
|
7
|
+
ARRAY_CONVERSION = ->(value) { value.is_a?(Array) ? value.join(',') : value }.freeze
|
|
6
8
|
OPTIONS_CONVERSIONS = {
|
|
7
9
|
split_sentences: BOOLEAN_CONVERSION,
|
|
8
10
|
preserve_formatting: BOOLEAN_CONVERSION,
|
|
11
|
+
outline_detection: BOOLEAN_CONVERSION,
|
|
12
|
+
splitting_tags: ARRAY_CONVERSION,
|
|
9
13
|
non_splitting_tags: ARRAY_CONVERSION,
|
|
10
14
|
ignore_tags: ARRAY_CONVERSION
|
|
11
15
|
}.freeze
|
|
12
16
|
|
|
13
|
-
attr_reader :text, :source_lang, :target_lang, :ignore_tags, :
|
|
17
|
+
attr_reader :text, :source_lang, :target_lang, :ignore_tags, :splitting_tags,
|
|
18
|
+
:non_splitting_tags
|
|
14
19
|
|
|
15
20
|
def initialize(api, text, source_lang, target_lang, options = {})
|
|
16
21
|
super(api, options)
|
|
@@ -31,6 +36,7 @@ module DeepL
|
|
|
31
36
|
def tweak_parameters!
|
|
32
37
|
OPTIONS_CONVERSIONS.each do |param, converter|
|
|
33
38
|
next unless option?(param) && converter[option(param)]
|
|
39
|
+
|
|
34
40
|
set_option(param, converter[option(param)])
|
|
35
41
|
end
|
|
36
42
|
end
|
data/lib/deepl/requests/usage.rb
CHANGED
data/lib/deepl/resources/base.rb
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Resources
|
|
5
|
+
class Glossary < Base
|
|
6
|
+
attr_reader :id, :name, :ready, :source_lang, :target_lang, :creation_time, :entry_count
|
|
7
|
+
|
|
8
|
+
def initialize(glossary, *args)
|
|
9
|
+
super(*args)
|
|
10
|
+
|
|
11
|
+
@id = glossary['glossary_id']
|
|
12
|
+
@name = glossary['name']
|
|
13
|
+
@ready = glossary['ready']
|
|
14
|
+
@source_lang = glossary['source_lang']
|
|
15
|
+
@target_lang = glossary['target_lang']
|
|
16
|
+
@creation_time = glossary['creation_time']
|
|
17
|
+
@entry_count = glossary['entry_count']
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
"#{id} - #{name}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Resources
|
|
5
|
+
class Language < Base
|
|
6
|
+
attr_reader :code, :name
|
|
7
|
+
|
|
8
|
+
def initialize(code, name, supports_formality, *args)
|
|
9
|
+
super(*args)
|
|
10
|
+
|
|
11
|
+
@code = code
|
|
12
|
+
@name = name
|
|
13
|
+
@supports_formality = supports_formality
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
"#{code} - #{name}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def supports_formality?
|
|
21
|
+
return @supports_formality unless @supports_formality.nil?
|
|
22
|
+
|
|
23
|
+
raise Exceptions::NotSupported, 'Support formality is only available on target languages'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Resources
|
|
5
|
+
class LanguagePair < Base
|
|
6
|
+
attr_reader :source_lang, :target_lang
|
|
7
|
+
|
|
8
|
+
def initialize(source_lang, target_lang, *args)
|
|
9
|
+
super(*args)
|
|
10
|
+
|
|
11
|
+
@source_lang = source_lang
|
|
12
|
+
@target_lang = target_lang
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
"#{source_lang} - #{target_lang}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/deepl/resources/text.rb
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepL
|
|
4
|
+
module Utils
|
|
5
|
+
class ExceptionBuilder
|
|
6
|
+
attr_reader :request, :response
|
|
7
|
+
|
|
8
|
+
ERROR_CODE_CLASS_MAP = {
|
|
9
|
+
'400' => Exceptions::BadRequest,
|
|
10
|
+
'401' => Exceptions::AuthorizationFailed,
|
|
11
|
+
'403' => Exceptions::AuthorizationFailed,
|
|
12
|
+
'404' => Exceptions::NotFound,
|
|
13
|
+
'413' => Exceptions::RequestEntityTooLarge,
|
|
14
|
+
'429' => Exceptions::LimitExceeded,
|
|
15
|
+
'456' => Exceptions::QuotaExceeded
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
def initialize(request, response)
|
|
19
|
+
@request = request
|
|
20
|
+
@response = response
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def build
|
|
24
|
+
error_class = ERROR_CODE_CLASS_MAP[response.code.to_s] || Exceptions::RequestError
|
|
25
|
+
error_class.new(request, response)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/deepl.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# -- Dependencies
|
|
2
4
|
require 'json'
|
|
3
5
|
require 'net/http'
|
|
@@ -9,20 +11,37 @@ require 'deepl/exceptions/authorization_failed'
|
|
|
9
11
|
require 'deepl/exceptions/bad_request'
|
|
10
12
|
require 'deepl/exceptions/limit_exceeded'
|
|
11
13
|
require 'deepl/exceptions/quota_exceeded'
|
|
14
|
+
require 'deepl/exceptions/not_found'
|
|
15
|
+
require 'deepl/exceptions/not_supported'
|
|
16
|
+
require 'deepl/exceptions/request_entity_too_large'
|
|
12
17
|
|
|
13
18
|
# -- Requests
|
|
14
19
|
require 'deepl/requests/base'
|
|
20
|
+
require 'deepl/requests/glossary/create'
|
|
21
|
+
require 'deepl/requests/glossary/destroy'
|
|
22
|
+
require 'deepl/requests/glossary/entries'
|
|
23
|
+
require 'deepl/requests/glossary/find'
|
|
24
|
+
require 'deepl/requests/glossary/language_pairs'
|
|
25
|
+
require 'deepl/requests/glossary/list'
|
|
26
|
+
require 'deepl/requests/languages'
|
|
15
27
|
require 'deepl/requests/translate'
|
|
16
28
|
require 'deepl/requests/usage'
|
|
17
29
|
|
|
18
30
|
# -- Responses and resources
|
|
19
31
|
require 'deepl/resources/base'
|
|
32
|
+
require 'deepl/resources/glossary'
|
|
33
|
+
require 'deepl/resources/language'
|
|
34
|
+
require 'deepl/resources/language_pair'
|
|
20
35
|
require 'deepl/resources/text'
|
|
21
36
|
require 'deepl/resources/usage'
|
|
22
37
|
|
|
38
|
+
# -- Utils
|
|
39
|
+
require 'deepl/utils/exception_builder'
|
|
40
|
+
|
|
23
41
|
# -- Other wrappers
|
|
24
42
|
require 'deepl/api'
|
|
25
43
|
require 'deepl/configuration'
|
|
44
|
+
require 'deepl/glossary_api'
|
|
26
45
|
|
|
27
46
|
# -- Gem interface
|
|
28
47
|
module DeepL
|
|
@@ -34,11 +53,20 @@ module DeepL
|
|
|
34
53
|
@api ||= API.new(configuration)
|
|
35
54
|
end
|
|
36
55
|
|
|
56
|
+
def languages(options = {})
|
|
57
|
+
Requests::Languages.new(api, options).request
|
|
58
|
+
end
|
|
59
|
+
|
|
37
60
|
def translate(text, source_lang, target_lang, options = {})
|
|
38
61
|
configure if @configuration.nil?
|
|
39
62
|
Requests::Translate.new(api, text, source_lang, target_lang, options).request
|
|
40
63
|
end
|
|
41
64
|
|
|
65
|
+
def glossaries(options = {})
|
|
66
|
+
configure if @configuration.nil?
|
|
67
|
+
GlossaryApi.new(api, options)
|
|
68
|
+
end
|
|
69
|
+
|
|
42
70
|
def usage(options = {})
|
|
43
71
|
configure if @configuration.nil?
|
|
44
72
|
Requests::Usage.new(api, options).request
|
data/spec/api/api_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe DeepL::Configuration do
|
|
@@ -7,14 +9,14 @@ describe DeepL::Configuration do
|
|
|
7
9
|
describe '#initialize' do
|
|
8
10
|
context 'When using default configuration attributes' do
|
|
9
11
|
it 'should use default attributes' do
|
|
10
|
-
expect(subject.auth_key).to eq(ENV
|
|
12
|
+
expect(subject.auth_key).to eq(ENV.fetch('DEEPL_AUTH_KEY', nil))
|
|
11
13
|
expect(subject.host).to eq('https://api.deepl.com')
|
|
12
14
|
expect(subject.version).to eq('v2')
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
context 'When using custom configuration attributes' do
|
|
17
|
-
let(:attributes) { { auth_key: 'SAMPLE', host: '
|
|
19
|
+
let(:attributes) { { auth_key: 'SAMPLE', host: 'https://api-free.deepl.com', version: 'v1' } }
|
|
18
20
|
|
|
19
21
|
it 'should use custom attributes' do
|
|
20
22
|
expect(subject.auth_key).to eq(attributes[:auth_key])
|