deepl-rb 3.7.0 → 3.8.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +3 -1
  3. data/CHANGELOG.md +17 -1
  4. data/Gemfile +0 -2
  5. data/README.md +12 -12
  6. data/VERSION +1 -1
  7. data/deepl-rb.gemspec +27 -22
  8. data/lib/deepl/requests/rephrase.rb +3 -2
  9. data/lib/deepl/requests/translate.rb +2 -2
  10. data/lib/deepl.rb +7 -4
  11. data/lib/version.rb +1 -1
  12. data/spec/api/deepl_spec.rb +134 -332
  13. data/spec/integration_tests/document_api_spec.rb +4 -18
  14. data/spec/integration_tests/document_error_paths_spec.rb +33 -0
  15. data/spec/integration_tests/glossary_api_spec.rb +114 -0
  16. data/spec/integration_tests/glossary_error_paths_spec.rb +107 -0
  17. data/spec/integration_tests/languages_api_spec.rb +54 -0
  18. data/spec/integration_tests/languages_error_paths_spec.rb +25 -0
  19. data/spec/integration_tests/rephrase_api_spec.rb +90 -0
  20. data/spec/integration_tests/rephrase_error_paths_spec.rb +53 -0
  21. data/spec/integration_tests/smoke_test_spec.rb +24 -0
  22. data/spec/integration_tests/style_rule_api_spec.rb +1 -19
  23. data/spec/integration_tests/style_rule_error_paths_spec.rb +45 -0
  24. data/spec/integration_tests/translate_api_spec.rb +98 -0
  25. data/spec/integration_tests/translate_error_paths_spec.rb +48 -0
  26. data/spec/integration_tests/translation_memory_api_spec.rb +1 -17
  27. data/spec/integration_tests/translation_memory_error_paths_spec.rb +19 -0
  28. data/spec/integration_tests/usage_api_spec.rb +29 -0
  29. data/spec/integration_tests/usage_error_paths_spec.rb +18 -0
  30. data/spec/requests/glossary/create_spec.rb +0 -21
  31. data/spec/requests/glossary/destroy_spec.rb +0 -39
  32. data/spec/requests/glossary/entries_spec.rb +0 -35
  33. data/spec/requests/glossary/find_spec.rb +0 -40
  34. data/spec/requests/glossary/language_pairs_spec.rb +0 -13
  35. data/spec/requests/glossary/list_spec.rb +0 -27
  36. data/spec/requests/languages_spec.rb +0 -41
  37. data/spec/requests/rephrase_spec.rb +13 -139
  38. data/spec/requests/style_rule/create_custom_instruction_spec.rb +0 -24
  39. data/spec/requests/style_rule/create_spec.rb +0 -16
  40. data/spec/requests/style_rule/destroy_custom_instruction_spec.rb +0 -26
  41. data/spec/requests/style_rule/destroy_spec.rb +0 -27
  42. data/spec/requests/style_rule/find_custom_instruction_spec.rb +0 -27
  43. data/spec/requests/style_rule/find_spec.rb +0 -28
  44. data/spec/requests/style_rule/list_spec.rb +0 -31
  45. data/spec/requests/style_rule/update_configured_rules_spec.rb +0 -21
  46. data/spec/requests/style_rule/update_custom_instruction_spec.rb +0 -26
  47. data/spec/requests/style_rule/update_spec.rb +0 -19
  48. data/spec/requests/translate_spec.rb +8 -217
  49. data/spec/requests/translation_memory/list_spec.rb +0 -34
  50. data/spec/requests/usage_spec.rb +0 -16
  51. data/spec/resources/custom_instruction_spec.rb +32 -0
  52. data/spec/resources/style_rule_spec.rb +68 -0
  53. data/spec/spec_helper.rb +15 -45
  54. data/spec/support/live_mock_server.rb +12 -0
  55. data/spec/support/managed_glossary.rb +17 -0
  56. data/spec/support/managed_style_rule.rb +17 -0
  57. data/spec/support/managed_translation_memory.rb +7 -0
  58. metadata +23 -21
  59. data/spec/fixtures/vcr_cassettes/deepl_document.yml +0 -95
  60. data/spec/fixtures/vcr_cassettes/deepl_document_download.yml +0 -1214
  61. data/spec/fixtures/vcr_cassettes/deepl_glossaries.yml +0 -1163
  62. data/spec/fixtures/vcr_cassettes/deepl_languages.yml +0 -54
  63. data/spec/fixtures/vcr_cassettes/deepl_rephrase.yml +0 -87
  64. data/spec/fixtures/vcr_cassettes/deepl_translate.yml +0 -358
  65. data/spec/fixtures/vcr_cassettes/deepl_usage.yml +0 -129
  66. data/spec/fixtures/vcr_cassettes/glossaries.yml +0 -1702
  67. data/spec/fixtures/vcr_cassettes/languages.yml +0 -229
  68. data/spec/fixtures/vcr_cassettes/rephrase_texts.yml +0 -401
  69. data/spec/fixtures/vcr_cassettes/style_rules.yml +0 -92
  70. data/spec/fixtures/vcr_cassettes/style_rules_crud.yml +0 -926
  71. data/spec/fixtures/vcr_cassettes/translate_texts.yml +0 -10630
  72. data/spec/fixtures/vcr_cassettes/translation_memories.yml +0 -74
  73. data/spec/fixtures/vcr_cassettes/usage.yml +0 -171
