deepl-rb 3.9.0 → 3.10.0
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 +4 -4
- data/.gitlab-ci.yml +70 -52
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +429 -18
- data/Gemfile +4 -0
- data/README.md +981 -223
- data/Rakefile +18 -5
- data/VERSION +1 -1
- data/deepl-rb.gemspec +6 -6
- data/lib/deepl/admin_client.rb +183 -0
- data/lib/deepl/api.rb +30 -6
- data/lib/deepl/app_info.rb +20 -0
- data/lib/deepl/client.rb +969 -0
- data/lib/deepl/configuration.rb +56 -10
- data/lib/deepl/constants/admin_usage_group_by.rb +13 -0
- data/lib/deepl/constants/custom_tag_usage_aggregate_by.rb +13 -0
- data/lib/deepl/constants/document_status_code.rb +17 -0
- data/lib/deepl/constants/language_include.rb +17 -0
- data/lib/deepl/constants/language_resource_name.rb +21 -0
- data/lib/deepl/constants/tag_handling_version.rb +14 -0
- data/lib/deepl/deprecation.rb +42 -0
- data/lib/deepl/document_api.rb +41 -22
- data/lib/deepl/exceptions/bad_request.rb +1 -3
- data/lib/deepl/exceptions/connection_error.rb +37 -0
- data/lib/deepl/exceptions/document_not_ready_error.rb +17 -0
- data/lib/deepl/exceptions/document_translation_error.rb +17 -1
- data/lib/deepl/exceptions/error.rb +13 -1
- data/lib/deepl/exceptions/not_found.rb +8 -3
- data/lib/deepl/exceptions/not_supported.rb +6 -0
- data/lib/deepl/exceptions/request_error.rb +19 -2
- data/lib/deepl/exceptions/server_error.rb +7 -1
- data/lib/deepl/exceptions/validation_error.rb +14 -0
- data/lib/deepl/requests/admin/base.rb +94 -0
- data/lib/deepl/requests/admin/create_developer_key.rb +38 -0
- data/lib/deepl/requests/admin/custom_tag_usage_analytics.rb +38 -0
- data/lib/deepl/requests/admin/list_developer_keys.rb +28 -0
- data/lib/deepl/requests/admin/update_developer_key.rb +35 -0
- data/lib/deepl/requests/admin/usage_analytics.rb +36 -0
- data/lib/deepl/requests/base.rb +229 -59
- data/lib/deepl/requests/correct.rb +57 -0
- data/lib/deepl/requests/document/download.rb +11 -3
- data/lib/deepl/requests/document/get_status.rb +2 -2
- data/lib/deepl/requests/document/upload.rb +43 -10
- data/lib/deepl/requests/glossary/create.rb +6 -2
- data/lib/deepl/requests/glossary/language_pairs.rb +20 -4
- data/lib/deepl/requests/language_resources.rb +41 -0
- data/lib/deepl/requests/languages.rb +28 -4
- data/lib/deepl/requests/languages_for_resource.rb +54 -0
- data/lib/deepl/requests/multilingual_glossary/create.rb +37 -0
- data/lib/deepl/requests/multilingual_glossary/destroy.rb +36 -0
- data/lib/deepl/requests/multilingual_glossary/destroy_dictionary.rb +51 -0
- data/lib/deepl/requests/multilingual_glossary/entries.rb +66 -0
- data/lib/deepl/requests/multilingual_glossary/find.rb +35 -0
- data/lib/deepl/requests/multilingual_glossary/helpers.rb +63 -0
- data/lib/deepl/requests/multilingual_glossary/list.rb +39 -0
- data/lib/deepl/requests/multilingual_glossary/replace_dictionary.rb +41 -0
- data/lib/deepl/requests/multilingual_glossary/update.rb +40 -0
- data/lib/deepl/requests/rephrase.rb +5 -9
- data/lib/deepl/requests/spoken_terms/create.rb +37 -0
- data/lib/deepl/requests/spoken_terms/destroy.rb +36 -0
- data/lib/deepl/requests/spoken_terms/destroy_term_list.rb +41 -0
- data/lib/deepl/requests/spoken_terms/entries.rb +46 -0
- data/lib/deepl/requests/spoken_terms/find.rb +35 -0
- data/lib/deepl/requests/spoken_terms/helpers.rb +67 -0
- data/lib/deepl/requests/spoken_terms/list.rb +35 -0
- data/lib/deepl/requests/spoken_terms/replace_term_list.rb +41 -0
- data/lib/deepl/requests/spoken_terms/update.rb +40 -0
- data/lib/deepl/requests/style_profile/base.rb +83 -0
- data/lib/deepl/requests/style_profile/create.rb +35 -0
- data/lib/deepl/requests/style_profile/destroy.rb +34 -0
- data/lib/deepl/requests/style_profile/find.rb +33 -0
- data/lib/deepl/requests/style_profile/list.rb +43 -0
- data/lib/deepl/requests/style_profile/update.rb +35 -0
- data/lib/deepl/requests/style_rule/create.rb +1 -1
- data/lib/deepl/requests/style_rule/create_custom_instruction.rb +4 -2
- data/lib/deepl/requests/style_rule/destroy.rb +4 -2
- data/lib/deepl/requests/style_rule/destroy_custom_instruction.rb +5 -3
- data/lib/deepl/requests/style_rule/find.rb +4 -2
- data/lib/deepl/requests/style_rule/find_custom_instruction.rb +5 -3
- data/lib/deepl/requests/style_rule/helpers.rb +35 -0
- data/lib/deepl/requests/style_rule/list.rb +1 -1
- data/lib/deepl/requests/style_rule/update.rb +4 -2
- data/lib/deepl/requests/style_rule/update_configured_rules.rb +4 -2
- data/lib/deepl/requests/style_rule/update_custom_instruction.rb +5 -3
- data/lib/deepl/requests/translate.rb +52 -20
- data/lib/deepl/requests/translation_memory/base.rb +1 -4
- data/lib/deepl/requests/translation_memory/create_export.rb +1 -1
- data/lib/deepl/requests/translation_memory/create_import.rb +1 -1
- data/lib/deepl/requests/translation_memory/destroy.rb +1 -1
- data/lib/deepl/requests/translation_memory/download_export.rb +4 -0
- data/lib/deepl/requests/translation_memory/find.rb +1 -1
- data/lib/deepl/requests/translation_memory/find_job.rb +1 -1
- data/lib/deepl/requests/translation_memory/list.rb +2 -1
- data/lib/deepl/requests/translation_memory/segments.rb +3 -2
- data/lib/deepl/requests/translation_memory/storage_base.rb +40 -8
- data/lib/deepl/requests/translation_memory/upload_file.rb +1 -1
- data/lib/deepl/requests/usage.rb +28 -1
- data/lib/deepl/requests/write_improvements.rb +35 -0
- data/lib/deepl/resources/admin_usage_report.rb +73 -0
- data/lib/deepl/resources/custom_tag_usage_report.rb +59 -0
- data/lib/deepl/resources/developer_key.rb +57 -0
- data/lib/deepl/resources/document_handle.rb +24 -25
- data/lib/deepl/resources/document_translation_status.rb +23 -4
- data/lib/deepl/resources/language.rb +10 -2
- data/lib/deepl/resources/language_resource.rb +57 -0
- data/lib/deepl/resources/language_support.rb +56 -0
- data/lib/deepl/resources/multilingual_glossary.rb +112 -0
- data/lib/deepl/resources/spoken_terms.rb +61 -0
- data/lib/deepl/resources/style_profile.rb +44 -0
- data/lib/deepl/resources/style_rule.rb +3 -0
- data/lib/deepl/resources/text.rb +18 -2
- data/lib/deepl/resources/translation_memory.rb +8 -2
- data/lib/deepl/resources/translation_memory_import.rb +1 -1
- data/lib/deepl/resources/translation_memory_job.rb +23 -3
- data/lib/deepl/resources/translation_memory_segments.rb +8 -6
- data/lib/deepl/resources/usage.rb +93 -4
- data/lib/deepl/style_rule_api.rb +11 -0
- data/lib/deepl/translation_memory_api.rb +104 -24
- data/lib/deepl/utils/client_builder.rb +54 -0
- data/lib/deepl/utils/document_poller.rb +70 -0
- data/lib/deepl/utils/exception_builder.rb +3 -2
- data/lib/deepl/utils/http_client_builder.rb +79 -0
- data/lib/deepl/utils/number_parser.rb +34 -0
- data/lib/deepl/utils/term_validator.rb +33 -0
- data/lib/deepl/utils/time_parser.rb +14 -0
- data/lib/deepl.rb +166 -41
- data/lib/http_client_options.rb +21 -1
- data/lib/version.rb +1 -1
- data/spec/fixtures.rb +33 -0
- data/spec/offline/admin_client_spec.rb +551 -0
- data/spec/offline/client_spec.rb +273 -0
- data/spec/{api → offline}/configuration_spec.rb +45 -3
- data/spec/{constants → offline}/constants_spec.rb +23 -1
- data/spec/offline/correct_text_spec.rb +50 -0
- data/spec/offline/deprecation_spec.rb +32 -0
- data/spec/offline/errors_spec.rb +92 -0
- data/spec/offline/glossaries_spec.rb +98 -0
- data/spec/offline/http_client_spec.rb +319 -0
- data/spec/offline/languages_spec.rb +155 -0
- data/spec/offline/module_methods_spec.rb +13 -0
- data/spec/offline/multilingual_glossaries_spec.rb +358 -0
- data/spec/offline/offline_helper.rb +71 -0
- data/spec/offline/rephrase_text_spec.rb +73 -0
- data/spec/offline/spoken_terms_spec.rb +215 -0
- data/spec/offline/style_profiles_spec.rb +266 -0
- data/spec/offline/style_rules_spec.rb +318 -0
- data/spec/offline/translate_document_spec.rb +606 -0
- data/spec/offline/translate_text_spec.rb +286 -0
- data/spec/offline/translation_memories_client_spec.rb +256 -0
- data/spec/offline/translation_memories_spec.rb +463 -0
- data/spec/offline/usage_spec.rb +151 -0
- data/spec/real_api/admin_client_spec.rb +77 -0
- data/spec/real_api/correct_text_spec.rb +20 -0
- data/spec/real_api/glossaries_spec.rb +28 -0
- data/spec/real_api/languages_spec.rb +27 -0
- data/spec/real_api/multilingual_glossaries_spec.rb +53 -0
- data/spec/real_api/proxy_spec.rb +41 -0
- data/spec/real_api/real_api_helper.rb +65 -0
- data/spec/real_api/rephrase_text_spec.rb +16 -0
- data/spec/real_api/spoken_terms_spec.rb +56 -0
- data/spec/real_api/style_profiles_spec.rb +46 -0
- data/spec/real_api/style_rules_spec.rb +46 -0
- data/spec/real_api/translate_document_spec.rb +18 -0
- data/spec/real_api/translate_text_spec.rb +16 -0
- data/spec/real_api/translation_memories_spec.rb +56 -0
- data/spec/real_api/usage_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -50
- metadata +116 -76
- data/.circleci/config.yml +0 -27
- data/.github/workflows/add_issues_to_kanban.yml +0 -16
- data/spec/api/api_spec.rb +0 -20
- data/spec/api/deepl_spec.rb +0 -262
- data/spec/integration_tests/document_api_spec.rb +0 -211
- data/spec/integration_tests/document_error_paths_spec.rb +0 -33
- data/spec/integration_tests/glossary_api_spec.rb +0 -114
- data/spec/integration_tests/glossary_error_paths_spec.rb +0 -107
- data/spec/integration_tests/integration_test_utils.rb +0 -178
- data/spec/integration_tests/languages_api_spec.rb +0 -54
- data/spec/integration_tests/languages_error_paths_spec.rb +0 -25
- data/spec/integration_tests/rephrase_api_spec.rb +0 -90
- data/spec/integration_tests/rephrase_error_paths_spec.rb +0 -53
- data/spec/integration_tests/smoke_test_spec.rb +0 -24
- data/spec/integration_tests/style_rule_api_spec.rb +0 -117
- data/spec/integration_tests/style_rule_error_paths_spec.rb +0 -45
- data/spec/integration_tests/translate_api_spec.rb +0 -117
- data/spec/integration_tests/translate_error_paths_spec.rb +0 -48
- data/spec/integration_tests/translation_memory_api_spec.rb +0 -244
- data/spec/integration_tests/translation_memory_error_paths_spec.rb +0 -87
- data/spec/integration_tests/usage_api_spec.rb +0 -29
- data/spec/integration_tests/usage_error_paths_spec.rb +0 -18
- data/spec/requests/document/upload_spec.rb +0 -130
- data/spec/requests/extra_body_parameters_types_spec.rb +0 -82
- data/spec/requests/glossary/create_spec.rb +0 -44
- data/spec/requests/glossary/destroy_spec.rb +0 -27
- data/spec/requests/glossary/entries_spec.rb +0 -27
- data/spec/requests/glossary/find_spec.rb +0 -28
- data/spec/requests/glossary/language_pairs_spec.rb +0 -27
- data/spec/requests/glossary/list_spec.rb +0 -27
- data/spec/requests/languages_spec.rb +0 -27
- data/spec/requests/rephrase_spec.rb +0 -46
- data/spec/requests/style_rule/create_custom_instruction_spec.rb +0 -30
- data/spec/requests/style_rule/create_spec.rb +0 -29
- data/spec/requests/style_rule/destroy_custom_instruction_spec.rb +0 -28
- data/spec/requests/style_rule/destroy_spec.rb +0 -27
- data/spec/requests/style_rule/find_custom_instruction_spec.rb +0 -29
- data/spec/requests/style_rule/find_spec.rb +0 -28
- data/spec/requests/style_rule/list_spec.rb +0 -27
- data/spec/requests/style_rule/update_configured_rules_spec.rb +0 -31
- data/spec/requests/style_rule/update_custom_instruction_spec.rb +0 -32
- data/spec/requests/style_rule/update_spec.rb +0 -29
- data/spec/requests/translate_spec.rb +0 -338
- data/spec/requests/translation_memory/create_export_spec.rb +0 -37
- data/spec/requests/translation_memory/create_import_spec.rb +0 -61
- data/spec/requests/translation_memory/destroy_spec.rb +0 -36
- data/spec/requests/translation_memory/download_export_spec.rb +0 -54
- data/spec/requests/translation_memory/find_job_spec.rb +0 -37
- data/spec/requests/translation_memory/find_spec.rb +0 -36
- data/spec/requests/translation_memory/list_spec.rb +0 -27
- data/spec/requests/translation_memory/segments_spec.rb +0 -58
- data/spec/requests/translation_memory/upload_file_spec.rb +0 -55
- data/spec/requests/usage_spec.rb +0 -27
- data/spec/resources/custom_instruction_spec.rb +0 -32
- data/spec/resources/glossary_spec.rb +0 -38
- data/spec/resources/language_pair_spec.rb +0 -23
- data/spec/resources/language_spec.rb +0 -45
- data/spec/resources/style_rule_spec.rb +0 -68
- data/spec/resources/text_spec.rb +0 -23
- data/spec/resources/translation_memory_export_spec.rb +0 -38
- data/spec/resources/translation_memory_import_spec.rb +0 -30
- data/spec/resources/translation_memory_job_spec.rb +0 -109
- data/spec/resources/translation_memory_segments_spec.rb +0 -78
- data/spec/resources/translation_memory_spec.rb +0 -52
- data/spec/resources/usage_spec.rb +0 -35
- data/spec/support/live_mock_server.rb +0 -12
- data/spec/support/managed_glossary.rb +0 -65
- data/spec/support/managed_style_rule.rb +0 -17
- data/spec/support/managed_translation_memory.rb +0 -55
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE.md file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe DeepL::AdminClient do
|
|
9
|
+
subject(:client) do
|
|
10
|
+
described_class.new(ENV.fetch('DEEPL_ADMIN_KEY'),
|
|
11
|
+
server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
next unless ENV.fetch('DEEPL_ADMIN_KEY', '').empty?
|
|
16
|
+
|
|
17
|
+
raise 'DEEPL_ADMIN_KEY must be set to run the Admin API specs'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:end_date) { Time.now.utc.to_date }
|
|
21
|
+
let(:start_date) { end_date - 7 }
|
|
22
|
+
|
|
23
|
+
def key_listed?(client, key_id)
|
|
24
|
+
5.times do |attempt|
|
|
25
|
+
return true if client.list_developer_keys.map(&:key_id).include?(key_id)
|
|
26
|
+
|
|
27
|
+
sleep 1 unless attempt == 4
|
|
28
|
+
end
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'sends GET /v2/admin/analytics and parses the report' do
|
|
33
|
+
report = client.get_usage_analytics(start_date, end_date,
|
|
34
|
+
group_by: DeepL::Constants::AdminUsageGroupBy::KEY_AND_DAY)
|
|
35
|
+
|
|
36
|
+
expect(report.start_date).not_to be_nil
|
|
37
|
+
expect(report.end_date).not_to be_nil
|
|
38
|
+
expect(report.group_by).to eq('keyAndDay')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'sends GET /v2/admin/analytics/custom-tags and parses the report' do
|
|
42
|
+
report = client.get_custom_tag_usage_analytics(
|
|
43
|
+
start_date, end_date, aggregate_by: DeepL::Constants::CustomTagUsageAggregateBy::DAY
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
expect(report.start_date).not_to be_nil
|
|
47
|
+
expect(report.end_date).not_to be_nil
|
|
48
|
+
expect(report.aggregate_by).to eq('day')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'sends the developer key requests: create, list, rename, set limits and deactivate' do
|
|
52
|
+
key = client.create_developer_key(label: unique_name('developer-key'))
|
|
53
|
+
failure = nil
|
|
54
|
+
begin
|
|
55
|
+
expect(key.deactivated?).to be(false)
|
|
56
|
+
expect(key_listed?(client, key.key_id)).to be(true), 'created key not listed after 5 attempts'
|
|
57
|
+
renamed = client.rename_developer_key(key, "#{key.label}-renamed")
|
|
58
|
+
expect(renamed.label).to eq("#{key.label}-renamed")
|
|
59
|
+
limited = client.set_developer_key_usage_limits(key, characters: 5000,
|
|
60
|
+
speech_to_text_milliseconds: nil)
|
|
61
|
+
expect(limited.usage_limits).to have_attributes(characters: 5000,
|
|
62
|
+
speech_to_text_milliseconds: nil)
|
|
63
|
+
rescue StandardError, RSpec::Expectations::ExpectationNotMetError => e
|
|
64
|
+
failure = e
|
|
65
|
+
raise
|
|
66
|
+
ensure
|
|
67
|
+
begin
|
|
68
|
+
deactivated = client.deactivate_developer_key(key)
|
|
69
|
+
rescue DeepL::Exceptions::NotFound
|
|
70
|
+
deactivated = nil
|
|
71
|
+
rescue StandardError
|
|
72
|
+
raise if failure.nil?
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
expect(deactivated&.deactivated?).to be(true)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client#correct_text' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'sends POST /v2/write/correct and parses the result' do
|
|
14
|
+
result = client.correct_text('Protonenstrahl', 'de')
|
|
15
|
+
|
|
16
|
+
expect(result).to be_a(DeepL::Resources::Text)
|
|
17
|
+
expect(result.text).to be_a(String)
|
|
18
|
+
expect(result.detected_source_language).not_to be_empty
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL.glossaries' do
|
|
9
|
+
it 'sends the v2 glossary requests: create, get, list, entries and delete' do
|
|
10
|
+
glossaries = DeepL.glossaries
|
|
11
|
+
name = unique_name('glossary')
|
|
12
|
+
entries = [%w[Apple Apfel], %w[Banana Banane]]
|
|
13
|
+
|
|
14
|
+
glossary = glossaries.create(name, 'EN', 'DE', entries)
|
|
15
|
+
begin
|
|
16
|
+
expect([glossary.name, glossary.source_lang, glossary.target_lang, glossary.entry_count])
|
|
17
|
+
.to eq([name, 'en', 'de', 2])
|
|
18
|
+
|
|
19
|
+
fetched = retry_while_not_found { glossaries.find(glossary.id) }
|
|
20
|
+
expect([fetched.id, fetched.name]).to eq([glossary.id, name])
|
|
21
|
+
expect(glossaries.list.map(&:id)).to include(glossary.id)
|
|
22
|
+
expect(glossaries.entries(glossary.id)).to match_array(entries)
|
|
23
|
+
ensure
|
|
24
|
+
delete_quietly { glossaries.destroy(glossary.id) }
|
|
25
|
+
end
|
|
26
|
+
expect { glossaries.find(glossary.id) }.to raise_error(DeepL::Exceptions::NotFound)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'languages' do
|
|
9
|
+
it 'sends GET /v3/languages and parses the source languages' do
|
|
10
|
+
languages = DeepL.languages
|
|
11
|
+
codes = languages.map(&:code)
|
|
12
|
+
|
|
13
|
+
expect(codes).to include('EN')
|
|
14
|
+
expect(codes).to eq(codes.map(&:upcase))
|
|
15
|
+
expect(languages.map(&:name)).to all(be_a(String))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'sends GET /v3/languages/resources and parses the resources and their features' do
|
|
19
|
+
client = DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'),
|
|
20
|
+
server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
21
|
+
resources = client.get_language_resources
|
|
22
|
+
|
|
23
|
+
translate_text = resources.find { |resource| resource.name == 'translate_text' }
|
|
24
|
+
expect(translate_text.features['glossary'].needs_source_support?).to be(true)
|
|
25
|
+
expect(translate_text.features['glossary'].needs_target_support?).to be(true)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client multilingual glossaries' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pairs_of(glossary)
|
|
14
|
+
glossary.dictionaries.map { |d| "#{d.source_lang}-#{d.target_lang}" }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'creates, reads, updates, replaces and deletes a multilingual glossary' do
|
|
18
|
+
name = unique_name('glossary-v3')
|
|
19
|
+
dictionaries = [
|
|
20
|
+
DeepL::Resources::MultilingualGlossaryDictionaryEntries.new('EN', 'DE', [%w[Apple Apfel]]),
|
|
21
|
+
{ source_lang: 'EN', target_lang: 'FR', entries: [%w[Apple Pomme]] }
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
glossary = client.create_multilingual_glossary(name, dictionaries)
|
|
25
|
+
begin
|
|
26
|
+
expect(glossary.name).to eq(name)
|
|
27
|
+
expect(glossary.creation_time).to be_a(Time)
|
|
28
|
+
expect(pairs_of(glossary)).to contain_exactly('en-de', 'en-fr')
|
|
29
|
+
|
|
30
|
+
fetched = retry_while_not_found { client.get_multilingual_glossary(glossary) }
|
|
31
|
+
expect([fetched.id, fetched.name]).to eq([glossary.id, name])
|
|
32
|
+
expect(client.list_multilingual_glossaries.map(&:id)).to include(glossary.id)
|
|
33
|
+
|
|
34
|
+
entries = client.get_multilingual_glossary_dictionary_entries(glossary, 'EN', 'DE')
|
|
35
|
+
expect(entries.entries).to eq('Apple' => 'Apfel')
|
|
36
|
+
|
|
37
|
+
pear = { source_lang: 'EN', target_lang: 'DE', entries: [%w[Pear Birne]] }
|
|
38
|
+
updated = client.update_multilingual_glossary(glossary, name: "#{name}-renamed",
|
|
39
|
+
dictionaries: [pear])
|
|
40
|
+
expect(updated.name).to eq("#{name}-renamed")
|
|
41
|
+
|
|
42
|
+
replaced = client.replace_multilingual_glossary_dictionary(
|
|
43
|
+
glossary, { source_lang: 'EN', target_lang: 'DE', entries: [%w[Cherry Kirsche]] }
|
|
44
|
+
)
|
|
45
|
+
expect([replaced.source_lang, replaced.target_lang, replaced.entry_count])
|
|
46
|
+
.to eq(['en', 'de', 1])
|
|
47
|
+
|
|
48
|
+
expect(client.delete_multilingual_glossary_dictionary(glossary, 'EN', 'FR')).to be_nil
|
|
49
|
+
ensure
|
|
50
|
+
delete_quietly { client.delete_multilingual_glossary(glossary) }
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require 'webrick'
|
|
7
|
+
require 'webrick/httpproxy'
|
|
8
|
+
require_relative 'real_api_helper'
|
|
9
|
+
|
|
10
|
+
# A forward proxy that records the target of each CONNECT.
|
|
11
|
+
class RecordingProxy < WEBrick::HTTPProxyServer
|
|
12
|
+
def connect_targets
|
|
13
|
+
@connect_targets ||= []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def do_CONNECT(req, res) # rubocop:disable Naming/MethodName
|
|
17
|
+
connect_targets << req.unparsed_uri
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'DeepL.with_session' do
|
|
23
|
+
it 'sends requests through the configured proxy' do
|
|
24
|
+
proxy = RecordingProxy.new(Port: 0, BindAddress: '127.0.0.1', AccessLog: [],
|
|
25
|
+
Logger: WEBrick::Log.new(File::NULL))
|
|
26
|
+
thread = Thread.new { proxy.start }
|
|
27
|
+
begin
|
|
28
|
+
port = proxy.listeners.first.addr[1]
|
|
29
|
+
options = DeepL::HTTPClientOptions.new({ 'proxy_addr' => '127.0.0.1', 'proxy_port' => port })
|
|
30
|
+
|
|
31
|
+
usage = DeepL.with_session(options) { DeepL.usage }
|
|
32
|
+
|
|
33
|
+
host = URI(DeepL.configuration.host)
|
|
34
|
+
expect(usage.character_limit).to be_an(Integer)
|
|
35
|
+
expect(proxy.connect_targets).to eq(["#{host.host}:#{host.port}"])
|
|
36
|
+
ensure
|
|
37
|
+
proxy.shutdown
|
|
38
|
+
thread.join
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
# The real-API suite sends one real request per SDK operation to the API at DEEPL_SERVER_URL.
|
|
7
|
+
# Run it on its own: bundle exec rspec spec/real_api
|
|
8
|
+
|
|
9
|
+
raise 'DEEPL_AUTH_KEY must be set to run spec/real_api' if ENV.fetch('DEEPL_AUTH_KEY', '').empty?
|
|
10
|
+
if defined?(WebMock)
|
|
11
|
+
raise 'spec/real_api and spec/offline cannot run in one process: WebMock blocks the network'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
require 'securerandom'
|
|
15
|
+
require_relative '../spec_helper'
|
|
16
|
+
require_relative '../fixtures'
|
|
17
|
+
|
|
18
|
+
module RealApiHelper
|
|
19
|
+
RUN_ID = "#{Time.now.utc.strftime('%Y%m%d%H%M')}-#{SecureRandom.alphanumeric(6).downcase}"
|
|
20
|
+
|
|
21
|
+
# Name of a resource created by this run, for example sdktest-ruby-202610151530-k3f9qz-glossary.
|
|
22
|
+
def unique_name(label)
|
|
23
|
+
"sdktest-ruby-#{RUN_ID}-#{label}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# A new glossary can be briefly invisible: retry NotFound for a few seconds.
|
|
27
|
+
def retry_while_not_found(attempts: 10)
|
|
28
|
+
tries = 0
|
|
29
|
+
begin
|
|
30
|
+
yield
|
|
31
|
+
rescue DeepL::Exceptions::NotFound
|
|
32
|
+
tries += 1
|
|
33
|
+
raise if tries >= attempts
|
|
34
|
+
|
|
35
|
+
sleep(1)
|
|
36
|
+
retry
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Cleanup that must not hide the failure of the example it runs after.
|
|
41
|
+
def delete_quietly
|
|
42
|
+
yield
|
|
43
|
+
rescue DeepL::Exceptions::Error
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Fetches pages of 0-based index until +id+ is in one of them. The block returns the IDs of a
|
|
48
|
+
# page; an empty page ends the list.
|
|
49
|
+
def found_on_any_page?(id, max_pages: 20)
|
|
50
|
+
max_pages.times do |page|
|
|
51
|
+
ids = yield(page)
|
|
52
|
+
return false if ids.empty?
|
|
53
|
+
return true if ids.include?(id)
|
|
54
|
+
end
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The host comes from DEEPL_SERVER_URL, which Configuration reads itself.
|
|
60
|
+
DeepL.configure { |config| config.auth_key = ENV.fetch('DEEPL_AUTH_KEY') }
|
|
61
|
+
|
|
62
|
+
RSpec.configure do |config|
|
|
63
|
+
config.include RealApiHelper
|
|
64
|
+
config.include Fixtures
|
|
65
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL.rephrase' do
|
|
9
|
+
it 'sends POST /v2/write/rephrase and parses the result' do
|
|
10
|
+
result = DeepL.rephrase('Protonenstrahl', 'de')
|
|
11
|
+
|
|
12
|
+
expect(result).to be_a(DeepL::Resources::Text)
|
|
13
|
+
expect(result.text).to be_a(String)
|
|
14
|
+
expect(result.detected_source_language).not_to be_empty
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client spoken terms' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def term_lists_of(collection)
|
|
14
|
+
collection.term_lists.map { |list| [list.lang, list.entry_count] }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'creates, reads, updates, replaces and deletes a spoken terms collection' do
|
|
18
|
+
name = unique_name('spokenTerms')
|
|
19
|
+
|
|
20
|
+
term_list = DeepL::Resources::SpokenTermsEntries.new('en', %w[DeepL webhook])
|
|
21
|
+
created = client.create_spoken_terms(name, [term_list])
|
|
22
|
+
id = created.spoken_terms_id
|
|
23
|
+
begin
|
|
24
|
+
expect(created.name).to eq(name)
|
|
25
|
+
expect(created.creation_time).to be_a(Time)
|
|
26
|
+
expect(term_lists_of(created)).to eq([['en', 2]])
|
|
27
|
+
|
|
28
|
+
fetched = retry_while_not_found { client.get_spoken_terms(id) }
|
|
29
|
+
expect([fetched.spoken_terms_id, fetched.name]).to eq([id, name])
|
|
30
|
+
expect(client.list_spoken_terms.map(&:spoken_terms_id)).to include(id)
|
|
31
|
+
|
|
32
|
+
more = [{ lang: 'en', entries: ['authentication'] }]
|
|
33
|
+
updated = client.update_spoken_terms(created, term_lists: more)
|
|
34
|
+
expect(term_lists_of(updated)).to eq([['en', 3]])
|
|
35
|
+
entries = client.get_spoken_terms_entries(id, 'en')
|
|
36
|
+
expect(entries.lang).to eq('en')
|
|
37
|
+
expect(entries.entries).to contain_exactly('DeepL', 'authentication', 'webhook')
|
|
38
|
+
|
|
39
|
+
replaced = client.replace_spoken_terms_list(id, { lang: 'en', entries: ['API'] })
|
|
40
|
+
expect([replaced.lang, replaced.entry_count]).to eq(['en', 1])
|
|
41
|
+
expect(client.get_spoken_terms_entries(id, 'en').entries).to eq(['API'])
|
|
42
|
+
|
|
43
|
+
added = client.replace_spoken_terms_list(
|
|
44
|
+
created, DeepL::Resources::SpokenTermsEntries.new('de', ['Schnittstelle'])
|
|
45
|
+
)
|
|
46
|
+
expect([added.lang, added.entry_count]).to eq(['de', 1])
|
|
47
|
+
expect(client.delete_spoken_terms_list(id, 'de')).to be_nil
|
|
48
|
+
expect(term_lists_of(client.get_spoken_terms(id))).to eq([['en', 1]])
|
|
49
|
+
|
|
50
|
+
expect(client.delete_spoken_terms(id)).to be_nil
|
|
51
|
+
expect { client.get_spoken_terms(id) }.to raise_error(DeepL::Exceptions::NotFound)
|
|
52
|
+
ensure
|
|
53
|
+
delete_quietly { client.delete_spoken_terms(id) }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client style profiles' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'creates, reads, lists, updates and deletes a style profile' do
|
|
14
|
+
rule = DeepL.style_rules.create(unique_name('styleProfileRule'), 'de')
|
|
15
|
+
rule_id = rule.style_id
|
|
16
|
+
id = nil
|
|
17
|
+
begin
|
|
18
|
+
name = unique_name('styleProfile')
|
|
19
|
+
profile = client.create_style_profile(name, description: 'SDK test', style_rule_ids: [rule])
|
|
20
|
+
id = profile.style_profile_id
|
|
21
|
+
expect([profile.name, profile.description, profile.style_rule_ids])
|
|
22
|
+
.to eq([name, 'SDK test', [rule_id]])
|
|
23
|
+
expect([profile.glossary_ids, profile.translation_memory_ids]).to eq([[], []])
|
|
24
|
+
|
|
25
|
+
fetched = retry_while_not_found { client.get_style_profile(id) }
|
|
26
|
+
expect([fetched.style_profile_id, fetched.name, fetched.description, fetched.style_rule_ids])
|
|
27
|
+
.to eq([id, name, 'SDK test', [rule_id]])
|
|
28
|
+
expect(fetched.creation_time).to be_a(Time)
|
|
29
|
+
|
|
30
|
+
expect(found_on_any_page?(id) do |page|
|
|
31
|
+
client.list_style_profiles(page: page, page_size: 100).map(&:style_profile_id)
|
|
32
|
+
end).to be(true)
|
|
33
|
+
|
|
34
|
+
updated = client.update_style_profile(profile, name: "#{name}-renamed", industry: 'Legal',
|
|
35
|
+
description: '', style_rule_ids: [])
|
|
36
|
+
expect([updated.name, updated.industry, updated.description, updated.style_rule_ids])
|
|
37
|
+
.to eq(["#{name}-renamed", 'Legal', nil, []])
|
|
38
|
+
|
|
39
|
+
expect(client.delete_style_profile(id)).to be_nil
|
|
40
|
+
expect { client.get_style_profile(id) }.to raise_error(DeepL::Exceptions::NotFound)
|
|
41
|
+
ensure
|
|
42
|
+
delete_quietly { client.delete_style_profile(id) } if id
|
|
43
|
+
delete_quietly { DeepL.style_rules.destroy(rule_id) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client style rules' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'sends the style rule requests: create, get, list, rename, configure, instructions, delete' do
|
|
14
|
+
name = unique_name('style-rule')
|
|
15
|
+
rules = { dates_and_times: { calendar_era: 'use_bc_and_ad' } }
|
|
16
|
+
|
|
17
|
+
rule = client.create_style_rule(name, 'en', configured_rules: rules,
|
|
18
|
+
custom_instructions: [{ label: 'Init',
|
|
19
|
+
prompt: 'Be formal',
|
|
20
|
+
source_language: 'de' }])
|
|
21
|
+
begin
|
|
22
|
+
expect([rule.name, rule.language, rule.creation_time.class]).to eq([name, 'en', Time])
|
|
23
|
+
|
|
24
|
+
fetched = client.get_style_rule(rule.style_id)
|
|
25
|
+
expect([fetched.style_id, fetched.name]).to eq([rule.style_id, name])
|
|
26
|
+
expect(found_on_any_page?(rule.style_id) do |page|
|
|
27
|
+
client.get_all_style_rules(page: page, page_size: 25, detailed: true).map(&:style_id)
|
|
28
|
+
end).to be(true)
|
|
29
|
+
|
|
30
|
+
expect(client.update_style_rule_name(rule, "#{name}-renamed").name).to eq("#{name}-renamed")
|
|
31
|
+
expect(client.update_style_rule_configured_rules(rule, rules).style_id).to eq(rule.style_id)
|
|
32
|
+
|
|
33
|
+
instruction = client.create_style_rule_custom_instruction(rule, 'Label', 'Prompt',
|
|
34
|
+
source_language: 'de')
|
|
35
|
+
expect([instruction.id.class, instruction.label]).to eq([String, 'Label'])
|
|
36
|
+
found = client.get_style_rule_custom_instruction(rule, instruction)
|
|
37
|
+
expect(found.prompt).to eq('Prompt')
|
|
38
|
+
updated = client.update_style_rule_custom_instruction(rule, instruction.id, 'New Label',
|
|
39
|
+
'New Prompt', source_language: 'en')
|
|
40
|
+
expect(updated.label).to eq('New Label')
|
|
41
|
+
expect(client.delete_style_rule_custom_instruction(rule, instruction)).to be_nil
|
|
42
|
+
ensure
|
|
43
|
+
delete_quietly { client.delete_style_rule(rule) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL.document' do
|
|
9
|
+
include_context 'with a temporary directory'
|
|
10
|
+
|
|
11
|
+
it 'uploads, polls and downloads a .txt document' do
|
|
12
|
+
input, output = create_text_document(temp_dir)
|
|
13
|
+
|
|
14
|
+
DeepL.document.translate_document(input, output, 'EN', 'DE')
|
|
15
|
+
|
|
16
|
+
expect(File.size(output)).to be_positive
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL.translate' do
|
|
9
|
+
it 'sends POST /v2/translate and parses the result' do
|
|
10
|
+
result = DeepL.translate('proton beam', nil, 'DE')
|
|
11
|
+
|
|
12
|
+
expect(result).to be_a(DeepL::Resources::Text)
|
|
13
|
+
expect(result.text).to be_a(String)
|
|
14
|
+
expect(result.detected_source_language).not_to be_empty
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
# The import appears as a translation memory only after about a minute, and a run killed in that
|
|
9
|
+
# window leaves one memory behind.
|
|
10
|
+
describe 'DeepL::Client translation memories' do
|
|
11
|
+
include_context 'with a temporary directory'
|
|
12
|
+
|
|
13
|
+
let(:client) do
|
|
14
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:job_timeout_s) { 120 }
|
|
18
|
+
|
|
19
|
+
it 'sends the translation memory requests: import, upload, get, list, segments, export, delete' do
|
|
20
|
+
name = unique_name('translation-memory')
|
|
21
|
+
memory_id = nil
|
|
22
|
+
begin
|
|
23
|
+
created = client.create_translation_memory_import('example.tmx',
|
|
24
|
+
Fixtures::EXAMPLE_TMX.bytesize,
|
|
25
|
+
display_name: name)
|
|
26
|
+
expect([created.job_id.class, created.upload_url.class]).to eq([String, String])
|
|
27
|
+
|
|
28
|
+
client.upload_translation_memory_file(created, Fixtures::EXAMPLE_TMX)
|
|
29
|
+
import_job = client.wait_until_translation_memory_job_done(created.job_id,
|
|
30
|
+
timeout_s: job_timeout_s)
|
|
31
|
+
memory_id = import_job.result.translation_memory_id
|
|
32
|
+
expect([import_job.operation, import_job.status, memory_id.class])
|
|
33
|
+
.to eq(['import', 'completed', String])
|
|
34
|
+
|
|
35
|
+
fetched = client.get_translation_memory(memory_id)
|
|
36
|
+
expect([fetched.translation_memory_id, fetched.name]).to eq([memory_id, name])
|
|
37
|
+
expect(found_on_any_page?(memory_id) do |page|
|
|
38
|
+
client.list_translation_memories(page: page, page_size: 100).map(&:translation_memory_id)
|
|
39
|
+
end).to be(true)
|
|
40
|
+
|
|
41
|
+
segments = client.list_translation_memory_segments(memory_id)
|
|
42
|
+
expect(segments.segments).not_to be_empty
|
|
43
|
+
expect(segments.segments.first.source_segment_id).to be_a(String)
|
|
44
|
+
|
|
45
|
+
exported = client.create_translation_memory_export(memory_id)
|
|
46
|
+
export_job = client.wait_until_translation_memory_job_done(
|
|
47
|
+
client.get_translation_memory_job(exported.job_id), timeout_s: job_timeout_s
|
|
48
|
+
)
|
|
49
|
+
output = File.join(temp_dir, 'export.tmx')
|
|
50
|
+
client.download_translation_memory_export(export_job, output)
|
|
51
|
+
expect(File.read(output)).to include('<tmx')
|
|
52
|
+
ensure
|
|
53
|
+
delete_quietly { client.delete_translation_memory(memory_id) } unless memory_id.nil?
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2026 DeepL SE (https://www.deepl.com)
|
|
2
|
+
# Use of this source code is governed by an MIT
|
|
3
|
+
# license that can be found in the LICENSE file.
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
require_relative 'real_api_helper'
|
|
7
|
+
|
|
8
|
+
describe 'DeepL::Client#get_usage' do
|
|
9
|
+
let(:client) do
|
|
10
|
+
DeepL::Client.new(ENV.fetch('DEEPL_AUTH_KEY'), server_url: ENV.fetch('DEEPL_SERVER_URL', nil))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'sends GET /v2/usage and parses the usage' do
|
|
14
|
+
usage = client.get_usage
|
|
15
|
+
|
|
16
|
+
expect(usage.character.count).to be_an(Integer)
|
|
17
|
+
expect(usage.character.limit).to be_an(Integer)
|
|
18
|
+
expect(usage.any_limit_reached?).to be(true).or be(false)
|
|
19
|
+
end
|
|
20
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -3,60 +3,11 @@
|
|
|
3
3
|
# license that can be found in the LICENSE.md file.
|
|
4
4
|
# frozen_string_literal: true
|
|
5
5
|
|
|
6
|
-
# Coverage
|
|
6
|
+
# Coverage. It must start before the library is loaded.
|
|
7
7
|
require 'simplecov'
|
|
8
8
|
SimpleCov.start
|
|
9
9
|
|
|
10
10
|
require 'simplecov-cobertura'
|
|
11
11
|
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
|
12
12
|
|
|
13
|
-
# Load lib
|
|
14
13
|
require_relative '../lib/deepl'
|
|
15
|
-
require_relative 'integration_tests/integration_test_utils'
|
|
16
|
-
|
|
17
|
-
# Auto-load test helpers under spec/support
|
|
18
|
-
Dir[File.expand_path('support/**/*.rb', __dir__)].sort.each { |f| require f }
|
|
19
|
-
|
|
20
|
-
# Lib config
|
|
21
|
-
ENV['DEEPL_AUTH_KEY'] ||= 'TEST-TOKEN'
|
|
22
|
-
|
|
23
|
-
RSpec.configure do |config|
|
|
24
|
-
config.include ManagedGlossary
|
|
25
|
-
config.include ManagedStyleRule
|
|
26
|
-
config.include ManagedTranslationMemory
|
|
27
|
-
|
|
28
|
-
config.before(:each, :mock_server_only) do
|
|
29
|
-
skip 'Only runs on mock server' unless ENV.key?('DEEPL_MOCK_SERVER_PORT')
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
config.before(:each, :real_server_only) do
|
|
33
|
-
skip 'Only runs on real server' if ENV.key?('DEEPL_MOCK_SERVER_PORT')
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# General helpers
|
|
38
|
-
def build_deepl_api
|
|
39
|
-
DeepL::API.new(DeepL::Configuration.new)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Test helpers
|
|
43
|
-
|
|
44
|
-
def replace_env_preserving_deepl_vars
|
|
45
|
-
env_auth_key = ENV.fetch('DEEPL_AUTH_KEY', false)
|
|
46
|
-
env_server_url = ENV.fetch('DEEPL_SERVER_URL', false)
|
|
47
|
-
env_mock_server_port = ENV.fetch('DEEPL_MOCK_SERVER_PORT', false)
|
|
48
|
-
tmp_env = ENV.to_hash
|
|
49
|
-
ENV.clear
|
|
50
|
-
ENV['DEEPL_AUTH_KEY'] = (env_auth_key || 'VALID')
|
|
51
|
-
ENV['DEEPL_SERVER_URL'] = (env_server_url || '')
|
|
52
|
-
ENV['DEEPL_MOCK_SERVER_PORT'] = (env_mock_server_port || '')
|
|
53
|
-
tmp_env
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def replace_env_preserving_deepl_vars_except_mock_server
|
|
57
|
-
env_auth_key = ENV.fetch('DEEPL_AUTH_KEY', false)
|
|
58
|
-
tmp_env = ENV.to_hash
|
|
59
|
-
ENV.clear
|
|
60
|
-
ENV['DEEPL_AUTH_KEY'] = (env_auth_key || 'VALID')
|
|
61
|
-
tmp_env
|
|
62
|
-
end
|