wovnrb 0.2.01 → 0.2.02

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -6
  3. data/README.md +116 -12
  4. data/lib/wovnrb/api_data.rb +59 -0
  5. data/lib/wovnrb/headers.rb +30 -5
  6. data/lib/wovnrb/html_replacers/image_replacer.rb +44 -0
  7. data/lib/wovnrb/html_replacers/link_replacer.rb +18 -0
  8. data/lib/wovnrb/html_replacers/meta_replacer.rb +20 -0
  9. data/lib/wovnrb/html_replacers/replacer_base.rb +17 -0
  10. data/lib/wovnrb/html_replacers/script_replacer.rb +39 -0
  11. data/lib/wovnrb/html_replacers/text_replacer.rb +19 -0
  12. data/lib/wovnrb/lang.rb +133 -23
  13. data/lib/wovnrb/services/url.rb +2 -68
  14. data/lib/wovnrb/services/wovn_logger.rb +45 -0
  15. data/lib/wovnrb/store.rb +19 -38
  16. data/lib/wovnrb/text_caches/cache_base.rb +52 -0
  17. data/lib/wovnrb/text_caches/memory_cache.rb +52 -0
  18. data/lib/wovnrb/version.rb +1 -1
  19. data/lib/wovnrb.rb +19 -224
  20. data/test/lib/api_data_test.rb +62 -0
  21. data/test/lib/headers_test.rb +1221 -1212
  22. data/test/lib/html_replacers/image_replacer_test.rb +86 -0
  23. data/test/lib/html_replacers/link_replacer_test.rb +43 -0
  24. data/test/lib/html_replacers/meta_replacer_test.rb +105 -0
  25. data/test/lib/html_replacers/replacer_base_test.rb +31 -0
  26. data/test/lib/html_replacers/script_replacer_test.rb +90 -0
  27. data/test/lib/html_replacers/text_replacer_test.rb +57 -0
  28. data/test/lib/lang_test.rb +446 -33
  29. data/test/lib/services/wovn_logger_test.rb +40 -0
  30. data/test/lib/store_test.rb +39 -29
  31. data/test/lib/text_caches/cache_base_test.rb +31 -0
  32. data/test/lib/text_caches/memory_cache_test.rb +91 -0
  33. data/test/lib/wovnrb_test.rb +39 -886
  34. data/test/test_helper.rb +96 -1
  35. data/wovnrb.gemspec +4 -0
  36. metadata +89 -2
@@ -1,78 +1,12 @@
1
1
  module Wovnrb
2
2
  class URL
3
-
4
3
  def self.resolve_absolute_url(curr_location, rel_location)
5
4
  end
6
5
 
7
- # Set the path lang to
6
+ # Set the path lang to
8
7
  def self.prepend_path(url, dir)
9
-
10
- result = url.sub(/(.+\.[^\/]+)(\/|$)/, '\1/' + dir + '\2')
8
+ result = url.sub(/(.+\.[^\/]+)(\/|$)/, '\1/' + dir + '\2')
11
9
  return result
12
-
13
- end
14
-
15
- =begin
16
-
17
- url_slash = url.count("/")
18
-
19
- if url.include?("//") && url_slash >= 3 then
20
-
21
- url_base = url.split("/", 4)
22
-
23
- url_begin = url_base[0]
24
- url_middle = url_base[2]
25
- url_end = url_base[3]
26
-
27
- result = url_begin + "//" + url_middle + "/" + dir + "/" + url_end
28
-
29
- return result
30
-
31
- elsif url.include?("//") then
32
-
33
- result = url + "/" + dir
34
-
35
- return result
36
-
37
- elsif url.include?("/") #&& url_slash >= 2 then
38
-
39
- url_base = url.split("/", 2)
40
-
41
- url_begin = url_base[0]
42
- url_end = url_base[1]
43
-
44
- result = url_begin + "/" + dir + "/" + url_end
45
-
46
- return result
47
-
48
- else
49
-
50
- result = url + "/" + dir
51
-
52
- return result
53
-
54
10
  end