@@ -24,31 +24,4 @@ describe DeepL::Requests::StyleRule::Destroy do
24
24
  end
25
25
  end
26
26
  end
27
-
28
- describe '#request' do
29
- around do |example|
30
- VCR.use_cassette('style_rules_crud') { example.call }
31
- end
32
-
33
- context 'when performing a valid request' do
34
- subject(:destroy) { described_class.new(api, new_rule.style_id) }
35
-
36
- let(:new_rule) do
37
- DeepL::Requests::StyleRule::Create.new(api, 'Destroy Test', 'en').request
38
- end
39
-
40
- it 'returns the deleted style rule id' do
41
- response = destroy.request
42
- expect(response).to eq(new_rule.style_id)
43
- end
44
- end
45
-
46
- context 'when deleting a non existing style rule with an invalid id' do
47
- let(:style_id) { 'invalid-uuid' }
48
-
49
- it 'raises an error' do
50
- expect { destroy.request }.to raise_error(DeepL::Exceptions::Error)
51
- end
52
- end
53
- end
54
27
  end
@@ -26,31 +26,4 @@ describe DeepL::Requests::StyleRule::FindCustomInstruction do
26
26
  end
27
27
  end
28
28
  end
29
-
30
- describe '#request' do
31
- around do |example|
32
- VCR.use_cassette('style_rules_crud') { example.call }
33
- end
34
-
35
- context 'when performing a valid request' do
36
- subject(:find_instruction) do
37
- described_class.new(api, new_rule.style_id, new_instruction.id)
38
- end
39
-
40
- let(:new_rule) do
41
- DeepL::Requests::StyleRule::Create.new(api, 'Find Instruction Test', 'en').request
42
- end
43
- let(:new_instruction) do
44
- DeepL::Requests::StyleRule::CreateCustomInstruction.new(
45
- api, new_rule.style_id, 'Test', 'Test prompt'
46
- ).request
47
- end
48
-
49
- it 'returns a custom instruction object' do
50
- instruction = find_instruction.request
51
- expect(instruction).to be_a(DeepL::Resources::CustomInstruction)
52
- expect(instruction.id).to eq(new_instruction.id)
53
- end
54
- end
55
- end
56
29
  end
@@ -25,32 +25,4 @@ describe DeepL::Requests::StyleRule::Find do
25
25
  end
26
26
  end
27
27
  end
