txbr 1.1.1 → 2.0.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.
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'support/standard_setup'
3
+ require 'json'
3
4
 
4
5
  describe Txbr::EmailTemplate do
5
6
  include_context 'standard setup'
@@ -14,7 +15,8 @@ describe Txbr::EmailTemplate do
14
15
  {% assign project_slug = "my_project" %}
15
16
  {% assign resource_slug = "my_resource" %}
16
17
  {% assign translation_enabled = true %}
17
- {% connected_content http://my_strings_api.com/ :save strings %}
18
+ {% connected_content http://my_strings_api.com?project_slug={{project_slug}}&resource_slug={{resource_slug}} :save strings %}
19
+ {% connected_content http://my_strings_api.com?project_slug=my_project&resource_slug=my_footer_resource :save footer %}
18
20
  </head>
19
21
  <body>
20
22
  {{strings.header | default: 'Buy our stuff!'}}
@@ -23,6 +25,7 @@ describe Txbr::EmailTemplate do
23
25
  {% else %}
24
26
  {{strings.no_discount | default: 'You get no discount'}}
25
27
  {% endif %}
28
+ {{footer.company | default: 'Megamarketing Corp'}}
26
29
  </body>
27
30
  </html>
28
31
  HTML
@@ -33,7 +36,7 @@ describe Txbr::EmailTemplate do
33
36
  {% assign project_slug = "my_project" %}
34
37
  {% assign resource_slug = "my_resource" %}
35
38
  {% assign translation_enabled = true %}
36
- {% connected_content http://my_strings_api.com/ :save strings %}
39
+ {% connected_content http://my_strings_api.com?project_slug={{project_slug}}&resource_slug={{resource_slug}} :save strings %}
37
40
  {{strings.meta.subject_line | default: 'You lucky duck maybe'}}
38
41
  HTML
39
42
  end
@@ -43,7 +46,7 @@ describe Txbr::EmailTemplate do
43
46
  {% assign project_slug = "my_project" %}
44
47
  {% assign resource_slug = "my_resource" %}
45
48
  {% assign translation_enabled = true %}
46
- {% connected_content http://my_strings_api.com/ :save strings %}
49
+ {% connected_content http://my_strings_api.com?project_slug={{project_slug}}&resource_slug={{resource_slug}} :save strings %}
47
50
  {{strings.meta.preheader | default: 'Our stuff is the bomb and you should buy it.'}}
48
51
  HTML
49
52
  end
@@ -53,7 +56,7 @@ describe Txbr::EmailTemplate do
53
56
  [{
54
57
  request: {
55
58
  verb: 'get',
56
- url: Txbr::BrazeApi::TEMPLATE_INFO_PATH,
59
+ url: Txbr::EmailTemplatesApi::TEMPLATE_DETAILS_PATH,
57
60
  params: { email_template_id: email_template_id }
58
61
  },
59
62
  response: {
@@ -69,10 +72,9 @@ describe Txbr::EmailTemplate do
69
72
  end
70
73
 
71
74
  it 'extracts and groups all strings with the same project, resource, and prefix' do
72
- resources = email_template.each_resource.to_a
73
- expect(resources.size).to eq(1)
74
-
75
- resource = resources.first
75
+ resource = email_template.each_resource.to_a.first
76
+ expect(resource.tx_resource.project_slug).to eq('my_project')
77
+ expect(resource.tx_resource.resource_slug).to eq('my_resource')
76
78
 
77
79
  # notice how it combined strings from the subject, preheader,
78
80
  # and template (i.e. HTML body)
@@ -96,6 +98,16 @@ describe Txbr::EmailTemplate do
96
98
  expect(tx_resource.type).to eq(project.strings_format)
97
99
  end
98
100
 
101
+ it 'constructs a separate resource for the footer' do
102
+ footer = email_template.each_resource.to_a.last
103
+ expect(footer.tx_resource.project_slug).to eq('my_project')
104
+ expect(footer.tx_resource.resource_slug).to eq('my_footer_resource')
105
+
106
+ expect(footer.phrases).to eq([
107
+ { 'key' => 'company', 'string' => 'Megamarketing Corp' }
108
+ ])
109
+ end
110
+
99
111
  context 'with translations disabled for the subject' do
100
112
  let(:subject_html) do
101
113
  super().tap do |subj|
@@ -120,9 +132,9 @@ describe Txbr::EmailTemplate do
120
132
  end
121
133
  end
122
134
 
123
- it 'includes two resources' do
135
+ it 'includes the additional resource' do
124
136
  resources = email_template.each_resource.to_a
125
- expect(resources.size).to eq(2)
137
+ expect(resources.size).to eq(3)
126
138
 
127
139
  expect(resources.first.phrases).to_not(
128
140
  include({ 'key' => 'meta.subject_line', 'string' => 'You lucky duck maybe' })
@@ -131,6 +143,9 @@ describe Txbr::EmailTemplate do
131
143
  expect(resources.last.phrases).to eq(
132
144
  [{ 'key' => 'meta.subject_line', 'string' => 'You lucky duck maybe' }]
133
145
  )
146
+
147
+ expect(resources.last.tx_resource.project_slug).to eq('my_project')
148
+ expect(resources.last.tx_resource.resource_slug).to eq('my_other_resource')
134
149
  end
135
150
  end
136
151
  end
@@ -1,55 +1,18 @@
1
1
  require 'spec_helper'
2
2
  require 'support/fake_connection'
3
+ require 'shared_examples/api_errors'
3
4
 
4
- describe Txbr::BrazeApi do
5
+ require 'json'
6
+
7
+ describe Txbr::EmailTemplatesApi do
5
8
  let(:api_key) { 'abc123' }
6
9
  let(:api_url) { 'https://somewhere.braze.com' }
7
10
  let(:connection) { FakeConnection.new(interactions) }
8
- let(:client) { described_class.new(api_key, api_url, connection: connection) }
9
-
10
- shared_examples 'a client request that handles errors' do
11
- context 'when the resource is not found' do
12
- let(:interactions) do
13
- super().tap do |inter|
14
- inter[0][:response][:status] = 404
15
- end
16
- end
17
-
18
- it 'raises a not found error' do
19
- expect { subject }.to raise_error(Txbr::BrazeNotFoundError)
20
- end
21
- end
22
-
23
- context 'when the request is unauthorized' do
24
- let(:interactions) do
25
- super().tap do |inter|
26
- inter.unshift(
27
- request: inter[0][:request],
28
- response: { status: 401 }
29
- )
30
- end
31
- end
32
-
33
- it 'raises an unauthorized error' do
34
- expect { subject }.to raise_error(Txbr::BrazeUnauthorizedError)
35
- end
36
- end
37
-
38
- context 'when some other bad thing happens' do
39
- let(:interactions) do
40
- super().tap do |inter|
41
- inter[0][:response][:status] = 500
42
- end
43
- end
44
-
45
- it 'raises a generic error' do
46
- expect { subject }.to raise_error(Txbr::BrazeApiError)
47
- end
48
- end
49
- end
11
+ let(:braze_api) { Txbr::BrazeApi.new(api_key, api_url, connection: connection) }
12
+ let(:client) { described_class.new(braze_api) }
50
13
 
51
- describe '#each_email_template' do
52
- subject { client.each_email_template.to_a }
14
+ describe '#each' do
15
+ subject { client.each.to_a }
53
16
 
54
17
  before do
55
18
  stub_const("#{described_class.name}::TEMPLATE_BATCH_SIZE", 1)
@@ -78,8 +41,8 @@ describe Txbr::BrazeApi do
78
41
  it_behaves_like 'a client request that handles errors'
79
42
  end
80
43
 
81
- describe '#get_email_template_details' do
82
- subject { client.get_email_template_details(email_template_id: email_template_id) }
44
+ describe '#details' do
45
+ subject { client.details(email_template_id: email_template_id) }
83
46
  let(:email_template_id) { 'abc123' }
84
47
 
85
48
  let(:details) do
@@ -93,7 +56,7 @@ describe Txbr::BrazeApi do
93
56
 
94
57
  let(:interactions) do
95
58
  [{
96
- request: { verb: 'get', url: described_class::TEMPLATE_INFO_PATH, params: { email_template_id: email_template_id } },
59
+ request: { verb: 'get', url: described_class::TEMPLATE_DETAILS_PATH, params: { email_template_id: email_template_id } },
97
60
  response: { status: 200, body: details.to_json }
98
61
  }]
99
62
  end
@@ -0,0 +1,40 @@
1
+ shared_examples 'a client request that handles errors' do
2
+ context 'when the resource is not found' do
3
+ let(:interactions) do
4
+ super().tap do |inter|
5
+ inter[0][:response][:status] = 404
6
+ end
7
+ end
8
+
9
+ it 'raises a not found error' do
10
+ expect { subject }.to raise_error(Txbr::BrazeNotFoundError)
11
+ end
12
+ end
13
+
14
+ context 'when the request is unauthorized' do
15
+ let(:interactions) do
16
+ super().tap do |inter|
17
+ inter.unshift(
18
+ request: inter[0][:request],
19
+ response: { status: 401 }
20
+ )
21
+ end
22
+ end
23
+
24
+ it 'raises an unauthorized error' do
25
+ expect { subject }.to raise_error(Txbr::BrazeUnauthorizedError)
26
+ end
27
+ end
28
+
29
+ context 'when some other bad thing happens' do
30
+ let(:interactions) do
31
+ super().tap do |inter|
32
+ inter[0][:response][:status] = 500
33
+ end
34
+ end
35
+
36
+ it 'raises a generic error' do
37
+ expect { subject }.to raise_error(Txbr::BrazeApiError)
38
+ end
39
+ end
40
+ end
@@ -10,15 +10,21 @@ describe Txbr::Uploader do
10
10
  [{
11
11
  request: {
12
12
  verb: 'get',
13
- url: Txbr::BrazeApi::TEMPLATE_LIST_PATH,
14
- params: { offset: 1, limit: Txbr::BrazeApi::TEMPLATE_BATCH_SIZE }
13
+ url: Txbr::EmailTemplatesApi::TEMPLATE_LIST_PATH,
14
+ params: { offset: 1, limit: Txbr::EmailTemplatesApi::TEMPLATE_BATCH_SIZE }
15
15
  },
16
+
16
17
  response: {
17
18
  status: 200,
18
19
  body: { templates: [{ email_template_id: email_template_id }] }.to_json
19
20
  }
20
21
  }, {
21
- request: { verb: 'get', url: Txbr::BrazeApi::TEMPLATE_INFO_PATH, params: { email_template_id: email_template_id } },
22
+ request: {
23
+ verb: 'get',
24
+ url: Txbr::EmailTemplatesApi::TEMPLATE_DETAILS_PATH,
25
+ params: { email_template_id: email_template_id }
26
+ },
27
+
22
28
  response: {
23
29
  status: 200,
24
30
  body: {
@@ -49,7 +55,7 @@ describe Txbr::Uploader do
49
55
  {% assign project_slug = "my_project" %}
50
56
  {% assign resource_slug = "my_resource" %}
51
57
  {% assign translation_enabled = true %}
52
- {% connected_content http://my_strings_api.com/ :save strings %}
58
+ {% connected_content http://my_strings_api.com?project_slug={{project_slug}}&resource_slug={{resource_slug}} :save strings %}
53
59
  </head>
54
60
  <body>
55
61
  {{strings.header | default: 'Buy our stuff!'}}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: txbr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Dutro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-10 00:00:00.000000000 Z
11
+ date: 2019-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abroad
@@ -120,22 +120,34 @@ files:
120
120
  - lib/txbr.rb
121
121
  - lib/txbr/application.rb
122
122
  - lib/txbr/braze_api.rb
123
+ - lib/txbr/campaign.rb
124
+ - lib/txbr/campaign_handler.rb
125
+ - lib/txbr/campaigns_api.rb
123
126
  - lib/txbr/commands.rb
124
127
  - lib/txbr/config.rb
128
+ - lib/txbr/content_tag.rb
125
129
  - lib/txbr/email_template.rb
126
- - lib/txbr/email_template_component.rb
127
130
  - lib/txbr/email_template_handler.rb
131
+ - lib/txbr/email_templates_api.rb
132
+ - lib/txbr/liquid.rb
133
+ - lib/txbr/liquid/connected_content_tag.rb
134
+ - lib/txbr/metadata.rb
128
135
  - lib/txbr/project.rb
129
136
  - lib/txbr/request_methods.rb
130
137
  - lib/txbr/strings_manifest.rb
131
138
  - lib/txbr/tasks.rb
139
+ - lib/txbr/template.rb
140
+ - lib/txbr/template_group.rb
132
141
  - lib/txbr/uploader.rb
133
142
  - lib/txbr/utils.rb
134
143
  - lib/txbr/version.rb
135
144
  - spec/application_spec.rb
136
- - spec/braze_api_spec.rb
145
+ - spec/campaign_spec.rb
146
+ - spec/campaigns_api_spec.rb
137
147
  - spec/config_spec.rb
138
148
  - spec/email_template_spec.rb
149
+ - spec/email_templates_api_spec.rb
150
+ - spec/shared_examples/api_errors.rb
139
151
  - spec/spec_helper.rb
140
152
  - spec/strings_manifest_spec.rb
141
153
  - spec/support/env_helpers.rb
@@ -1,96 +0,0 @@
1
- module Txbr
2
- class EmailTemplateComponent
3
- ASSIGNMENTS = %w(project_slug resource_slug translation_enabled)
4
-
5
- attr_reader :liquid_template
6
-
7
- def initialize(liquid_template)
8
- @liquid_template = liquid_template
9
- end
10
-
11
- def project_slug
12
- # blow up with KeyError if not found
13
- assignments.fetch('project_slug')
14
- end
15
-
16
- def resource_slug
17
- # blow up with KeyError if not found
18
- assignments.fetch('resource_slug')
19
- end
20
-
21
- def translation_enabled?
22
- # translation is disabled by default
23
- assignments.fetch('translation_enabled', true)
24
- end
25
-
26
- def assignments
27
- @assignments ||= {}.tap do |assgn|
28
- liquid_template.root.nodelist.each do |node|
29
- case node
30
- when Liquid::Assign
31
- to = node.instance_variable_get(:@to)
32
-
33
- if ASSIGNMENTS.include?(to)
34
- from = node.instance_variable_get(:@from).name
35
- assgn[to] = from
36
- end
37
- end
38
- end
39
- end
40
- end
41
-
42
- def strings
43
- @strings ||= StringsManifest.new.tap do |manifest|
44
- extract_strings_from(liquid_template.root, manifest)
45
- end
46
- end
47
-
48
- private
49
-
50
- def extract_strings_from(root, manifest)
51
- return unless root.nodelist
52
-
53
- root.nodelist.each do |node|
54
- case node
55
- # We only care about Liquid variables, which are written
56
- # like {{prefix.foo.bar}}. We identify the prefix (i.e.
57
- # the first lookup, or path segment) to verify it's
58
- # associated with a connected_content call. Then we add
59
- # the prefix and the rest of the lookups to the strings
60
- # manifest along with the value. The prefix is used to
61
- # divide the strings into individual Transifex resources
62
- # while the rest of the lookups form the string's key.
63
- when Liquid::Variable
64
- next unless node.name.is_a?(Liquid::VariableLookup)
65
-
66
- prefix = node.name.name
67
- path = node.name.lookups
68
-
69
- # the English translation (or whatever language your
70
- # source strings are written in) is provided using
71
- # Liquid's built-in "default" filter
72
- next unless connected_content_prefixes.include?(prefix)
73
- default = node.filters.find { |f| f.first == 'default' }
74
-
75
- manifest.add(path, default&.last&.first)
76
- end
77
-
78
- if node.respond_to?(:nodelist)
79
- extract_strings_from(node, manifest)
80
- end
81
- end
82
- end
83
-
84
- def connected_content_prefixes
85
- @connected_content_prefixes ||= connected_content_tags.map(&:prefix)
86
- end
87
-
88
- def connected_content_tags
89
- # this assumes these are basically at the top of the template and not
90
- # nested inside other liquid tags
91
- @connected_content_tags ||= liquid_template.root.nodelist.select do |node|
92
- node.is_a?(Txbr::ConnectedContentTag)
93
- end
94
- end
95
- end
96
- end