55
- end
56
-
57
- =end
58
-
59
- #def self.set_query_lang(url, lang, param_name='wovn')
60
- # url =
61
- # lang =
62
- # param_name = 'wovn'
63
- # return
64
- #end
65
-
66
- #def self.set_subdomain_lang(url, lang)
67
- #end
68
-
69
- #def self.remove_subdomain(url)
70
- #end
71
-
72
- #def self.add_subdomain(url, subdomain)
73
- #end
74
- #def iself.set_query_param(url, param, value)
75
- #end
76
-
77
11
  end
78
12
  end
@@ -0,0 +1,45 @@
1
+ require 'singleton'
2
+ require 'logger' unless defined?(Logger)
3
+
4
+ module Wovnrb
5
+ class WovnLogger
6
+ include Singleton
7
+
8
+ def initialize
9
+ path = Store.instance.settings['log_path']
10
+ if path
11
+ begin
12
+ @logger = Logger.new(path)
13
+ rescue
14
+ begin
15
+ @logger = Logger.new('wovn_error.log')
16
+ @logger.error("Wovn Error: log_path(#{path}) is invalid, please change log_path at config")
17
+ rescue
18
+ @logger = $stderr
19
+ $stderr.puts("Wovn Error: log_path(#{path}) is invalid, please change log_path at config")
20
+ end
21
+ end
22
+ else
23
+ @logger = $stderr
24
+ end
25
+ end
26
+
27
+ def set_logger(logger)
28
+ [:error].each do |method|
29
+ unless logger.respond_to? method
30
+ raise 'not suite for logger'
31
+ end
32
+ end
33
+
34
+ @logger = logger
35
+ end
36
+
37
+ def error(message)
38
+ if @logger == $stderr
39
+ @logger.puts "Wovnrb Error: #{message}"
40
+ else
41
+ @logger.error message
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/wovnrb/store.rb CHANGED
@@ -1,29 +1,40 @@
1
1
  require 'net/http'
2
2
  require 'uri'
3
3
  require 'cgi'
4
- require 'logger' unless defined?(Logger)
4
+ require 'singleton'
5
+ require 'wovnrb/services/wovn_logger'
5
6
 
6
7
  module Wovnrb
7
-
8
8
  class Store
9
+ include Singleton
9
10
 
10
11
  def initialize
11
- @settings =
12
+ @settings = {}
13
+ @config_loaded = false
14
+ reset
15
+ end
16
+
17
+ # Reset @settings and @config_loaded variables to default.
18
+ #
19
+ # @return [nil]
20
+ def reset
21
+ @settings =
12
22
  {
13
23
  'user_token' => '',
14
24
  'secret_key' => '',
15
- # 'url_pattern' => 'query'
16
- # 'url_pattern_reg' => "?.*wovn=(?<lang>[^&]+)(&|$)",
25
+ 'log_path' => 'log/wovn_error.log',
17
26
  'url_pattern' => 'path',
18
27
  'url_pattern_reg' => "/(?<lang>[^/.?]+)",
19
- #'url_pattern' => 'subdomain',
20
- #'url_pattern_reg' => "^(?<lang>[^.]+)\.",
21
28
  'query' => [],
22
29
  'api_url' => 'https://api.wovn.io/v0/values',
30
+ 'api_timeout_seconds' => 0.5,
23
31
  'default_lang' => 'en',
24
32
  'supported_langs' => ['en'],
25
33
  'test_mode' => false,
26
34
  'test_url' => '',
35
+ 'cache_megabytes' => nil,
36
+ 'ttl_seconds' => nil,
37
+ 'use_proxy' => false, # use env['HTTP_X_FORWARDED_HOST'] instead of env['HTTP_HOST'] and env['SERVER_NAME'] when this setting is true.
27
38
  }
28
39
  # When Store is initialized, the Rails.configuration object is not yet initialized
29
40
  @config_loaded = false
@@ -65,9 +76,8 @@ module Wovnrb
65
76
  end
66
77
  # log errors
67
78
  if errors.length > 0
68
- logger = Logger.new('log/error.log')
69
79
  errors.each do |e|
70
- logger.error(e)
80
+ WovnLogger.instance.error(e)
71
81
  end