28
-
29
- describe '#request' do
30
- around do |example|
31
- VCR.use_cassette('style_rules_crud') { example.call }
32
- end
33
-
34
- context 'when performing a valid request' do
35
- subject(:style_rule_find) do
36
- new_rule = DeepL::Requests::StyleRule::Create.new(api, 'Find Test', 'en').request
37
- described_class.new(api, new_rule.style_id, options)
38
- end
39
-
40
- it 'returns a style rule object' do
41
- style_rule = style_rule_find.request
42
- expect(style_rule).to be_a(DeepL::Resources::StyleRule)
43
- expect(style_rule.style_id).to be_a(String)
44
- expect(style_rule.name).to be_a(String)
45
- end
46
- end
47
-
48
- context 'when requesting a non existing style rule with an invalid id' do
49
- let(:style_id) { 'invalid-uuid' }
50
-
51
- it 'raises an error' do
52
- expect { style_rule_find.request }.to raise_error(DeepL::Exceptions::Error)
53
- end
54
- end
55
- end
56
28
  end
@@ -24,35 +24,4 @@ describe DeepL::Requests::StyleRule::List do
24
24
  end
25
25
  end
26
26
  end
27
-
28
- describe '#request' do
29
- around do |example|
30
- VCR.use_cassette('style_rules') { example.call }
31
- end
32
-
33
- context 'when requesting a list of all style rules' do
34
- it 'returns an array of style rules' do
35
- style_rules = style_rule_list.request
36
- expect(style_rules).to be_an(Array)
37
- expect(style_rules).not_to be_empty
38
- expect(style_rules.first).to be_a(DeepL::Resources::StyleRule)
39
- expect(style_rules.first.style_id).to be_a(String)
40
- expect(style_rules.first.name).to be_a(String)
41
- end
42
- end
43
-
44
- context 'when performing a bad request' do
45
- context 'when using an invalid token' do
46
- let(:api) do
47
- api = build_deepl_api
48
- api.configuration.auth_key = 'invalid'
49
- api
50
- end
51
-
52
- it 'raises an authorization failed error' do
53
- expect { style_rule_list.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
54
- end
55
- end
56
- end
57
- end
58
27
  end
@@ -28,25 +28,4 @@ describe DeepL::Requests::StyleRule::UpdateConfiguredRules do
28
28
  end
29
29
  end
30
30
  end
31
-
32
- describe '#request' do
33
- around do |example|
34
- VCR.use_cassette('style_rules_crud') { example.call }
35
- end
36
-
37
- context 'when performing a valid request' do
38
- subject(:update_configured_rules) do
39
- described_class.new(api, new_rule.style_id, configured_rules)
40
- end
41
-
42
- let(:new_rule) do
43
- DeepL::Requests::StyleRule::Create.new(api, 'Configured Rules Test', 'en').request
44
- end
45
-
46
- it 'returns a style rule object' do
47
- style_rule = update_configured_rules.request
48
- expect(style_rule).to be_a(DeepL::Resources::StyleRule)
49
- end
50
- end
51
- end
52
31
  end
@@ -29,30 +29,4 @@ describe DeepL::Requests::StyleRule::UpdateCustomInstruction do
29
29
  end
30
30
  end
31
31
  end
32
-
33
- describe '#request' do
34
- around do |example|
35
- VCR.use_cassette('style_rules_crud') { example.call }
36
- end
37
-
38
- context 'when performing a valid request' do
39
- subject(:update_instruction) do
40
- described_class.new(api, new_rule.style_id, new_instruction.id, label, prompt)
41
- end
42
-
43
- let(:new_rule) do
44
- DeepL::Requests::StyleRule::Create.new(api, 'Update Instruction Test', 'en').request
45
- end
46
- let(:new_instruction) do
47
- DeepL::Requests::StyleRule::CreateCustomInstruction.new(
48
- api, new_rule.style_id, 'Original', 'Original prompt'
49
- ).request
50
- end
51
-
52
- it 'returns a custom instruction object' do
53
- instruction = update_instruction.request
54
- expect(instruction).to be_a(DeepL::Resources::CustomInstruction)
55
- end
56
- end
57
- end
58
32
  end
@@ -26,23 +26,4 @@ describe DeepL::Requests::StyleRule::Update do
26
26
  end
27
27
  end
28
28
  end
29
-
30
- describe '#request' do
31
- around do |example|
32
- VCR.use_cassette('style_rules_crud') { example.call }
33
- end
34
-
35
- context 'when performing a valid request' do
36
- subject(:update) { described_class.new(api, new_rule.style_id, 'Updated Name') }
37
-
38
- let(:new_rule) do
39
- DeepL::Requests::StyleRule::Create.new(api, 'Update Test', 'en').request
40
- end
41
-
42
- it 'returns a style rule object' do
43
- style_rule = update.request
44
- expect(style_rule).to be_a(DeepL::Resources::StyleRule)
45
- end
46
- end
47
- end
48
29
  end
@@ -266,226 +266,17 @@ describe DeepL::Requests::Translate do
266
266
  expect(request.options[:custom_instructions]).to eq(['Use informal language', 'Be concise'])
267
267
  end
268
268
  end
269
- end
270
-
271
- describe '#request' do
272
- around do |example|
273
- VCR.use_cassette('translate_texts') { example.call }
274
- end
275
-
276
- context 'when performing a valid request with one text' do
277
- it 'returns a text object' do
278
- text = translate.request
279
-
280
- expect(text).to be_a(DeepL::Resources::Text)
281
- expect(text.text).to eq('Texto de muestra')
282
- expect(text.detected_source_language).to eq('EN')
283
- end
284
- end
285
-
286
- context 'when performing a valid request with multiple texts' do
287
- let(:text) { %w[Sample Word] }
288
-
289
- it 'returns a text object' do
290
- texts = translate.request
291
-
292
- expect(texts).to be_a(Array)
293
- expect(texts.first.text).to eq('Muestra')
294
- expect(texts.first.detected_source_language).to eq('EN')
295
-
296
- expect(texts.last.text).to eq('Palabra')
297
- expect(texts.last.detected_source_language).to eq('EN')
298
- end
299
- end
300
-
301
- context 'when performing a valid request with tag handling' do
302
- let(:text) { '<p>Sample text</p>' }
303
- let(:options) { { tag_handling: 'xml' } }
304
-
305
- it 'returns a text object' do
306
- text = translate.request
307
-
308
- expect(text).to be_a(DeepL::Resources::Text)
309
- expect(text.text).to eq('<p>Texto de muestra</p>')
310
- expect(text.detected_source_language).to eq('EN')
311
- end
312
- end
313
-
314
- context 'when performing a valid request and passing a variable' do
315
- let(:text) { 'Welcome and <code>Hello great World</code> Good Morning!' }
316
- let(:options) { { tag_handling: 'xml', ignore_tags: %w[code span] } }
317
-
318
- it 'returns a text object' do
319
- text = translate.request
320
-
321
- expect(text).to be_a(DeepL::Resources::Text)
322
- expect(text.text).to eq('Bienvenido y <code>Hello great World</code> ¡Buenos días!')
323
- expect(text.detected_source_language).to eq('EN')
324
- end
325
- end
326
-
327
- context 'when performing a valid request with an HTML document' do
328
- let(:text) do
329
- <<~XML
330
- <document>
331
- <meta>
332
- <title>A document's title</title>
333
- </meta>
334
- <content>
335
- <par>This is the first sentence. Followed by a second one.</par>
336
- <par>This is the third sentence.</par>
337
- </content>
338
- </document>
339
- XML
340
- end
341
- let(:options) do
342
- {
343
- tag_handling: 'xml',
344
- split_sentences: 'nonewlines',
345
- outline_detection: false,
346
- splitting_tags: %w[title par]
347
- }
348
- end
349
-
350
- it 'returns a text object' do
351
- text = translate.request
352
-
353
- expect(text).to be_a(DeepL::Resources::Text)
354
- expect(text.text).to eq(
355
- <<~XML
356
- <document>
357
- <meta>
358
- <title>Título de un documento</title>
359
- </meta>
360
- <content>
361
- <par>Es la primera frase. Seguido de una segunda.</par>
362
- <par>Esta es la tercera frase.</par>
363
- </content>
364
- </document>
365
- XML
366
- )
367
- expect(text.detected_source_language).to eq('EN')
368
- end
369
- end
370
-
371
- context 'when performing a valid request with context' do
372
- let(:text) { 'That is hot!' }
373
-
374
- context 'when context is empty' do
375
- let(:options) { { context: '' } }
376
-
377
- it 'translates correctly with empty context' do
378
- res = translate.request
379
- expect(res).to be_a(DeepL::Resources::Text)
380
- expect(res.text).to eq('¡Eso está caliente!')
381
- end
382
- end
383
269
 
384
- context 'when context is set' do
385
- let(:options) { { context: 'He did not like the jalapenos in his meal.' } }
386
-
387
- it 'translates correctly with context taken into account' do
388
- res = translate.request
389
- expect(res).to be_a(DeepL::Resources::Text)
390
- expect(res.text).to eq('¡Eso es picante!')
391
- end
392
- end
393
- end
394
-
395
- context 'when performing a request with a model type' do
396
- let(:target_lang) { 'DE' }
397
-
398
- %w[quality_optimized latency_optimized prefer_quality_optimized].each do |model_type_str|
399
- it "translates correctly with #{model_type_str} models" do
400
- options = { model_type: model_type_str }
401
- translate = described_class.new(api, text, source_lang, target_lang, options)
402
- res = translate.request
403
- expect(res).to be_a(DeepL::Resources::Text)
404
- expect(res.model_type_used).not_to be_nil
405
- end
406
- end
407
- end
408
-
409
- context 'when performing a request with extra_body_parameters' do
410
- it 'allows extra parameters to override standard parameters' do
411
- extra_options = { extra_body_parameters: { target_lang: 'FR', debug: '1' } }
412
- translate = described_class.new(api, text, source_lang, target_lang, extra_options)
413
- res = translate.request
414
-
415
- expect(res).to be_a(DeepL::Resources::Text)
416
- expect(res.text).to eq('Texte modèle')
417
- expect(res.detected_source_language).to eq('EN')
418
- end
419
- end
420
-
421
- context 'when performing a request with custom_instructions' do
422
- let(:text) { 'Hello world' }
423
- let(:target_lang) { 'DE' }
424
-
425
- it 'includes custom_instructions in the payload' do
426
- options = { custom_instructions: ['Use formal language', 'Be concise'] }
427
- translate = described_class.new(api, text, source_lang, target_lang, options)
428
-
429
- # Verify the options are properly stored
430
- expect(translate.options[:custom_instructions]).to eq(['Use formal language', 'Be concise'])
270
+ context 'when passing additional headers' do
271
+ it 'merges the headers into the request headers' do
272
+ request = described_class.new(api, nil, nil, nil, {},
273
+ { 'X-DeepL-Reporting-Tag' => 'my-tag' })
274
+ expect(request.send(:headers)).to include('X-DeepL-Reporting-Tag' => 'my-tag')
431
275
  end
432
- end
433
-
434
- context 'when performing a request with tag_handling_version' do
435
- let(:text) { '<p>Hello world</p>' }
436
- let(:target_lang) { 'DE' }
437
-
438
- %w[v1 v2].each do |version|
439
- it "translates correctly with tag_handling_version #{version}" do
440
- options = { tag_handling: 'html', tag_handling_version: version }
441
- translate = described_class.new(api, text, source_lang, target_lang, options)
442
- res = translate.request
443
-
444
- expect(res).to be_a(DeepL::Resources::Text)
445
- expect(res.text).not_to be_nil
446
- expect(res.text).not_to be_empty
447
- end
448
- end
449
- end
450
-
451
- context 'when performing a bad request' do
452
- context 'when using an invalid token' do
453
- let(:api) do
454
- api = build_deepl_api
455
- api.configuration.auth_key = 'invalid'
456
- api
457
- end
458
-
459
- it 'raises an unauthorized error' do
460
- expect { translate.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
461
- end
462
- end
463
-
464
- context 'when using an invalid text' do
465
- let(:text) { nil }
466
-
467
- it 'raises a bad request error' do
468
- message = "Invalid request: Expected 'text' parameter to be an array of strings"
469
- expect { translate.request }.to raise_error(DeepL::Exceptions::BadRequest, message)
470
- end
471
- end
472
-
473
- context 'when using an invalid target language' do
474
- let(:target_lang) { nil }
475
-
476
- it 'raises a bad request error' do
477
- message = "Value for 'target_lang' not supported."
478
- expect { translate.request }.to raise_error(DeepL::Exceptions::BadRequest, message)
479
- end
480
- end
481
- end
482
-
483
- context 'when performing a request with too many texts' do
484
- let(:text) { Array.new(10_000) { |i| "This is the sentence number #{i}" } }
485
276
 
486
- it 'raises a request entity too large error' do
487
- expect { translate.request }.to raise_error(DeepL::Exceptions::RequestEntityTooLarge,
488
- /request size has reached the supported limit/)
277
+ it 'defaults to no additional headers' do
278
+ request = described_class.new(api, nil, nil, nil)
279
+ expect(request.send(:headers).keys).to contain_exactly('Authorization', 'User-Agent')
489
280
  end
490
281
  end
491
282
  end
@@ -24,38 +24,4 @@ describe DeepL::Requests::TranslationMemory::List do
24
24
  end
25
25
  end
26
26
  end
27
-
28
- describe '#request' do
29
- around do |example|
30
- VCR.use_cassette('translation_memories') { example.call }
31
- end
32
-
33
- context 'when requesting a list of all translation memories' do
34
- it 'returns an array of translation memories' do
35
- translation_memories = translation_memory_list.request
36
- expect(translation_memories).to be_an(Array)
37
- expect(translation_memories).not_to be_empty
38
- expect(translation_memories.first).to be_a(DeepL::Resources::TranslationMemory)
39
- expect(translation_memories.first.translation_memory_id).to be_a(String)
40
- expect(translation_memories.first.name).to be_a(String)
41
- expect(translation_memories.first.source_language).to be_a(String)
42
- expect(translation_memories.first.target_languages).to be_an(Array)
43
- expect(translation_memories.first.segment_count).to be_an(Integer)
44
- end
45
- end
46
-
47
- context 'when performing a bad request' do
48
- context 'when using an invalid token' do
49
- let(:api) do
50
- api = build_deepl_api
51
- api.configuration.auth_key = 'invalid'
52
- api
53
- end
54
-
55
- it 'raises an authorization failed error' do
56
- expect { translation_memory_list.request }.to raise_error(DeepL::Exceptions::AuthorizationFailed)
57
- end
58
- end
59
- end
60
- end
61
27
  end
@@ -24,20 +24,4 @@ describe DeepL::Requests::Usage do
24
24
  end
25
25
  end
26
26
  end
27
-
28
- describe '#request' do
29
- around do |example|
30
- VCR.use_cassette('usage') { example.call }
31
- end
32
-
33
- context 'when performing a valid request' do
34
- it 'returns an usage object' do
35
- usage = usage_req.request
36
-
37
- expect(usage).to be_a(DeepL::Resources::Usage)
38
- expect(usage.character_count).to be_a(Numeric)
39
- expect(usage.character_limit).to be_a(Numeric)
40
- end
41
- end
42
- end
43
27
  end
@@ -0,0 +1,32 @@
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 'spec_helper'
7
+
8
+ describe DeepL::Resources::CustomInstruction do
9
+ subject(:custom_instruction) do
10
+ described_class.new({
11
+ 'id' => 'ci-1',
12
+ 'label' => 'Formal',
13
+ 'prompt' => 'Always use formal language',
14
+ 'source_language' => 'en'
15
+ })
16
+ end
17
+
18
+ describe '#initialize' do
19
+ context 'when building a basic object' do
20
+ it 'creates a resource' do
21
+ expect(custom_instruction).to be_a(described_class)
22
+ end
23
+
24
+ it 'assigns the attributes' do
25
+ expect(custom_instruction.id).to eq('ci-1')
26
+ expect(custom_instruction.label).to eq('Formal')
27
+ expect(custom_instruction.prompt).to eq('Always use formal language')
28
+ expect(custom_instruction.source_language).to eq('en')
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
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 'spec_helper'
7
+
8
+ describe DeepL::Resources::StyleRule do
9
+ subject(:style_rule) do
10
+ described_class.new({
11
+ 'style_id' => 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4',
12
+ 'name' => 'Default Style Rule',
13
+ 'creation_time' => '2025-01-01T00:00:00Z',
14
+ 'updated_time' => '2025-01-02T00:00:00Z',
15
+ 'language' => 'en',
16
+ 'version' => 1
17
+ }, nil, nil)
18
+ end
19
+
20
+ describe '#initialize' do
21
+ context 'when building a basic object' do
22
+ it 'creates a resource' do
23
+ expect(style_rule).to be_a(described_class)
24
+ end
25
+
26
+ it 'assigns the attributes' do
27
+ expect(style_rule.style_id).to eq('dca2e053-8ae5-45e6-a0d2-881156e7f4e4')
28
+ expect(style_rule.name).to eq('Default Style Rule')
29
+ expect(style_rule.language).to eq('en')
30
+ expect(style_rule.version).to eq(1)
31
+ expect(style_rule.creation_time).to eq(Time.parse('2025-01-01T00:00:00Z'))
32
+ expect(style_rule.updated_time).to eq(Time.parse('2025-01-02T00:00:00Z'))
33
+ expect(style_rule.configured_rules).to be_nil
34
+ expect(style_rule.custom_instructions).to be_nil
35
+ end
36
+ end
37
+
38
+ context 'when building an object with configured rules and custom instructions' do
39
+ subject(:style_rule) do
40
+ described_class.new({
41
+ 'style_id' => 'dca2e053-8ae5-45e6-a0d2-881156e7f4e4',
42
+ 'name' => 'Detailed Style Rule',
43
+ 'language' => 'en',
44
+ 'version' => 1,
45
+ 'configured_rules' => {
46
+ 'dates_and_times' => { 'calendar_era' => 'use_bc_and_ad' }
47
+ },
48
+ 'custom_instructions' => [
49
+ { 'id' => 'ci-1', 'label' => 'Test', 'prompt' => 'Be formal' }
50
+ ]
51
+ }, nil, nil)
52
+ end
53
+
54
+ it 'maps configured_rules into a ConfiguredRules resource' do
55
+ expect(style_rule.configured_rules).to be_a(DeepL::Resources::ConfiguredRules)
56
+ expect(style_rule.configured_rules.dates_and_times)
57
+ .to eq({ 'calendar_era' => 'use_bc_and_ad' })
58
+ end
59
+
60
+ it 'maps custom_instructions into an array of CustomInstruction resources' do
61
+ expect(style_rule.custom_instructions).to all(be_a(DeepL::Resources::CustomInstruction))
62
+ expect(style_rule.custom_instructions.first.id).to eq('ci-1')
63
+ expect(style_rule.custom_instructions.first.label).to eq('Test')
64
+ expect(style_rule.custom_instructions.first.prompt).to eq('Be formal')
65
+ end
66
+ end
67
+ end
68
+ end