wovnrb 0.2.01 → 0.2.02

Sign up to get free protection for your applications and to get access to all the features.
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