72
82
  end
73
83
  return valid
@@ -117,35 +127,6 @@ module Wovnrb
117
127
  end
118
128
  @settings
119
129
  end
120
-
121
- # Get the values for the passed in url
122
- #
123
- # @param url [String] The url to get the values for
124
- # @return [Hash] The values Hash for the passed in url
125
- def get_values(url)
126
- url = url.gsub(/\/$/, '')
127
-
128
- begin
129
- uri = URI.parse("#{settings['api_url']}?token=#{settings['user_token']}&url=#{url}")
130
- http = Net::HTTP.new(uri.host, uri.port)
131
- http.use_ssl = true if uri.scheme == 'https'
132
- res = http.start {
133
- http.get(uri.request_uri)
134
- }
135
- if res.code == "200"
136
- vals = JSON.parse(res.body || '{}')
137
- else
138
- vals = {}
139
- end
140
- rescue
141
- vals = {}
142
- logger = Logger.new('../error.log')
143
- logger.error("API server GET request failed with the following parameters:\napi_url: #{settings['api_url']}\ntoken: #{settings['user_token']}\nurl: #{url}")
144
- end
145
-
146
- vals
147
- end
148
-
149
130
  end
150
131
 
151
132
  end
@@ -0,0 +1,52 @@
1
+ require 'active_support/inflector'
2
+
3
+ module Wovnrb
4
+ class CacheBase
5
+ @@strategy_map = {
6
+ memory: :memory_cache
7
+ }
8
+
9
+ @@default_base_config = {
10
+ strategy: :memory
11
+ }
12
+
13
+ @@singleton_cache = nil
14
+ def self.get_single
15
+ raise 'cache is not initialized' unless @@singleton_cache
16
+ @@singleton_cache
17
+ end
18
+
19
+ def self.set_single(config)
20
+ @@singleton_cache = self.build(config)
21
+ end
22
+
23
+ def self.reset_cache
24
+ @@singleton_cache = nil
25
+ end
26
+
27
+ def self.build(config)
28
+ @config = @@default_base_config.merge config
29
+
30
+ strategy = @@strategy_map[@config[:strategy]]
31
+ raise "Invalid strategy: #{strategy}" unless strategy
32
+
33
+ strategy_sym = strategy.to_sym
34
+ begin
35
+ require "wovnrb/text_caches/#{strategy_sym}"
36
+ rescue LoadError => e
37
+ raise "Could not find #{strategy_sym} (#{e})"
38
+ end
39
+
40
+ strategy_class = Wovnrb.const_get(ActiveSupport::Inflector.camelize(strategy_sym))
41
+ strategy_class.new(config)
42
+ end
43
+
44
+ def put(key, value)
45
+ raise NotImplementedError.new('put is not defined')
46
+ end
47
+
48
+ def get(key)
49
+ raise NotImplementedError.new('put is not defined')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_support/cache'
2
+ require 'active_support/cache/memory_store'
3
+ require 'lz4-ruby'
4
+
5
+ module Wovnrb
6
+ class MemoryCache < CacheBase
7
+ @@default_memory_cache_config = {
8
+ cache_megabytes: 200,
9
+ ttl_seconds: 300
10
+ }
11
+
12
+ def initialize(config)
13
+ @config = merge_setting(@@default_memory_cache_config, config)
14
+ cache_size = @config[:cache_megabytes].to_f
15
+ ttl = @config[:ttl_seconds].to_i
16
+ @cache_store = ActiveSupport::Cache::MemoryStore.new(expires_in: ttl.seconds, size: cache_size.megabytes)
17
+ end
18
+
19
+ def put(key, value)
20
+ @cache_store.write(key, compress(value))
21
+ end
22
+
23
+ def get(key)
24
+ stored_value =@cache_store.fetch(key)
25
+ decompress(stored_value) if stored_value
26
+ end
27
+
28
+ def options
29
+ @cache_store.options.clone
30
+ end
31
+
32
+ private
33
+ def merge_setting(original_config, merging_config)
34
+ config = original_config.clone
35
+ config.keys.each do |key|
36
+ key_string = key.to_s
37
+ if merging_config.has_key?(key_string) && merging_config[key_string].present?
38
+ config[key] = merging_config[key_string]
39
+ end
40
+ end
41
+ config
42
+ end
43
+
44
+ def compress(value)
45
+ LZ4::compress(value)
46
+ end
47
+
48
+ def decompress(value)
49
+ LZ4::decompress(value, value.bytesize, 'UTF-8')
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module Wovnrb
2
- VERSION = "0.2.01"
2
+ VERSION = "0.2.02"
3
3
  end
