txdb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +202 -0
  3. data/README.md +39 -0
  4. data/lib/txdb.rb +32 -0
  5. data/lib/txdb/app.rb +36 -0
  6. data/lib/txdb/backends.rb +19 -0
  7. data/lib/txdb/backends/globalize.rb +10 -0
  8. data/lib/txdb/backends/globalize/backend.rb +19 -0
  9. data/lib/txdb/backends/globalize/helpers.rb +19 -0
  10. data/lib/txdb/backends/globalize/reader.rb +63 -0
  11. data/lib/txdb/backends/globalize/writer.rb +39 -0
  12. data/lib/txdb/config.rb +52 -0
  13. data/lib/txdb/connection_string.rb +18 -0
  14. data/lib/txdb/database.rb +40 -0
  15. data/lib/txdb/downloader.rb +32 -0
  16. data/lib/txdb/handlers.rb +6 -0
  17. data/lib/txdb/handlers/hook_handler.rb +59 -0
  18. data/lib/txdb/handlers/triggers.rb +9 -0
  19. data/lib/txdb/handlers/triggers/handler.rb +50 -0
  20. data/lib/txdb/handlers/triggers/pull_handler.rb +34 -0
  21. data/lib/txdb/handlers/triggers/push_handler.rb +19 -0
  22. data/lib/txdb/response.rb +11 -0
  23. data/lib/txdb/response_helpers.rb +26 -0
  24. data/lib/txdb/table.rb +36 -0
  25. data/lib/txdb/transifex_project.rb +17 -0
  26. data/lib/txdb/tx_resource.rb +52 -0
  27. data/lib/txdb/uploader.rb +33 -0
  28. data/lib/txdb/version.rb +3 -0
  29. data/spec/backends/globalize/helpers_spec.rb +17 -0
  30. data/spec/backends/globalize/reader_spec.rb +25 -0
  31. data/spec/backends/globalize/writer_spec.rb +53 -0
  32. data/spec/backends_spec.rb +30 -0
  33. data/spec/config_spec.rb +71 -0
  34. data/spec/connection_string_spec.rb +24 -0
  35. data/spec/database_spec.rb +33 -0
  36. data/spec/downloader_spec.rb +36 -0
  37. data/spec/handlers/hook_handler_spec.rb +73 -0
  38. data/spec/handlers/triggers/pull_handler_spec.rb +58 -0
  39. data/spec/handlers/triggers/push_handler_spec.rb +49 -0
  40. data/spec/spec_helper.rb +20 -0
  41. data/spec/spec_helpers/env_helpers.rb +13 -0
  42. data/spec/spec_helpers/globalize_db.rb +60 -0
  43. data/spec/spec_helpers/test_backend.rb +28 -0
  44. data/spec/spec_helpers/test_db.rb +76 -0
  45. data/spec/table_spec.rb +58 -0
  46. data/spec/test.sqlite3 +0 -0
  47. data/spec/transifex_project_spec.rb +15 -0
  48. data/spec/tx_resource_spec.rb +17 -0
  49. data/spec/uploader_spec.rb +36 -0
  50. data/txdb.gemspec +22 -0
  51. metadata +134 -0
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_backend'
3
+ require 'spec_helpers/test_db'
4
+ require 'uri'
5
+ require 'yaml'
6
+
7
+ include Txdb::Handlers::Triggers
8
+
9
+ describe PullHandler do
10
+ include Rack::Test::Methods
11
+
12
+ let(:database) { TestDb.database }
13
+ let(:table) { database.tables.first }
14
+ let(:project) { database.transifex_project }
15
+
16
+ def app
17
+ Txdb::Triggers
18
+ end
19
+
20
+ before(:each) do
21
+ allow(Txdb::Config).to receive(:databases).and_return([database])
22
+ end
23
+
24
+ let(:params) do
25
+ { 'database' => database.database, 'table' => table.name }
26
+ end
27
+
28
+ it 'downloads the table for each locale' do
29
+ locales = [{ 'language_code' => 'es' }, { 'language_code' => 'ja' }]
30
+ content = { 'phrase' => 'trans' }
31
+ expect(database.transifex_api).to receive(:get_languages).and_return(locales)
32
+ allow(database.transifex_api).to receive(:download).and_return(YAML.dump(content))
33
+
34
+ expect { patch('/pull', params) }.to(
35
+ change { Txdb::TestBackend.writes.size }.from(0).to(2)
36
+ )
37
+
38
+ expect(last_response.status).to eq(200)
39
+ expect(last_response.body).to eq('{}')
40
+
41
+ expect(Txdb::TestBackend.writes).to include(
42
+ locale: 'es', table: table.name, content: content
43
+ )
44
+
45
+ expect(Txdb::TestBackend.writes).to include(
46
+ locale: 'ja', table: table.name, content: content
47
+ )
48
+ end
49
+
50
+ it 'reports errors' do
51
+ expect(database.transifex_api).to receive(:get_languages).and_raise('jelly beans')
52
+ patch '/pull', params
53
+ expect(last_response.status).to eq(500)
54
+ expect(JSON.parse(last_response.body)).to eq(
55
+ [{ 'error' => 'Internal server error: jelly beans' }]
56
+ )
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_backend'
3
+ require 'spec_helpers/test_db'
4
+ require 'uri'
5
+ require 'yaml'
6
+
7
+ include Txdb::Handlers::Triggers
8
+
9
+ describe PushHandler do
10
+ include Rack::Test::Methods
11
+
12
+ let(:database) { TestDb.database }
13
+ let(:table) { database.tables.first }
14
+ let(:project) { database.transifex_project }
15
+
16
+ def app
17
+ Txdb::Triggers
18
+ end
19
+
20
+ before(:each) do
21
+ allow(Txdb::Config).to receive(:databases).and_return([database])
22
+ end
23
+
24
+ let(:params) do
25
+ { 'database' => database.database, 'table' => table.name }
26
+ end
27
+
28
+ it 'uploads the table' do
29
+ expect(database.transifex_api).to receive(:create_or_update)
30
+
31
+ expect { patch('/push', params) }.to(
32
+ change { Txdb::TestBackend.reads.size }.from(0).to(1)
33
+ )
34
+
35
+ expect(last_response.status).to eq(200)
36
+ expect(last_response.body).to eq('{}')
37
+
38
+ expect(Txdb::TestBackend.reads).to include(table: table.name)
39
+ end
40
+
41
+ it 'reports errors' do
42
+ expect(database.transifex_api).to receive(:create_or_update).and_raise('jelly beans')
43
+ patch '/push', params
44
+ expect(last_response.status).to eq(500)
45
+ expect(JSON.parse(last_response.body)).to eq(
46
+ [{ 'error' => 'Internal server error: jelly beans' }]
47
+ )
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ require 'pry-byebug'
2
+ require 'rack/test'
3
+ require 'rake'
4
+ require 'rspec'
5
+ require 'sequel'
6
+ require 'sqlite3'
7
+ require 'txdb'
8
+
9
+ require 'spec_helpers/env_helpers'
10
+ require 'spec_helpers/test_backend'
11
+
12
+ RSpec.configure do |config|
13
+ config.before(:each) do
14
+ Txdb::TestBackend.reset
15
+ end
16
+
17
+ config.include(EnvHelpers)
18
+ end
19
+
20
+ Txdb::Backends.register('test-backend', Txdb::TestBackend)
@@ -0,0 +1,13 @@
1
+ module EnvHelpers
2
+ def with_env(env)
3
+ # ENV can't be duped, so use select instead to make a copy
4
+ old_env = ENV.select { true }
5
+ env.each_pair { |k, v| ENV[k] = v }
6
+ yield
7
+ ensure
8
+ # reset back to old vars
9
+ env.each_pair { |k, _| ENV[k] = old_env[k] }
10
+ end
11
+ end
12
+
13
+ EnvHelpers.extend(EnvHelpers)
@@ -0,0 +1,60 @@
1
+ require 'spec_helpers/test_db'
2
+
3
+ class GlobalizeDb < TestDb
4
+ class << self
5
+ def database
6
+ @database ||= Txdb::Database.new(
7
+ raw_config[:databases].first.merge(
8
+ backend: Txdb::Backends.get('globalize'),
9
+ tables: [{
10
+ name: 'widget_translations',
11
+ source_lang: 'en',
12
+ columns: %w(name)
13
+ }]
14
+ )
15
+ )
16
+ end
17
+
18
+ def setup_db
19
+ db.create_table(:widgets) do
20
+ primary_key :id
21
+ string :name
22
+ end
23
+
24
+ db.create_table(:widget_translations) do
25
+ primary_key :id
26
+ integer :widget_id
27
+ string :locale
28
+ string :name
29
+ end
30
+ end
31
+
32
+ def widgets
33
+ db[:widgets]
34
+ end
35
+
36
+ def widget_translations
37
+ db[:widget_translations]
38
+ end
39
+
40
+ def widget_translations_table
41
+ database.tables.find do |table|
42
+ table.name == 'widget_translations'
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ RSpec.shared_context(:globalize) do
49
+ let(:widgets) { GlobalizeDb.widgets }
50
+ let(:widget_translations) { GlobalizeDb.widget_translations }
51
+ let(:widget_translations_table) { GlobalizeDb.widget_translations_table }
52
+ let(:database) { GlobalizeDb.database }
53
+ end
54
+
55
+ RSpec.configure do |config|
56
+ config.around(:each) do |example|
57
+ GlobalizeDb.reset_db if example.metadata[:globalize_db]
58
+ example.run
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ module Txdb
2
+ class TestBackend
3
+ class << self
4
+ def reads
5
+ @reads ||= []
6
+ end
7
+
8
+ def writes
9
+ @writes ||= []
10
+ end
11
+
12
+ def reset
13
+ @reads = nil
14
+ @writes = nil
15
+ end
16
+
17
+ def read_content_from(table)
18
+ reads << { table: table.name }
19
+ {}
20
+ end
21
+
22
+ def write_content_to(table, content, locale)
23
+ writes << { table: table.name, content: content, locale: locale }
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helpers/env_helpers'
2
+ require 'spec_helpers/test_backend'
3
+ require 'yaml'
4
+
5
+ class TestDb
6
+ class << self
7
+ def db
8
+ @db ||= database.db
9
+ end
10
+
11
+ def database
12
+ @database ||= Txdb::Database.new(raw_config[:databases].first)
13
+ end
14
+
15
+ def db_path
16
+ File.join(File.dirname(__FILE__), '../test.sqlite3')
17
+ end
18
+
19
+ def raw_config
20
+ @config ||= deep_freeze({
21
+ databases: [{
22
+ adapter: 'sqlite',
23
+ backend: 'test-backend',
24
+ username: 'username',
25
+ password: 'password',
26
+ database: 'spec/test.sqlite3',
27
+ transifex: {
28
+ organization: 'myorg',
29
+ project_slug: 'myproject',
30
+ username: 'username',
31
+ password: 'password',
32
+ webhook_secret: '123abc'
33
+ },
34
+ tables: [{
35
+ name: 'my_table',
36
+ source_lang: 'en',
37
+ columns: %w(my_column)
38
+ }]
39
+ }]
40
+ })
41
+ end
42
+
43
+ def reset_db
44
+ db.tables.each { |t| db.drop_table(t) }
45
+ setup_db
46
+ end
47
+
48
+ def setup_db
49
+ # no-op
50
+ end
51
+
52
+ private
53
+
54
+ def deep_freeze(obj)
55
+ case obj
56
+ when Hash
57
+ obj.each_with_object({}) do |(k, v), ret|
58
+ ret[k] = deep_freeze(v)
59
+ end.freeze
60
+
61
+ when Array
62
+ obj.map { |elem| deep_freeze(elem) }.freeze
63
+
64
+ else
65
+ obj
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ RSpec.configure do |config|
72
+ config.around(:each) do |example|
73
+ TestDb.reset_db if example.metadata[:test_db]
74
+ example.run
75
+ end
76
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_db'
3
+ require 'yaml'
4
+
5
+ include Txdb
6
+
7
+ describe Table, test_db: true do
8
+ let(:database) { TestDb.database }
9
+ let(:table) { database.tables.first }
10
+
11
+ describe '#db' do
12
+ it 'returns a dataset primed to select from the table' do
13
+ expect(table.db).to be_a(Sequel::Dataset)
14
+ expect(table.db.sql).to eq('SELECT * FROM `my_table`')
15
+ end
16
+ end
17
+
18
+ describe '#resource' do
19
+ it 'creates a TxResource from the table' do
20
+ resource = table.resource
21
+ expect(resource).to be_a(Txdb::TxResource)
22
+ expect(resource.project_slug).to eq('myproject')
23
+ expect(resource.resource_slug).to eq(
24
+ Txgh::Utils.slugify("#{database.database}-#{table.name}")
25
+ )
26
+ expect(resource.source_file).to eq(table.name)
27
+ expect(resource.source_lang).to eq('en')
28
+ end
29
+ end
30
+
31
+ describe '#read_content' do
32
+ let(:content) { { foo: 'bar' } }
33
+
34
+ it 'dumps the content in YAML format' do
35
+ expect(database.backend).to(
36
+ receive(:read_content_from).and_return(content)
37
+ )
38
+
39
+ expect(table.read_content).to eq(YAML.dump(content))
40
+ end
41
+ end
42
+
43
+ describe '#write_content' do
44
+ let(:content) { { foo: 'bar' } }
45
+ let(:locale) { 'es' }
46
+
47
+ it 'parses and writes the content to the database' do
48
+ expect(database.backend).to(
49
+ receive(:write_content_to) do |_, cont, loc|
50
+ expect(cont).to eq(content)
51
+ expect(loc).to eq(locale)
52
+ end
53
+ )
54
+
55
+ table.write_content(YAML.dump(content), locale)
56
+ end
57
+ end
58
+ end
data/spec/test.sqlite3 ADDED
Binary file
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_db'
3
+
4
+ include Txdb
5
+
6
+ describe TransifexProject, test_db: true do
7
+ let(:database) { TestDb.database }
8
+ let(:project) { database.transifex_project }
9
+
10
+ describe '#api' do
11
+ it 'returns a transifex api instance' do
12
+ expect(project.api).to be_a(Txgh::TransifexApi)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_db'
3
+
4
+ include Txdb
5
+
6
+ describe TxResource, test_db: true do
7
+ let(:database) { TestDb.database }
8
+ let(:table) { database.tables.first }
9
+ let(:resource) { table.resource }
10
+
11
+ it 'proxies methods to the underlying Txgh::TxResource' do
12
+ expect(resource.project_slug).to eq('myproject')
13
+ expect(resource.resource_slug).to(
14
+ eq(Txgh::Utils.slugify("#{database.database}-#{table.name}"))
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_db'
3
+ require 'spec_helpers/test_backend'
4
+
5
+ include Txdb
6
+
7
+ describe Uploader, test_db: true do
8
+ let(:database) { Txdb::Config.databases.first }
9
+ let(:uploader) { Uploader.new(database) }
10
+ let(:transifex_api) { double(:transifex_api) }
11
+
12
+ before(:each) do
13
+ allow(database.transifex_project).to(
14
+ receive(:api).and_return(transifex_api)
15
+ )
16
+ end
17
+
18
+ describe '#upload' do
19
+ it 'reads phrases from the database and uploads them to Transifex' do
20
+ expect(transifex_api).to receive(:create_or_update) do |resource, content|
21
+ expect(resource.project_slug).to eq('myproject')
22
+ expect(resource.resource_slug).to(
23
+ eq(Txgh::Utils.slugify("#{database.database}-#{database.tables.first.name}"))
24
+ )
25
+ end
26
+
27
+ expect { uploader.upload }.to(
28
+ change { TestBackend.reads.size }.from(0).to(1)
29
+ )
30
+
31
+ expect(TestBackend.reads.first).to eq(
32
+ table: database.tables.first.name
33
+ )
34
+ end
35
+ end
36
+ end