riddick 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ module Riddick
2
+ def self.version
3
+ '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,96 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Welcome to Riddick!</title>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <!--[if IE ]><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><![endif]-->
8
+ <!--[if lt IE 9]>
9
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
10
+ <![endif]-->
11
+ <link href="<%= url 'stylesheets/vendor/bootstrap.css' %>" media="all" rel="stylesheet" type="text/css">
12
+ <link href="<%= url 'stylesheets/vendor/bootstrap-responsive.css' %>" media="all" rel="stylesheet" type="text/css">
13
+ <link href="<%= url 'stylesheets/vendor/chosen.css' %>" media="all" rel="stylesheet" type="text/css">
14
+ <link href="<%= url 'stylesheets/riddick.css' %>" media="all" rel="stylesheet" type="text/css">
15
+ </head>
16
+
17
+ <body>
18
+ <div class="container">
19
+ <div class="navbar">
20
+ <div class="navbar-inner">
21
+ <a href="<%= root_url %>" class="brand">Riddick</a>
22
+ <ul class="nav">
23
+ <li class="<%= 'active' if request.path == root_url %>">
24
+ <a href="<%= root_url %>">All translations</a>
25
+ </li>
26
+ <li class="<%= 'active' if request.path == my_url %>">
27
+ <a href="<%= my_url %>">My translations</a>
28
+ </li>
29
+ <li class="<%= 'active' if request.path == default_url %>">
30
+ <a href="<%= default_url %>">Default translations</a>
31
+ </li>
32
+ </ul>
33
+ </div>
34
+ </div>
35
+
36
+ <form action="<%= set_url %>" method="post" class="form-horizontal well">
37
+ <select name="k" data-chosen="chosen" data-for="textarea[name=v]" data-placeholder="en.greeting">
38
+ <option></option>
39
+ <% @translations.each do |k, v| %>
40
+ <option value="<%= k %>" data-v='<%= v %>'><%= k %></option>
41
+ <% end %>
42
+ </select>
43
+ <button type="submit" class="btn btn-success">Change</button><br />
44
+ <textarea name="v" type="text" placeholder="Hello World!"></textarea>
45
+ </form>
46
+
47
+ <% [:flash_success, :flash_error].each do |k| %>
48
+ <% if v = session.delete(k) %>
49
+ <div class="alert alert-<%= k.to_s.gsub 'flash_', '' %>"><%= v %></div>
50
+ <% end %>
51
+ <% end %>
52
+
53
+ <% if @translations.any? %>
54
+ <table class="table table-striped">
55
+ <tr><th>Path</th><th>Translation</th><th>Actions</th></tr>
56
+ <% @translations.each_pair do |k, v| %>
57
+ <tr>
58
+ <% if v.kind_of? Riddick::Backends::KeyValue::Value %>
59
+ <td><span class="badge badge-success"><%= k %></span></td>
60
+ <td><code>
61
+ <a rel="popover" data-title="My translation" data-content='<%= v %>'
62
+ data-trigger="hover"><%= truncate v %></a>
63
+ </code></td>
64
+ <td>
65
+ <a href="#custom-translations" data-choose="<%= k %>" data-v='<%= v %>'
66
+ class="btn btn-mini">Edit</a>
67
+ <a href="<%= del_url k %>" data-confirm="Are you sure?"
68
+ class="btn btn-mini btn-danger">Delete</a>
69
+ </td>
70
+ <% else %>
71
+ <td><span class="badge"><%= k %></span></td>
72
+ <td><code>
73
+ <a rel="popover" data-title="Default translation" data-content='<%= v %>'
74
+ data-trigger="hover"><%= truncate v %></a>
75
+ </code></td>
76
+ <td>
77
+ <a href="#custom-translations" data-choose="<%= k %>" data-v='<%= v %>'
78
+ class="btn btn-mini">Edit</a>
79
+ </td>
80
+ <% end %>
81
+ </tr>
82
+ <% end %>
83
+ </table>
84
+ <% else %>
85
+ <div class="alert alert-info">You have no translations yet.</div>
86
+ <% end %>
87
+
88
+ <div class="well"><a href="https://github.com/kostia/riddick">https://github.com/kostia/riddick</a></div>
89
+ </div>
90
+
91
+ <script src="<%= url 'javascripts/vendor/jquery.js' %>" type="text/javascript"></script>
92
+ <script src="<%= url 'javascripts/vendor/chosen.js' %>" type="text/javascript"></script>
93
+ <script src="<%= url 'javascripts/vendor/bootstrap.js' %>" type="text/javascript"></script>
94
+ <script src="<%= url 'javascripts/riddick.js' %>" type="text/javascript"></script>
95
+ </body>
96
+ </html>
@@ -0,0 +1,27 @@
1
+ require File.expand_path '../lib/riddick/version', __FILE__
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'riddick'
5
+ gem.version = Riddick.version
6
+ gem.description = %{
7
+ Riddick is a simple Sintra based GUI for Redis-I18n-backend.
8
+ It provides a list of preconfigured translations (via YAML-backend).
9
+ Also you can add your translations to Redis-backend.
10
+ }
11
+ gem.summary = 'Simple GUI for Redis-I18n-backend'
12
+ gem.homepage = 'https://github.com/kostia/riddick'
13
+ gem.authors = ['Kostiantyn Kahanskyi']
14
+ gem.email = %w[kostiantyn.kahanskyi@googlemail.com]
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.require_paths = %w[lib]
17
+ gem.required_ruby_version = '>= 1.9.3'
18
+ gem.add_dependency 'i18n'
19
+ gem.add_dependency 'redis'
20
+ gem.add_dependency 'sinatra'
21
+ gem.add_development_dependency 'capybara'
22
+ gem.add_development_dependency 'pry'
23
+ gem.add_development_dependency 'rack-test'
24
+ gem.add_development_dependency 'rake'
25
+ gem.add_development_dependency 'rspec'
26
+ gem.add_development_dependency 'yajl-ruby'
27
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddick::Backends::KeyValue do
4
+ describe 'creating a new backend' do
5
+ it 'should store i18n backend' do
6
+ i18n_be = mock
7
+ Riddick::Backends::KeyValue.new(i18n_be).i18n_backend.should == i18n_be
8
+ end
9
+ end
10
+
11
+ describe Riddick::Backends::KeyValue::Value do
12
+ it 'should return decoded string' do
13
+ v = Riddick::Backends::KeyValue::Value.new MultiJson.encode('foo')
14
+ v.to_s.should == 'foo'
15
+
16
+ v = Riddick::Backends::KeyValue::Value.new MultiJson.encode(%w[foo bar baz])
17
+ v.to_s.should == '["foo", "bar", "baz"]'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddick::Backends::Redis do
4
+ describe 'creating a new backend' do
5
+ it 'should be a key value backend' do
6
+ Riddick::Backends::Redis.new(mock).should be_kind_of(Riddick::Backends::KeyValue)
7
+ end
8
+
9
+ it 'should store i18n backend' do
10
+ i18n_be = mock
11
+ Riddick::Backends::Redis.new(i18n_be).i18n_backend.should == i18n_be
12
+ end
13
+ end
14
+
15
+ describe '#translations' do
16
+ describe 'if there are any keys' do
17
+ it 'should return the translation hash' do
18
+ redis_be = mock(store: mock(keys: %w[k1 k2 k3]))
19
+ redis_be.store.should_receive(:mget).with(%w[k1 k2 k3]).and_return %w["v1" "v2" "v3"]
20
+ translations = Riddick::Backends::Redis.new(redis_be).translations
21
+ translations.size.should == 3
22
+ translations['k1'].should be_a(Riddick::Backends::Redis::Value)
23
+ translations['k1'].to_s.should == 'v1'
24
+ translations['k2'].should be_a(Riddick::Backends::Redis::Value)
25
+ translations['k2'].to_s.should == 'v2'
26
+ translations['k3'].should be_a(Riddick::Backends::Redis::Value)
27
+ translations['k3'].to_s.should == 'v3'
28
+ end
29
+ end
30
+
31
+ describe 'if there are no keys' do
32
+ it 'should return an empty hash' do
33
+ redis_be = mock(store: mock(keys: []))
34
+ Riddick::Backends::Redis.new(redis_be).translations.should == {}
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '#delete_translation' do
40
+ it 'should delete key from the store' do
41
+ redis_be = mock store: mock
42
+ redis_be.store.should_receive(:del).with 'foo.bar'
43
+ Riddick::Backends::Redis.new(redis_be).delete_translation 'foo.bar'
44
+ end
45
+ end
46
+
47
+ describe Riddick::Backends::Redis::Value do
48
+ it 'should be a general key value value' do
49
+ v = Riddick::Backends::Redis::Value.new '"foo"'
50
+ v.should be_kind_of(Riddick::Backends::KeyValue::Value)
51
+ end
52
+
53
+ it 'should return decoded string' do
54
+ v = Riddick::Backends::Redis::Value.new MultiJson.encode('foo')
55
+ v.to_s.should == 'foo'
56
+
57
+ v = Riddick::Backends::Redis::Value.new MultiJson.encode(%w[foo bar baz])
58
+ v.to_s.should == '["foo", "bar", "baz"]'
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddick::Backends::Simple do
4
+ describe 'creating a new backend' do
5
+ it 'should store i18n backend' do
6
+ i18n_be = mock
7
+ Riddick::Backends::Simple.new(i18n_be).i18n_backend.should == i18n_be
8
+ end
9
+ end
10
+
11
+ describe '#translations' do
12
+ it 'should return normalized translation from i18n backend' do
13
+ I18n.stub(:locale).and_return :en
14
+ i18n_be = mock translations: {en: {'foo' => {'bar' => 'baz'}}}
15
+ Riddick::Backends::Simple.new(i18n_be).translations.should == {'en.foo.bar' => 'baz'}
16
+ end
17
+ end
18
+
19
+ describe '#init_translations' do
20
+ it 'should init translations of i18n backend' do
21
+ i18n_be = mock
22
+ i18n_be.should_receive :init_translations
23
+ Riddick::Backends::Simple.new(i18n_be).init_translations
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddick::Backends do
4
+ describe '#chain' do
5
+ context 'when not set via setter method' do
6
+ it 'should return I18n backend chain' do
7
+ Riddick::Backends.chain.should == I18n.backend
8
+ end
9
+ end
10
+
11
+ context 'when set via setter method' do
12
+ it 'should return the chain object' do
13
+ chain = mock
14
+ Riddick::Backends.chain = chain
15
+ Riddick::Backends.chain.should == chain
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '#simple' do
21
+ let(:kv_be) { I18n::Backend::KeyValue.new({}) }
22
+ let(:s_be) { I18n::Backend::Simple.new }
23
+ let(:chain) { mock backends: [kv_be, s_be] }
24
+
25
+ before do
26
+ Riddick::Backends.chain = chain
27
+ end
28
+
29
+ context 'when no set via setter method' do
30
+ it 'should determine backend dynamically' do
31
+ Riddick::Backends.simple.should be_kind_of(Riddick::Backends::Simple)
32
+ Riddick::Backends.simple.i18n_backend.should == s_be
33
+ end
34
+ end
35
+
36
+ context 'when set via setter method' do
37
+ it 'should return the backend object' do
38
+ Riddick::Backends.simple = s_be
39
+ Riddick::Backends.simple.should == s_be
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#key_value' do
45
+ let(:kv_be) { I18n::Backend::KeyValue.new({}) }
46
+ let(:s_be) { I18n::Backend::Simple.new }
47
+ let(:chain) { mock backends: [kv_be, s_be] }
48
+
49
+ before do
50
+ Riddick::Backends.chain = chain
51
+ end
52
+
53
+ context 'when no set via setter method' do
54
+ it 'should determine backend dynamically' do
55
+ Riddick::Backends.key_value.should be_kind_of(Riddick::Backends::Redis)
56
+ Riddick::Backends.key_value.i18n_backend.should == kv_be
57
+ end
58
+ end
59
+
60
+ context 'when set via setter method' do
61
+ it 'should return the backend object' do
62
+ Riddick::Backends.key_value = kv_be
63
+ Riddick::Backends.key_value.should == kv_be
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#store_translation' do
69
+ it 'should store unescaped translation in chain with correctly determined path' do
70
+ chain = mock
71
+ Riddick::Backends.chain = chain
72
+ chain.should_receive(:store_translations).with 'en', {'foo.bar' => 'baz'}, {escape: false}
73
+ Riddick::Backends.store_translation 'en.foo.bar', 'baz'
74
+ end
75
+ end
76
+
77
+ describe '#delete_translation' do
78
+ it 'should delete translation from key value backend' do
79
+ kv_be = mock
80
+ Riddick::Backends.key_value = kv_be
81
+ kv_be.should_receive(:delete_translation).with 'foo.bar'
82
+ Riddick::Backends.delete_translation 'foo.bar'
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hash do
4
+ describe '#riddick_normalize_i18n' do
5
+ it 'should return i18n-style hash' do
6
+ {
7
+ foo: {
8
+ bar: 'baz',
9
+ blub: 'bla',
10
+ }
11
+ }.riddick_normalize_i18n('en').should == {'en.foo.bar' => 'baz', 'en.foo.blub' => 'bla'}
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,133 @@
1
+ require 'capybara/rspec'
2
+ require 'rack/test'
3
+ require 'spec_helper'
4
+
5
+ set :environment, :test
6
+
7
+ describe 'Riddick::Server', type: :request do
8
+ include Rack::Test::Methods
9
+
10
+ def app
11
+ Riddick::Server.new
12
+ end
13
+
14
+ let(:s_be) { mock }
15
+ let(:kv_be) { mock }
16
+
17
+ before do
18
+ Riddick::Backends.simple = s_be
19
+ Riddick::Backends.key_value = kv_be
20
+
21
+ s_be.should_receive :init_translations # Assert translations are initialized on load
22
+
23
+ load 'lib/riddick/server.rb'
24
+
25
+ s_be.stub(:translations).and_return({
26
+ 'en.k1' => 'default-v1',
27
+ 'en.k2' => 'default-v2',
28
+ })
29
+ kv_be.stub(:translations).and_return({
30
+ 'en.k2' => Riddick::Backends::Redis::Value.new('"my-v2"'),
31
+ 'en.k3' => Riddick::Backends::Redis::Value.new('"my-v3"'),
32
+ })
33
+ end
34
+
35
+ describe 'GET /' do
36
+ it 'should render list of all translations overlaying default with my' do
37
+ get '/'
38
+ last_response.should be_ok
39
+ last_response.body.should have_selector("option[value='en.k1'][data-v='default-v1']")
40
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
41
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
42
+ end
43
+ end
44
+
45
+ describe 'GET /my' do
46
+ it 'should render list of my translations' do
47
+ get '/my'
48
+ last_response.should be_ok
49
+ last_response.body.should_not have_selector("option[data-v^='default-']")
50
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
51
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
52
+ end
53
+ end
54
+
55
+ describe 'GET /default' do
56
+ it 'should render list of default translations' do
57
+ get '/default'
58
+ last_response.should be_ok
59
+ last_response.body.should_not have_selector("option[data-v^='my-']")
60
+ last_response.body.should have_selector("option[value='en.k1'][data-v='default-v1']")
61
+ last_response.body.should have_selector("option[value='en.k2'][data-v='default-v2']")
62
+ end
63
+ end
64
+
65
+ describe 'POST /set' do
66
+ context 'with valid params' do
67
+ it 'should store translation and redirect to my translation' do
68
+ Riddick::Backends.should_receive(:store_translation).with 'en.k1', 'my-v1' do
69
+ kv_be.stub(:translations).and_return({
70
+ 'en.k1' => Riddick::Backends::Redis::Value.new('"my-v1"'),
71
+ 'en.k2' => Riddick::Backends::Redis::Value.new('"my-v2"'),
72
+ 'en.k3' => Riddick::Backends::Redis::Value.new('"my-v3"'),
73
+ })
74
+ end
75
+ post '/set', k: 'en.k1', v: 'my-v1'
76
+ follow_redirect!
77
+ last_response.should be_ok
78
+ last_response.body.should_not have_selector("option[data-v^='default-']")
79
+ last_response.body.should have_selector("option[value='en.k1'][data-v='my-v1']")
80
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
81
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
82
+ end
83
+ end
84
+
85
+ context 'with incorrect params' do
86
+ it 'should not try to store translation and render index' do
87
+ Riddick::Backends.should_not_receive :store_translation
88
+
89
+ post '/set', k: 'en.k1', v: ''
90
+ follow_redirect!
91
+ last_response.should be_ok
92
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
93
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
94
+
95
+ post '/set', k: '', v: 'my-v1'
96
+ follow_redirect!
97
+ last_response.should be_ok
98
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
99
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
100
+ end
101
+ end
102
+ end
103
+
104
+ describe 'GET /del' do
105
+ context 'with valid key' do
106
+ it 'should delete translation and redirect root' do
107
+ Riddick::Backends.should_receive(:delete_translation).with 'en.k2' do
108
+ kv_be.stub(:translations).and_return({
109
+ 'en.k3' => Riddick::Backends::Redis::Value.new('"my-v3"'),
110
+ })
111
+ end
112
+ get '/del', k: 'en.k2'
113
+ follow_redirect!
114
+ last_response.should be_ok
115
+ last_response.body.should have_selector("option[value='en.k1'][data-v='default-v1']")
116
+ last_response.body.should have_selector("option[value='en.k2'][data-v='default-v2']")
117
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
118
+ end
119
+ end
120
+
121
+ context 'with invalid key' do
122
+ it 'should delete translation and redirect root' do
123
+ Riddick::Backends.should_not_receive :delete_translation
124
+ get '/del', k: ''
125
+ follow_redirect!
126
+ last_response.should be_ok
127
+ last_response.body.should have_selector("option[value='en.k1'][data-v='default-v1']")
128
+ last_response.body.should have_selector("option[value='en.k2'][data-v='my-v2']")
129
+ last_response.body.should have_selector("option[value='en.k3'][data-v='my-v3']")
130
+ end
131
+ end
132
+ end
133
+ end