data/lib/wovnrb.rb CHANGED
@@ -4,21 +4,29 @@ require 'wovnrb/lang'
4
4
  require 'nokogumbo'
5
5
  #require 'dom'
6
6
  require 'json'
7
-
7
+ require 'wovnrb/api_data'
8
+ require 'wovnrb/text_caches/cache_base'
9
+ require 'wovnrb/html_replacers/replacer_base'
10
+ require 'wovnrb/html_replacers/link_replacer'
11
+ require 'wovnrb/html_replacers/text_replacer'
12
+ require 'wovnrb/html_replacers/meta_replacer'
13
+ require 'wovnrb/html_replacers/image_replacer'
14
+ require 'wovnrb/html_replacers/script_replacer'
8
15
  require 'wovnrb/railtie' if defined?(Rails)
16
+ require 'wovnrb/version'
9
17
 
10
18
  module Wovnrb
11
-
12
19
  class Interceptor
13
20
  def initialize(app, opts={})
14
21
  @app = app
15
- @store = Store.new
22
+ @store = Store.instance
16
23
  opts = opts.each_with_object({}){|(k,v),memo| memo[k.to_s]=v}
17
24
  @store.settings(opts)
25
+ CacheBase.set_single(@store.settings)
18
26
  end
19
27
 
20
28
  def call(env)
21
- unless @store.valid_settings?
29
+ unless Store.instance.valid_settings?
22
30
  return @app.call(env)
23
31
  end
24
32
  @env = env
@@ -26,7 +34,7 @@ module Wovnrb
26
34
  if @store.settings['test_mode'] && @store.settings['test_url'] != headers.url
27
35
  return @app.call(env)
28
36
  end
29
- #redirect if the path is set to the default language (for SEO purposes)
37
+ #redirect if the path is set to the default language (for SEO purposes)
30
38
  if (headers.path_lang == @store.settings['default_lang'])
31
39
  redirect_headers = headers.redirect(@store.settings['default_lang'])
32
40
  return [307, redirect_headers, ['']]
@@ -37,7 +45,10 @@ module Wovnrb
37
45
  status, res_headers, body = @app.call(headers.request_out)
38
46
 
39
47
  if res_headers["Content-Type"] =~ /html/ # && !body[0].nil?
40
- values = @store.get_values(headers.redis_url)
48
+ # ApiData creates request for external server, but cannot use async.
49
+ # Because some server not allow multi thread. (env['async.callback'] is not supported at all Server).
50
+ api_data = ApiData.new(headers.redis_url, @store)
51
+ values = api_data.get_data
41
52
  url = {
42
53
  :protocol => headers.protocol,
43
54
  :host => headers.host,
@@ -55,86 +66,9 @@ module Wovnrb
55
66
  #[status, res_headers, d.transform()]
56
67
  end
57
68
 
58
- def add_lang_code(href, pattern, lang, headers)
59
- return href if href =~ /^(#.*)?$/
60
- # absolute links
61
- new_href = href
62
- if href && href =~ /^(https?:)?\/\//i
63
- # in the future, perhaps validate url rather than using begin rescue
64
- # "#{url =~ /\// ? 'http:' : ''}#{url}" =~ URI::regexp
65
- begin
66
- uri = URI(href)
67
- rescue
68
- return new_href
69
- end
70
- # only add lang if it's an internal link
71
- # DNS names are case insensitive
72
- if uri.host.downcase === headers.host.downcase
73
- case pattern
74
- when 'subdomain'
75
- sub_d = href.match(/\/\/([^\.]*)\./)[1]
76
- sub_code = Lang.get_code(sub_d)
77
- if sub_code && sub_code.downcase == lang.downcase
78
- new_href = href.sub(Regexp.new(lang, 'i'), lang.downcase)
79
- else
80
- new_href = href.sub(/(\/\/)([^\.]*)/, '\1' + lang.downcase + '.' + '\2')
81
- end
82
- when 'query'
83
- new_href = href =~ /\?/ ? href + '&wovn=' + lang : href + '?wovn=' + lang
84
- else # path
85
- new_href = href.sub(/([^\.]*\.[^\/]*)(\/|$)/, '\1/' + lang + '/')
86
- end
87
- end
88
- elsif href
89
- case pattern
90
- when 'subdomain'
91
- lang_url = headers.protocol + '://' + lang.downcase + '.' + headers.host
92
- current_dir = headers.pathname.sub(/[^\/]*\.[^\.]{2,6}$/, '')
93
- if href =~ /^\.\..*$/
94
- # ../path
95
- new_href = lang_url + '/' + href.gsub(/^\.\.\//, '')
96
- elsif href =~ /^\..*$/
97
- # ./path
98
- new_href = lang_url + current_dir + '/' + href.gsub(/^\.\//, '')
99
- elsif href =~ /^\/.*$/
100
- # /path
101
- new_href = lang_url + href
102
- else
103
- # path
104
- new_href = lang_url + current_dir + '/' + href
105
- end
106
- when 'query'
107
- new_href = href =~ /\?/ ? href + '&wovn=' + lang : href + '?wovn=' + lang
108
- else # path
109
- if href =~ /^\//
110
- new_href = '/' + lang + href
111
- else
112
- current_dir = headers.pathname.sub(/[^\/]*\.[^\.]{2,6}$/, '')
113
- new_href = '/' + lang + current_dir + href
114
- end
115
- end
116
- end
117
- new_href
118
- end
119
-
120
- # returns true if a wovn_ignore is found in the tree from the node to the body tag
121
- def check_wovn_ignore(node)
122
- if !node.get_attribute('wovn-ignore').nil?
123
- return true
124
- elsif node.name === 'html'
125
- return false
126
- end
127
- check_wovn_ignore(node.parent)
128
- end
129
-
130
69
  def switch_lang(body, values, url, lang=@store.settings['default_lang'], headers)
131
-
132
- lang = Lang.get_code(lang)
133
- text_index = values['text_vals'] || {}
134
- src_index = values['img_vals'] || {}
135
- img_src_prefix = values['img_src_prefix'] || ''
70
+ lang = Lang.new(lang)
136
71
  ignore_all = false
137
- string_index = {}
138
72
  new_body = []
139
73
  body.each do |b|
140
74
  d = Nokogiri::HTML5(b)
@@ -148,151 +82,12 @@ module Wovnrb
148
82
  next
149
83
  end
150
84
 
151
- # add lang code to anchors href if not default lang
152
- if lang != @store.settings['default_lang']
153
- pattern = @store.settings['url_pattern']
154
-
155
- d.xpath('//a').each do |a|
156
- next if check_wovn_ignore(a)
157
- href = a.get_attribute('href')
158
- new_href = add_lang_code(href, pattern, lang, headers)
159
- a.set_attribute('href', new_href)
160
- end
161
-
162
- d.xpath('//form').each do |form|
163
- next if check_wovn_ignore(form)
164
- method = form.get_attribute('method')
165
- if pattern == 'query' && (method.nil? || method.upcase == 'GET')
166
- insert_node = Nokogiri::XML::Node.new('input', d)
167
- insert_node['type'] = 'hidden'
168
- insert_node['name'] = 'wovn'
169
- insert_node['value'] = lang
170
- if form.children.size > 0
171
- form.children.first.add_previous_sibling(insert_node)
172
- else
173
- form.add_child(insert_node)
174
- end
175
- else
176
- action = form.get_attribute('action')
177
- new_action = add_lang_code(action, pattern, lang, headers)
178
- form['action'] = new_action
179
- end
180
- end
181
- end
182
-
183
- # swap text
184
- d.xpath('//text()').each do |node|
185
- next if check_wovn_ignore(node)
186
- node_text = node.content.strip
187
- # shouldn't need size check, but for now...
188
- if text_index[node_text] && text_index[node_text][lang] && text_index[node_text][lang].size > 0
189
- node.content = node.content.gsub(/^(\s*)[\S\s]*(\s*)$/, '\1' + text_index[node_text][lang][0]['data'] + '\2')
190
- end
191
- end
192
- # swap meta tag values
193
- d.xpath('//meta').select { |t|
194
- next if check_wovn_ignore(t)
195
- (t.get_attribute('name') || t.get_attribute('property') || '') =~ /^(description|title|og:title|og:description|twitter:title|twitter:description)$/
196
- }.each do |node|
197
- node_content = node.get_attribute('content').strip
198
- # shouldn't need size check, but for now...
199
- if text_index[node_content] && text_index[node_content][lang] && text_index[node_content][lang].size > 0
200
- node.set_attribute('content', node_content.gsub(/^(\s*)[\S\s]*(\s*)$/, '\1' + text_index[node_content][lang][0]['data'] + '\2'))
201
- end
202
- end
203
- # swap img srcs
204
- d.xpath('//img').each do |node|
205
- next if check_wovn_ignore(node)
206
- # use regular expressions to support case insensitivity (right?)
207
- if node.to_html =~ /src=['"][^'"]*['"]/i
208
- src = node.to_html.match(/src=['"]([^'"]*)['"]/i)[1]
209
- # THIS SRC CORRECTION DOES NOT HANDLE ONE IMPORTANT CASE
210
- # 1) "../path/with/ellipse"
211
- # if this is not an absolute src
212
- if src !~ /:\/\//
213
- # if this is a path with a leading slash
214
- if src =~ /^\//
215
- src = "#{url[:protocol]}://#{url[:host]}#{src}"
216
- else
217
- src = "#{url[:protocol]}://#{url[:host]}#{url[:path]}#{src}"
218
- end
219
- end
220
-
221
- # shouldn't need size check, but for now...
222
- if src_index[src] && src_index[src][lang] && src_index[src][lang].size > 0
223
- node.attribute('src').value = "#{img_src_prefix}#{src_index[src][lang][0]['data']}"
224
- end
225
- end
226
- if node.get_attribute('alt')
227
- alt = node.get_attribute('alt').strip
228
- if text_index[alt] && text_index[alt][lang] && text_index[alt][lang].size > 0
229
- node.attribute('alt').value = alt.gsub(/^(\s*)[\S\s]*(\s*)$/, '\1' + text_index[alt][lang][0]['data'] + '\2')
230
- end
231
- end
232
- end
233
-
234
- # REMOVE WIDGET
235
- d.xpath('//script').each do |script_node|
236
- if script_node['src'] && script_node['src'].include?('//j.(dev-)?wovn.io(:3000)?/')
237
- #binding.pry
238
- script_node.remove
239
- end
240
- end
241
-
242
- # PARENT NODE FOR INSERTS
243
- parent_node = d.at_css('head') || d.at_css('body') || d.at_css('html')
244
-
245
- # INSERT BACKEND WIDGET
246
- insert_node = Nokogiri::XML::Node.new('script', d)
247
- # TODO: CHANGE THIS BACK; Should be '//j.wovn.io/0' in production
248
- insert_node['src'] = '//j.wovn.io/1'
249
- insert_node['async'] = true
250
- #insert_node['src'] = '//j.dev-wovn.io:3000/0'
251
- version = defined?(VERSION) ? VERSION : ''
252
- insert_node['data-wovnio'] = "key=#{@store.settings['user_token']}&backend=true&currentLang=#{lang}&defaultLang=#{@store.settings['default_lang']}&urlPattern=#{@store.settings['url_pattern']}&version=#{version}"
253
- # do this so that there will be a closing tag (better compatibility with browsers)
254
- insert_node.content = ' '
255
- if parent_node.children.size > 0
256
- parent_node.children.first.add_previous_sibling(insert_node)
257
- else
258
- parent_node.add_child(insert_node)
259
- end
260
-
261
-
262
- # INSERT LANGUAGE METALINKS
263
- published_langs = get_langs(values)
264
- published_langs.each do |l|
265
- insert_node = Nokogiri::XML::Node.new('link', d)
266
- insert_node['rel'] = 'alternate'
267
- insert_node['hreflang'] = l
268
- insert_node['href'] = headers.redirect_location(l)
269
- parent_node.add_child(insert_node)
270
- end
271
-
272
- # set lang property on HTML tag
273
- if d.at_css('html') || d.at_css('HTML')
274
- (d.at_css('html') || d.at_css('HTML')).set_attribute('lang', lang)
275
- end
276
-
277
- output = d.to_html.gsub(/href="([^"]*)"/) { |m| "href=\"#{URI.decode($1)}\"" }
85
+ output = lang.switch_dom_lang(d, @store, values, url, headers)
278
86
  new_body.push(output)
279
87
  end
280
88
  body.close if body.respond_to?(:close)
281
89
  new_body
282
- #body
283
90
  end
284
-
285
- # this clearly needs to be refactored. I'm thinking maybe a Value service? (@store.values.get_langs)
286
- def get_langs(values)
287
- langs = Set.new
288
- (values['text_vals'] || {}).merge(values['img_vals'] || {}).each do |key, index|
289
- index.each do |l, val|
290
- langs.add(l)
291
- end
292
- end
293
- langs
294
- end
295
-
296
91
  end
297
92
 
298
93
  end
@@ -0,0 +1,62 @@
1
+ require 'wovnrb/text_caches/cache_base'
2
+ require 'wovnrb/text_caches/memory_cache'
3
+ require 'wovnrb/api_data'
4
+ require 'test_helper'
5
+ require 'webmock/minitest'
6
+
7
+ module Wovnrb
8
+ class MemoryCacheTest < WovnMiniTest
9
+ def setup
10
+ Wovnrb::CacheBase.set_single({})
11
+ end
12
+
13
+ def teardown
14
+ Wovnrb::CacheBase.reset_cache
15
+ WebMock.reset!
16
+ end
17
+
18
+ def test_initialize
19
+ Wovnrb::ApiData.new('http://wwww.example.com', Wovnrb::Store.instance)
20
+ end
21
+
22
+ def test_get_data
23
+ token = 'a'
24
+ url = 'url'
25
+ stub_request(:get, "https://api.wovn.io/v0/values?token=#{token}&url=#{url}").
26
+ to_return(:body => '{"test_body": "a"}')
27
+ store = Wovnrb::Store.instance
28
+ store.settings['user_token'] = token
29
+ api_data = Wovnrb::ApiData.new(url, store)
30
+
31
+ assert_equal({'test_body' => 'a'}, api_data.get_data)
32
+ end
33
+
34
+ def test_get_data_when_cache_exists
35
+ token = 'a'
36
+ url = 'url'
37
+ stub = stub_request(:get, "https://api.wovn.io/v0/values?token=#{token}&url=#{url}").
38
+ to_return(:body => '{"test_body": "a"}')
39
+ store = Wovnrb::Store.instance
40
+ store.settings['user_token'] = token
41
+ api_data = Wovnrb::ApiData.new(url, store)
42
+
43
+ assert_equal({'test_body' => 'a'}, api_data.get_data)
44
+ assert_equal({'test_body' => 'a'}, api_data.get_data)
45
+ assert_requested(stub, :times => 1)
46
+ end
47
+
48
+ def test_get_data_fail
49
+ token = 'a'
50
+ url = 'url'
51
+ stub_request(:get, "https://api.wovn.io/v0/values?token=#{token}&url=#{url}").
52
+ to_return(:status => [500, "Internal Server Error"])
53
+ store = Wovnrb::Store.instance
54
+ store.settings['user_token'] = token
55
+ api_data = Wovnrb::ApiData.new(url, store)
56
+ log_mock = Wovnrb::LogMock.mock_log
57
+
58
+ assert_equal({}, api_data.get_data)
59
+ assert(log_mock.errors[0].start_with?('API server GET request failed'))
60
+ end
61
+ end
62
+ end