coupler 0.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitmodules +3 -0
- data/.rvmrc +1 -0
- data/.vimrc +40 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +71 -0
- data/LICENSE +20 -0
- data/NOTES +6 -0
- data/README.rdoc +18 -0
- data/Rakefile +42 -0
- data/TODO +11 -0
- data/VERSION +1 -0
- data/bin/coupler +7 -0
- data/db/.gitignore +6 -0
- data/db/migrate/001_initial_schema.rb +166 -0
- data/db/migrate/002_stub.rb +4 -0
- data/db/migrate/003_stub.rb +4 -0
- data/db/migrate/004_create_comparisons.rb +28 -0
- data/db/migrate/005_move_database_name.rb +19 -0
- data/db/migrate/006_upgrade_comparisons.rb +34 -0
- data/db/migrate/007_add_which_to_comparisons.rb +23 -0
- data/db/migrate/008_add_result_field_to_transformations.rb +33 -0
- data/db/migrate/009_add_generated_flag_to_fields.rb +13 -0
- data/db/migrate/010_create_imports.rb +24 -0
- data/db/migrate/011_add_primary_key_type.rb +13 -0
- data/db/migrate/012_add_transformed_with_to_resources.rb +13 -0
- data/db/migrate/013_add_run_count_to_scenarios.rb +13 -0
- data/db/migrate/014_add_last_accessed_at_to_some_tables.rb +13 -0
- data/db/migrate/015_add_run_number_to_results.rb +15 -0
- data/db/migrate/016_fix_scenario_run_count.rb +27 -0
- data/db/migrate/017_rename_comparison_columns.rb +14 -0
- data/db/migrate/018_fix_scenario_linkage_type.rb +8 -0
- data/db/migrate/019_add_columns_to_imports.rb +24 -0
- data/db/migrate/020_rename_import_columns.rb +12 -0
- data/db/migrate/021_add_fields_to_connections.rb +15 -0
- data/db/migrate/022_remove_database_name_from_resources.rb +11 -0
- data/features/connections.feature +28 -0
- data/features/matchers.feature +35 -0
- data/features/projects.feature +11 -0
- data/features/resources.feature +62 -0
- data/features/scenarios.feature +45 -0
- data/features/step_definitions/coupler_steps.rb +145 -0
- data/features/step_definitions/matchers_steps.rb +26 -0
- data/features/step_definitions/resources_steps.rb +12 -0
- data/features/step_definitions/scenarios_steps.rb +7 -0
- data/features/step_definitions/transformations_steps.rb +3 -0
- data/features/support/env.rb +128 -0
- data/features/transformations.feature +22 -0
- data/features/wizard.feature +10 -0
- data/gfx/coupler-header.svg +213 -0
- data/gfx/coupler-sidebar.svg +656 -0
- data/gfx/coupler.svg +184 -0
- data/gfx/icon.svg +75 -0
- data/lib/coupler/base.rb +63 -0
- data/lib/coupler/config.rb +128 -0
- data/lib/coupler/data_uploader.rb +20 -0
- data/lib/coupler/database.rb +31 -0
- data/lib/coupler/extensions/connections.rb +57 -0
- data/lib/coupler/extensions/exceptions.rb +58 -0
- data/lib/coupler/extensions/imports.rb +43 -0
- data/lib/coupler/extensions/jobs.rb +21 -0
- data/lib/coupler/extensions/matchers.rb +64 -0
- data/lib/coupler/extensions/projects.rb +62 -0
- data/lib/coupler/extensions/resources.rb +89 -0
- data/lib/coupler/extensions/results.rb +100 -0
- data/lib/coupler/extensions/scenarios.rb +50 -0
- data/lib/coupler/extensions/transformations.rb +70 -0
- data/lib/coupler/extensions/transformers.rb +58 -0
- data/lib/coupler/extensions.rb +16 -0
- data/lib/coupler/helpers.rb +121 -0
- data/lib/coupler/import_buffer.rb +48 -0
- data/lib/coupler/logger.rb +16 -0
- data/lib/coupler/models/common_model.rb +104 -0
- data/lib/coupler/models/comparison.rb +166 -0
- data/lib/coupler/models/connection.rb +59 -0
- data/lib/coupler/models/field.rb +55 -0
- data/lib/coupler/models/import.rb +238 -0
- data/lib/coupler/models/job.rb +42 -0
- data/lib/coupler/models/jobify.rb +17 -0
- data/lib/coupler/models/matcher.rb +36 -0
- data/lib/coupler/models/project.rb +40 -0
- data/lib/coupler/models/resource.rb +287 -0
- data/lib/coupler/models/result.rb +92 -0
- data/lib/coupler/models/scenario/runner.rb +357 -0
- data/lib/coupler/models/scenario.rb +115 -0
- data/lib/coupler/models/transformation.rb +117 -0
- data/lib/coupler/models/transformer/runner.rb +28 -0
- data/lib/coupler/models/transformer.rb +110 -0
- data/lib/coupler/models.rb +30 -0
- data/lib/coupler/runner.rb +76 -0
- data/lib/coupler/scheduler.rb +56 -0
- data/lib/coupler.rb +34 -0
- data/log/.gitignore +1 -0
- data/misc/README +5 -0
- data/misc/jruby-json.license +57 -0
- data/misc/rack-flash.license +22 -0
- data/script/dbconsole.rb +5 -0
- data/src/edu/vanderbilt/coupler/Main.java +116 -0
- data/src/edu/vanderbilt/coupler/jruby.properties +1 -0
- data/tasks/annotations.rake +84 -0
- data/tasks/db.rake +120 -0
- data/tasks/environment.rake +12 -0
- data/tasks/jeweler.rake +43 -0
- data/tasks/package.rake +58 -0
- data/tasks/rdoc.rake +13 -0
- data/tasks/test.rake +63 -0
- data/tasks/vendor.rake +43 -0
- data/test/README.txt +6 -0
- data/test/config.yml +9 -0
- data/test/coupler/models/test_import.rb +221 -0
- data/test/factories.rb +91 -0
- data/test/fixtures/duplicate-keys.csv +5 -0
- data/test/fixtures/no-headers.csv +50 -0
- data/test/fixtures/people.csv +51 -0
- data/test/fixtures/varying-row-size.csv +4 -0
- data/test/helper.rb +156 -0
- data/test/integration/extensions/test_connections.rb +80 -0
- data/test/integration/extensions/test_imports.rb +94 -0
- data/test/integration/extensions/test_jobs.rb +52 -0
- data/test/integration/extensions/test_matchers.rb +134 -0
- data/test/integration/extensions/test_projects.rb +82 -0
- data/test/integration/extensions/test_resources.rb +150 -0
- data/test/integration/extensions/test_results.rb +89 -0
- data/test/integration/extensions/test_scenarios.rb +88 -0
- data/test/integration/extensions/test_transformations.rb +113 -0
- data/test/integration/extensions/test_transformers.rb +80 -0
- data/test/integration/test_field.rb +45 -0
- data/test/integration/test_import.rb +78 -0
- data/test/integration/test_running_scenarios.rb +379 -0
- data/test/integration/test_transformation.rb +56 -0
- data/test/integration/test_transforming.rb +154 -0
- data/test/table_sets.rb +76 -0
- data/test/unit/models/test_common_model.rb +130 -0
- data/test/unit/models/test_comparison.rb +619 -0
- data/test/unit/models/test_connection.rb +115 -0
- data/test/unit/models/test_field.rb +99 -0
- data/test/unit/models/test_import.rb +130 -0
- data/test/unit/models/test_job.rb +115 -0
- data/test/unit/models/test_matcher.rb +82 -0
- data/test/unit/models/test_project.rb +102 -0
- data/test/unit/models/test_resource.rb +564 -0
- data/test/unit/models/test_result.rb +90 -0
- data/test/unit/models/test_scenario.rb +199 -0
- data/test/unit/models/test_transformation.rb +193 -0
- data/test/unit/models/test_transformer.rb +188 -0
- data/test/unit/test_base.rb +60 -0
- data/test/unit/test_data_uploader.rb +27 -0
- data/test/unit/test_database.rb +23 -0
- data/test/unit/test_helpers.rb +58 -0
- data/test/unit/test_logger.rb +10 -0
- data/test/unit/test_models.rb +12 -0
- data/test/unit/test_runner.rb +76 -0
- data/test/unit/test_scheduler.rb +66 -0
- data/uploads/.gitignore +2 -0
- data/vendor/java/.gitignore +5 -0
- data/webroot/public/css/960.css +1 -0
- data/webroot/public/css/dataTables.css +1057 -0
- data/webroot/public/css/jquery-ui.css +572 -0
- data/webroot/public/css/jquery.treeview.css +68 -0
- data/webroot/public/css/reset.css +1 -0
- data/webroot/public/css/style.css +504 -0
- data/webroot/public/css/text.css +1 -0
- data/webroot/public/favicon.ico +0 -0
- data/webroot/public/images/12_col.gif +0 -0
- data/webroot/public/images/16_col.gif +0 -0
- data/webroot/public/images/add.png +0 -0
- data/webroot/public/images/ajax-loader.gif +0 -0
- data/webroot/public/images/cog.png +0 -0
- data/webroot/public/images/coupler.png +0 -0
- data/webroot/public/images/foo.png +0 -0
- data/webroot/public/images/hammer.png +0 -0
- data/webroot/public/images/header.png +0 -0
- data/webroot/public/images/home.gif +0 -0
- data/webroot/public/images/jobs.gif +0 -0
- data/webroot/public/images/sidebar-bottom.png +0 -0
- data/webroot/public/images/sidebar.png +0 -0
- data/webroot/public/images/treeview-default-line.gif +0 -0
- data/webroot/public/images/treeview-default.gif +0 -0
- data/webroot/public/images/ui-anim_basic_16x16.gif +0 -0
- data/webroot/public/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/webroot/public/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/webroot/public/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/webroot/public/images/ui-bg_highlight-hard_30_565356_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-hard_75_888588_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_30_6e3b3a_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_35_8e8b8e_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/webroot/public/images/ui-icons_222222_256x240.png +0 -0
- data/webroot/public/images/ui-icons_2e83ff_256x240.png +0 -0
- data/webroot/public/images/ui-icons_454545_256x240.png +0 -0
- data/webroot/public/images/ui-icons_888888_256x240.png +0 -0
- data/webroot/public/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/webroot/public/images/ui-icons_ffffff_256x240.png +0 -0
- data/webroot/public/js/ajaxupload.js +673 -0
- data/webroot/public/js/application.js +40 -0
- data/webroot/public/js/jquery-ui.combobox.js +98 -0
- data/webroot/public/js/jquery-ui.js +9867 -0
- data/webroot/public/js/jquery-ui.min.js +559 -0
- data/webroot/public/js/jquery.dataTables.min.js +587 -0
- data/webroot/public/js/jquery.min.js +154 -0
- data/webroot/public/js/jquery.timeago.js +140 -0
- data/webroot/public/js/jquery.tooltip.min.js +19 -0
- data/webroot/public/js/jquery.treeview.min.js +15 -0
- data/webroot/public/js/resource.js +11 -0
- data/webroot/public/js/results.js +56 -0
- data/webroot/public/js/transformations.js +95 -0
- data/webroot/views/connections/index.erb +5 -0
- data/webroot/views/connections/list.erb +34 -0
- data/webroot/views/connections/new.erb +55 -0
- data/webroot/views/connections/show.erb +36 -0
- data/webroot/views/imports/edit.erb +60 -0
- data/webroot/views/imports/form.erb +81 -0
- data/webroot/views/imports/new.erb +89 -0
- data/webroot/views/index.erb +12 -0
- data/webroot/views/jobs/index.erb +7 -0
- data/webroot/views/jobs/list.erb +24 -0
- data/webroot/views/layout.erb +38 -0
- data/webroot/views/matchers/form.erb +250 -0
- data/webroot/views/matchers/list.erb +32 -0
- data/webroot/views/projects/form.erb +14 -0
- data/webroot/views/projects/index.erb +96 -0
- data/webroot/views/projects/show.erb +24 -0
- data/webroot/views/resources/edit.erb +88 -0
- data/webroot/views/resources/index.erb +5 -0
- data/webroot/views/resources/list.erb +27 -0
- data/webroot/views/resources/new.erb +121 -0
- data/webroot/views/resources/show.erb +86 -0
- data/webroot/views/resources/transform.erb +2 -0
- data/webroot/views/results/csv.erb +12 -0
- data/webroot/views/results/details.erb +15 -0
- data/webroot/views/results/index.erb +2 -0
- data/webroot/views/results/list.erb +22 -0
- data/webroot/views/results/record.erb +24 -0
- data/webroot/views/results/show.erb +68 -0
- data/webroot/views/scenarios/index.erb +5 -0
- data/webroot/views/scenarios/list.erb +20 -0
- data/webroot/views/scenarios/new.erb +99 -0
- data/webroot/views/scenarios/run.erb +2 -0
- data/webroot/views/scenarios/show.erb +50 -0
- data/webroot/views/sidebar.erb +106 -0
- data/webroot/views/transformations/create.erb +115 -0
- data/webroot/views/transformations/for.erb +16 -0
- data/webroot/views/transformations/index.erb +2 -0
- data/webroot/views/transformations/list.erb +29 -0
- data/webroot/views/transformations/new.erb +126 -0
- data/webroot/views/transformations/preview.erb +46 -0
- data/webroot/views/transformers/edit.erb +6 -0
- data/webroot/views/transformers/form.erb +58 -0
- data/webroot/views/transformers/index.erb +2 -0
- data/webroot/views/transformers/list.erb +25 -0
- data/webroot/views/transformers/new.erb +5 -0
- data/webroot/views/transformers/preview.erb +23 -0
- data/webroot/views/transformers/show.erb +0 -0
- metadata +558 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
module Models
|
5
|
+
class TestScenario < Coupler::Test::UnitTest
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@project = stub('project', :pk => 1, :id => 1, :associations => {})
|
9
|
+
@resource_1 = stub('resource 1', :pk => 123, :id => 123, :associations => {}, :status => "ok")
|
10
|
+
@resource_2 = stub('resource 2', :pk => 456, :id => 456, :associations => {}, :status => "ok")
|
11
|
+
@matcher = stub('matcher', :cross_match? => false, :associations => {})
|
12
|
+
end
|
13
|
+
|
14
|
+
def new_scenario(attribs = {})
|
15
|
+
values = {
|
16
|
+
:name => 'Foo bar',
|
17
|
+
:project => @project,
|
18
|
+
:resource_1 => @resource_1,
|
19
|
+
:matcher => @matcher
|
20
|
+
}.update(attribs)
|
21
|
+
matcher = values.delete(:matcher)
|
22
|
+
s = Scenario.new(values)
|
23
|
+
if values[:project]
|
24
|
+
s.stubs(:project_dataset).returns(stub({:all => [values[:project]]}))
|
25
|
+
end
|
26
|
+
if values[:resource_1]
|
27
|
+
s.stubs(:resource_1_dataset).returns(stub({:all => [values[:resource_1]]}))
|
28
|
+
end
|
29
|
+
if values[:resource_2]
|
30
|
+
s.stubs(:resource_2_dataset).returns(stub({:all => [values[:resource_2]]}))
|
31
|
+
end
|
32
|
+
if matcher
|
33
|
+
s.stubs(:matcher_dataset).returns(stub({:all => [matcher]}))
|
34
|
+
end
|
35
|
+
s
|
36
|
+
end
|
37
|
+
|
38
|
+
test "sequel model" do
|
39
|
+
assert_equal ::Sequel::Model, Scenario.superclass
|
40
|
+
assert_equal :scenarios, Scenario.table_name
|
41
|
+
end
|
42
|
+
|
43
|
+
test "many to one project" do
|
44
|
+
assert_respond_to Scenario.new, :project
|
45
|
+
end
|
46
|
+
|
47
|
+
test "many to one resource 1" do
|
48
|
+
assert_respond_to Scenario.new, :resource_1
|
49
|
+
end
|
50
|
+
|
51
|
+
test "many to one resource 2" do
|
52
|
+
assert_respond_to Scenario.new, :resource_2
|
53
|
+
end
|
54
|
+
|
55
|
+
test "resources" do
|
56
|
+
scenario = Scenario.new(:resource_1 => @resource_1)
|
57
|
+
assert_equal [@resource_1], scenario.resources
|
58
|
+
scenario.resource_2 = @resource_2
|
59
|
+
assert_equal [@resource_1, @resource_2], scenario.resources
|
60
|
+
end
|
61
|
+
|
62
|
+
test "one to one matcher" do
|
63
|
+
assert_respond_to Scenario.new, :matcher
|
64
|
+
end
|
65
|
+
|
66
|
+
test "one to many jobs" do
|
67
|
+
assert_respond_to Scenario.new, :jobs
|
68
|
+
end
|
69
|
+
|
70
|
+
test "one to many results" do
|
71
|
+
assert_respond_to Scenario.new, :results
|
72
|
+
end
|
73
|
+
|
74
|
+
test "requires name" do
|
75
|
+
scenario = new_scenario(:name => nil)
|
76
|
+
scenario.expects(:validates_presence).with(:name).returns(false)
|
77
|
+
scenario.valid?
|
78
|
+
end
|
79
|
+
|
80
|
+
test "requires unique name across projects" do
|
81
|
+
scenario = new_scenario
|
82
|
+
scenario.expects(:validates_unique).with([:name, :project_id]).returns(false)
|
83
|
+
scenario.valid?
|
84
|
+
end
|
85
|
+
|
86
|
+
test "requires at least one resource" do
|
87
|
+
scenario = new_scenario(:resource_1 => nil)
|
88
|
+
assert !scenario.valid?
|
89
|
+
end
|
90
|
+
|
91
|
+
test "sets slug from name" do
|
92
|
+
scenario = new_scenario.save!
|
93
|
+
assert_equal "foo_bar", scenario.slug
|
94
|
+
end
|
95
|
+
|
96
|
+
test "setting one resource with resource_ids=" do
|
97
|
+
scenario = new_scenario(:resource_1 => nil, :resource_ids => [123])
|
98
|
+
resource_1 = @resource_1 # so mocha can resolve it
|
99
|
+
@project.expects(:resources_dataset).returns(mock {
|
100
|
+
expects(:filter).with(:id => [123]).returns(self)
|
101
|
+
expects(:all).returns([resource_1])
|
102
|
+
})
|
103
|
+
scenario.save!
|
104
|
+
assert_equal 123, scenario.resource_1_id
|
105
|
+
end
|
106
|
+
|
107
|
+
test "setting two resources with resource ids=" do
|
108
|
+
scenario = new_scenario(:resource_1 => nil, :resource_ids => [123, 456])
|
109
|
+
resource_1 = @resource_1 # so mocha can resolve it
|
110
|
+
resource_2 = @resource_2
|
111
|
+
@project.expects(:resources_dataset).returns(mock {
|
112
|
+
expects(:filter).with(:id => [123, 456]).returns(self)
|
113
|
+
expects(:all).returns([resource_1, resource_2])
|
114
|
+
})
|
115
|
+
scenario.save!
|
116
|
+
assert_equal 123, scenario.resource_1_id
|
117
|
+
assert_equal 456, scenario.resource_2_id
|
118
|
+
end
|
119
|
+
|
120
|
+
test "doesn't run when there is no matcher" do
|
121
|
+
scenario = new_scenario(:matcher => nil).save!
|
122
|
+
assert_raises(Scenario::NoMatcherError) { scenario.run! }
|
123
|
+
end
|
124
|
+
|
125
|
+
test "doesn't run when resources are out of date" do
|
126
|
+
scenario = new_scenario.save!
|
127
|
+
@resource_1.expects(:status).returns("out_of_date")
|
128
|
+
assert_raises(Scenario::ResourcesOutOfDateError) { scenario.run! }
|
129
|
+
end
|
130
|
+
|
131
|
+
test "status with no matcher" do
|
132
|
+
scenario = new_scenario(:matcher => nil).save!
|
133
|
+
assert_equal "no_matcher", scenario.status
|
134
|
+
end
|
135
|
+
|
136
|
+
test "status with matcher" do
|
137
|
+
scenario = new_scenario.save!
|
138
|
+
assert_equal "ok", scenario.status
|
139
|
+
end
|
140
|
+
|
141
|
+
test "status with outdated resources" do
|
142
|
+
scenario = new_scenario.save!
|
143
|
+
@resource_1.expects(:status).returns("out_of_date")
|
144
|
+
assert_equal "resources_out_of_date", scenario.status
|
145
|
+
end
|
146
|
+
|
147
|
+
test "linkage type with one resource" do
|
148
|
+
scenario = new_scenario.save!
|
149
|
+
assert_equal "self-linkage", scenario.linkage_type
|
150
|
+
end
|
151
|
+
|
152
|
+
test "linkage type with two resources" do
|
153
|
+
scenario = new_scenario(:resource_2 => @resource_2).save!
|
154
|
+
assert_equal "dual-linkage", scenario.linkage_type
|
155
|
+
end
|
156
|
+
|
157
|
+
test "matcher with cross match makes cross-linkage" do
|
158
|
+
scenario = new_scenario.save!
|
159
|
+
@matcher.stubs(:cross_match?).returns(true)
|
160
|
+
scenario.set_linkage_type
|
161
|
+
assert_equal "cross-linkage", scenario.linkage_type
|
162
|
+
end
|
163
|
+
|
164
|
+
test "jobified" do
|
165
|
+
assert Scenario.ancestors.include?(Jobify)
|
166
|
+
end
|
167
|
+
|
168
|
+
#def test_destroying
|
169
|
+
#pend
|
170
|
+
#end
|
171
|
+
|
172
|
+
test "local database" do
|
173
|
+
scenario = new_scenario.save!
|
174
|
+
Base.expects(:connection_string).with("scenario_#{scenario.id}").returns("foo")
|
175
|
+
db = mock('scenario db')
|
176
|
+
Sequel.expects(:connect).with('foo', instance_of(Hash)).returns(db)
|
177
|
+
assert_equal db, scenario.local_database
|
178
|
+
end
|
179
|
+
|
180
|
+
#def test_deletes_local_database_after_destroy
|
181
|
+
#pend
|
182
|
+
#end
|
183
|
+
|
184
|
+
#def test_freezes_models_on_run
|
185
|
+
#flunk
|
186
|
+
#end
|
187
|
+
|
188
|
+
test "count by project" do
|
189
|
+
ds = mock('dataset') do
|
190
|
+
expects(:naked).returns(self)
|
191
|
+
expects(:group_and_count).with(:project_id).returns(self)
|
192
|
+
expects(:to_hash).with(:project_id, :count).returns({ 1 => 1 })
|
193
|
+
end
|
194
|
+
Scenario.expects(:dataset).returns(ds)
|
195
|
+
assert_equal({1 => 1}, Scenario.count_by_project)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
module Models
|
5
|
+
class TestTransformation < Coupler::Test::UnitTest
|
6
|
+
def new_transformation(attribs = {})
|
7
|
+
values = {
|
8
|
+
:transformer => @transformer,
|
9
|
+
:resource => @resource,
|
10
|
+
:source_field => @source_field
|
11
|
+
}.update(attribs)
|
12
|
+
t = Transformation.new(values)
|
13
|
+
if values[:transformer]
|
14
|
+
t.stubs(:transformer_dataset).returns(stub({:all => [values[:transformer]]}))
|
15
|
+
end
|
16
|
+
if values[:source_field]
|
17
|
+
t.stubs(:source_field_dataset).returns(stub({:all => [values[:source_field]]}))
|
18
|
+
if values[:resource]
|
19
|
+
values[:resource].stubs(:fields_dataset).returns(stub('fields dataset') {
|
20
|
+
stubs(:[]).with(:id => values[:source_field].id).returns(values[:source_field])
|
21
|
+
})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
if values[:result_field]
|
25
|
+
t.stubs(:result_field_dataset).returns(stub({:all => [values[:result_field]]}))
|
26
|
+
end
|
27
|
+
if values[:resource]
|
28
|
+
t.stubs(:resource_dataset).returns(stub({:all => [values[:resource]]}))
|
29
|
+
values[:resource].stubs(:fields_dataset).returns(stub('fields dataset') {
|
30
|
+
stubs(:[]).returns(nil)
|
31
|
+
if values[:source_field]
|
32
|
+
stubs(:[]).with(:id => values[:source_field].id).returns(values[:source_field])
|
33
|
+
end
|
34
|
+
if values[:result_field]
|
35
|
+
stubs(:[]).with(:id => values[:result_field].id).returns(values[:result_field])
|
36
|
+
end
|
37
|
+
})
|
38
|
+
end
|
39
|
+
t
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup
|
43
|
+
super
|
44
|
+
@resource = stub('resource', :pk => 3, :id => 3, :associations => {}, :refresh_fields! => nil)
|
45
|
+
@transformer = stub('transformer', {
|
46
|
+
:pk => 1, :id => 1, :associations => {},
|
47
|
+
:allowed_types => %w{string}, :name => "foobar"
|
48
|
+
})
|
49
|
+
@source_field = stub('source_field', {
|
50
|
+
:pk => 7, :id => 7, :associations => {},
|
51
|
+
:final_type => 'string', :name => 'first_name'
|
52
|
+
})
|
53
|
+
@result_field = stub('result_field', {
|
54
|
+
:pk => 8, :id => 8, :associations => {},
|
55
|
+
:final_type => 'string', :name => 'new_first_name'
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
test "sequel model" do
|
60
|
+
assert_equal ::Sequel::Model, Transformation.superclass
|
61
|
+
assert_equal :transformations, Transformation.table_name
|
62
|
+
end
|
63
|
+
|
64
|
+
test "many to one resource" do
|
65
|
+
assert_respond_to Transformation.new, :resource
|
66
|
+
end
|
67
|
+
|
68
|
+
test "many to one source field" do
|
69
|
+
assert_respond_to Transformation.new, :source_field
|
70
|
+
end
|
71
|
+
|
72
|
+
test "many to one result field" do
|
73
|
+
assert_respond_to Transformation.new, :result_field
|
74
|
+
end
|
75
|
+
|
76
|
+
test "requires resource id" do
|
77
|
+
transformation = new_transformation(:resource => nil)
|
78
|
+
assert !transformation.valid?
|
79
|
+
end
|
80
|
+
|
81
|
+
test "requires existing transformer or nested attributes" do
|
82
|
+
transformation = new_transformation(:transformer => nil)
|
83
|
+
assert !transformation.valid?
|
84
|
+
end
|
85
|
+
|
86
|
+
test "requires correct field type" do
|
87
|
+
@source_field.stubs(:final_type).returns('integer')
|
88
|
+
transformation = new_transformation
|
89
|
+
assert !transformation.valid?
|
90
|
+
end
|
91
|
+
|
92
|
+
test "requires existing source field" do
|
93
|
+
transformation = new_transformation(:source_field => nil, :source_field_id => 1337)
|
94
|
+
assert !transformation.valid?
|
95
|
+
end
|
96
|
+
|
97
|
+
test "result field same as source field by default" do
|
98
|
+
transformation = new_transformation.save!
|
99
|
+
assert_equal transformation.result_field_id, @source_field.id
|
100
|
+
end
|
101
|
+
|
102
|
+
test "requires existing result field or nested attributes" do
|
103
|
+
transformation = new_transformation(:result_field_id => 1337)
|
104
|
+
assert !transformation.valid?
|
105
|
+
end
|
106
|
+
|
107
|
+
test "accepts nested attributes for transformer" do
|
108
|
+
assert_respond_to Transformation.new, :transformer_attributes=
|
109
|
+
end
|
110
|
+
|
111
|
+
test "transform with same source and result field" do
|
112
|
+
transformation = new_transformation(:result_field => @source_field).save!
|
113
|
+
|
114
|
+
data = {:id => 1, :first_name => "Peter"}
|
115
|
+
expected = stub("result")
|
116
|
+
@transformer.expects(:transform).with(data, { :in => :first_name, :out => :first_name }).returns(expected)
|
117
|
+
|
118
|
+
assert_equal expected, transformation.transform(data)
|
119
|
+
end
|
120
|
+
|
121
|
+
test "transform with differing source and result field" do
|
122
|
+
transformation = new_transformation(:result_field => @result_field)
|
123
|
+
|
124
|
+
data = {:id => 1, :first_name => "Peter"}
|
125
|
+
expected = stub("result")
|
126
|
+
transformation.transformer.expects(:transform).with(data, { :in => :first_name, :out => :new_first_name }).returns(expected)
|
127
|
+
|
128
|
+
assert_equal expected, transformation.transform(data)
|
129
|
+
end
|
130
|
+
|
131
|
+
test "field changes" do
|
132
|
+
transformation = new_transformation.save!
|
133
|
+
result = stub('result')
|
134
|
+
@transformer.expects(:field_changes).with(@source_field).returns(result)
|
135
|
+
assert_equal result, transformation.field_changes
|
136
|
+
end
|
137
|
+
|
138
|
+
test "updates resource fields on save" do
|
139
|
+
transformation = new_transformation
|
140
|
+
@resource.expects(:refresh_fields!)
|
141
|
+
transformation.save!
|
142
|
+
end
|
143
|
+
|
144
|
+
#def test_updates_resource_fields_on_destroy
|
145
|
+
#pend
|
146
|
+
#end
|
147
|
+
|
148
|
+
test "deletes orphaned result field on destroy" do
|
149
|
+
@result_field.stubs(:is_generated).returns(true)
|
150
|
+
@result_field.stubs(:scenarios_dataset).returns(stub(:count => 0))
|
151
|
+
transformation = new_transformation(:result_field => @result_field).save!
|
152
|
+
Transformation.expects(:filter).with(:result_field_id => 8).returns(mock(:count => 0))
|
153
|
+
@result_field.expects(:destroy)
|
154
|
+
transformation.destroy
|
155
|
+
end
|
156
|
+
|
157
|
+
test "does not delete result field in use by other transformation" do
|
158
|
+
@result_field.stubs(:is_generated).returns(true)
|
159
|
+
@result_field.stubs(:scenarios_dataset).returns(stub(:count => 0))
|
160
|
+
transformation = new_transformation(:result_field => @result_field).save!
|
161
|
+
Transformation.expects(:filter).with(:result_field_id => 8).returns(mock(:count => 1))
|
162
|
+
@result_field.expects(:destroy).never
|
163
|
+
transformation.destroy
|
164
|
+
end
|
165
|
+
|
166
|
+
test "prevents deletion if result field is in use by scenario" do
|
167
|
+
@result_field.stubs(:is_generated).returns(true)
|
168
|
+
@result_field.stubs(:scenarios_dataset).returns(stub(:count => 1))
|
169
|
+
transformation = new_transformation(:result_field => @result_field).save!
|
170
|
+
assert !transformation.destroy
|
171
|
+
end
|
172
|
+
|
173
|
+
test "prevents deletion unless in last position" do
|
174
|
+
transformation_1 = new_transformation(:position => 1).save!
|
175
|
+
transformation_2 = new_transformation(:position => 2).save!
|
176
|
+
assert !transformation_1.destroy
|
177
|
+
assert_not_nil Transformation[:id => transformation_1.id]
|
178
|
+
end
|
179
|
+
|
180
|
+
test "sets position by resource" do
|
181
|
+
resource_1 = stub('resource', :pk => 1, :id => 1, :associations => {}, :refresh_fields! => nil)
|
182
|
+
resource_2 = stub('resource', :pk => 2, :id => 2, :associations => {}, :refresh_fields! => nil)
|
183
|
+
|
184
|
+
xformation_1 = new_transformation(:resource => resource_1).save!
|
185
|
+
xformation_2 = new_transformation(:resource => resource_1).save!
|
186
|
+
xformation_3 = new_transformation(:resource => resource_2).save!
|
187
|
+
assert_equal 1, xformation_1.position
|
188
|
+
assert_equal 2, xformation_2.position
|
189
|
+
assert_equal 1, xformation_3.position
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
module Models
|
5
|
+
class TestTransformer < Coupler::Test::UnitTest
|
6
|
+
def new_transformer(attribs = {})
|
7
|
+
values = {
|
8
|
+
:name => "foo",
|
9
|
+
:code => "value",
|
10
|
+
:allowed_types => %w{string integer datetime},
|
11
|
+
:result_type => 'same'
|
12
|
+
}.update(attribs)
|
13
|
+
Transformer.new(values)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "sequel model" do
|
17
|
+
assert_equal ::Sequel::Model, Transformer.superclass
|
18
|
+
assert_equal :transformers, Transformer.table_name
|
19
|
+
end
|
20
|
+
|
21
|
+
test "requires name" do
|
22
|
+
xformer = new_transformer(:name => nil)
|
23
|
+
assert !xformer.valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
test "requires unique name" do
|
27
|
+
new_transformer(:name => "foobar").save!
|
28
|
+
xformer = new_transformer(:name => "foobar")
|
29
|
+
assert !xformer.valid?
|
30
|
+
end
|
31
|
+
|
32
|
+
test "serializes allowed types" do
|
33
|
+
new_transformer.save!
|
34
|
+
xformer = Transformer[:name => "foo"]
|
35
|
+
assert_equal %w{string integer datetime}, xformer.allowed_types
|
36
|
+
end
|
37
|
+
|
38
|
+
test "requires allowed types" do
|
39
|
+
xformer = new_transformer(:allowed_types => nil)
|
40
|
+
assert !xformer.valid?
|
41
|
+
end
|
42
|
+
|
43
|
+
test "requires valid allowed types" do
|
44
|
+
xformer = new_transformer(:allowed_types => %w{blah})
|
45
|
+
assert !xformer.valid?
|
46
|
+
end
|
47
|
+
|
48
|
+
test "requires result type" do
|
49
|
+
xformer = new_transformer(:result_type => nil)
|
50
|
+
assert !xformer.valid?
|
51
|
+
end
|
52
|
+
|
53
|
+
test "requires valid result type" do
|
54
|
+
xformer = new_transformer(:result_type => "blah")
|
55
|
+
assert !xformer.valid?
|
56
|
+
end
|
57
|
+
|
58
|
+
test "special result type" do
|
59
|
+
xformer = new_transformer(:result_type => "same")
|
60
|
+
assert xformer.valid?
|
61
|
+
end
|
62
|
+
|
63
|
+
test "requires code" do
|
64
|
+
xformer = new_transformer(:code => nil)
|
65
|
+
assert !xformer.valid?
|
66
|
+
end
|
67
|
+
|
68
|
+
test "requires parseable code" do
|
69
|
+
xformer = new_transformer(:code => "foo(")
|
70
|
+
assert !xformer.valid?
|
71
|
+
end
|
72
|
+
|
73
|
+
test "no-op transform" do
|
74
|
+
xformer = new_transformer.save!
|
75
|
+
original = {:id => 1, :first_name => "Golan", :last_name => "Trevize"}
|
76
|
+
expected = original.dup
|
77
|
+
result = xformer.transform(original, { :in => :first_name, :out => :first_name })
|
78
|
+
assert_equal expected, result
|
79
|
+
end
|
80
|
+
|
81
|
+
test "transform new field" do
|
82
|
+
xformer = new_transformer(:code => "value.downcase", :allowed_types => %w{string}).save!
|
83
|
+
original = {:id => 1, :first_name => "Golan", :last_name => "Trevize"}
|
84
|
+
expected = original.merge(:first_name_small => "golan")
|
85
|
+
result = xformer.transform(original.dup, { :in => :first_name, :out => :first_name_small })
|
86
|
+
assert_equal expected, result
|
87
|
+
end
|
88
|
+
|
89
|
+
test "preview downcaser" do
|
90
|
+
xformer = new_transformer({
|
91
|
+
:name => "downcaser", :code => "value.to_s.downcase",
|
92
|
+
:allowed_types => %w{integer string datetime},
|
93
|
+
:result_type => "string"
|
94
|
+
})
|
95
|
+
now = Time.now
|
96
|
+
Timecop.freeze(now) do
|
97
|
+
expected = {
|
98
|
+
'integer' => {:in => 123, :out => "123"},
|
99
|
+
'string' => {:in => "Test", :out => "test"},
|
100
|
+
'datetime' => {:in => now, :out => now.to_s.downcase},
|
101
|
+
'success' => true
|
102
|
+
}
|
103
|
+
assert_equal expected, xformer.preview
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
test "preview fails if invalid" do
|
108
|
+
assert_nil Transformer.new.preview
|
109
|
+
end
|
110
|
+
|
111
|
+
test "preview code error returns exception" do
|
112
|
+
xformer = new_transformer({
|
113
|
+
:name => "downcaser", :code => "value.downcase",
|
114
|
+
:allowed_types => %w{integer string datetime},
|
115
|
+
:result_type => "string"
|
116
|
+
})
|
117
|
+
now = Time.now
|
118
|
+
Timecop.freeze(now) do
|
119
|
+
expected = {
|
120
|
+
'integer' => {:in => 123, :out => Exception},
|
121
|
+
'string' => {:in => "Test", :out => "test"},
|
122
|
+
'datetime' => {:in => now, :out => Exception},
|
123
|
+
'success' => false
|
124
|
+
}
|
125
|
+
assert expected === xformer.preview
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
test "requires successful preview" do
|
130
|
+
xformer = new_transformer({
|
131
|
+
:name => "downcaser", :code => "value.downcase",
|
132
|
+
:allowed_types => %w{integer string datetime},
|
133
|
+
:result_type => "string"
|
134
|
+
})
|
135
|
+
assert !xformer.valid?
|
136
|
+
end
|
137
|
+
|
138
|
+
test "requires correct result type" do
|
139
|
+
xformer = new_transformer({
|
140
|
+
:name => "stringify", :code => "value.to_i",
|
141
|
+
:allowed_types => %w{integer string datetime},
|
142
|
+
:result_type => "string"
|
143
|
+
})
|
144
|
+
assert !xformer.valid?
|
145
|
+
end
|
146
|
+
|
147
|
+
test "requires same result type" do
|
148
|
+
xformer = new_transformer({
|
149
|
+
:name => "stringify", :code => "value.to_i",
|
150
|
+
:allowed_types => %w{integer string datetime},
|
151
|
+
:result_type => "same"
|
152
|
+
})
|
153
|
+
assert !xformer.valid?
|
154
|
+
end
|
155
|
+
|
156
|
+
test "allows nil return value" do
|
157
|
+
xformer = new_transformer({
|
158
|
+
:name => "nullify", :code => "nil",
|
159
|
+
:allowed_types => %w{integer string datetime},
|
160
|
+
:result_type => "same"
|
161
|
+
})
|
162
|
+
assert xformer.valid?
|
163
|
+
end
|
164
|
+
|
165
|
+
test "field changes with no type changes" do
|
166
|
+
field = stub('field', :id => 1)
|
167
|
+
transformer = new_transformer({
|
168
|
+
:allowed_types => %w{integer datetime string},
|
169
|
+
:result_type => 'same', :code => 'value'
|
170
|
+
}).save!
|
171
|
+
assert_equal({ field.id => { } }, transformer.field_changes(field))
|
172
|
+
end
|
173
|
+
|
174
|
+
test "field changes to integer" do
|
175
|
+
field = stub('field', :id => 1)
|
176
|
+
transformer = new_transformer({
|
177
|
+
:allowed_types => %w{integer datetime string},
|
178
|
+
:result_type => 'integer', :code => 'value.to_i'
|
179
|
+
}).save!
|
180
|
+
assert_equal({ field.id => { :db_type => "int(11)", :type => :integer } }, transformer.field_changes(field))
|
181
|
+
end
|
182
|
+
|
183
|
+
#def test_should_handle_empty_values
|
184
|
+
#pend
|
185
|
+
#end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
class TestBase < Coupler::Test::UnitTest
|
5
|
+
def test_subclasses_sinatra_base
|
6
|
+
assert_equal Sinatra::Base, Coupler::Base.superclass
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_index_when_no_projects
|
10
|
+
get "/"
|
11
|
+
assert last_response.ok?
|
12
|
+
assert_match /Getting Started/, last_response.body
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_redirect_when_projects_exist
|
16
|
+
project = Factory(:project)
|
17
|
+
get "/"
|
18
|
+
assert last_response.redirect?
|
19
|
+
assert_equal "http://example.org/projects", last_response['location']
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_db_path
|
23
|
+
env = Base.settings.environment
|
24
|
+
begin
|
25
|
+
Base.set :environment, :production
|
26
|
+
expected = File.join(Base.settings.data_path, 'db', 'production', 'ponies')
|
27
|
+
assert_equal expected, Base.db_path("ponies")
|
28
|
+
ensure
|
29
|
+
Base.set :environment, env
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_connection_string
|
34
|
+
env = Base.settings.environment
|
35
|
+
begin
|
36
|
+
Base.set :environment, :production
|
37
|
+
expected = "jdbc:h2:#{File.join(Base.settings.data_path, 'db', 'production', 'ponies')};IGNORECASE=TRUE"
|
38
|
+
assert_equal expected, Base.connection_string("ponies")
|
39
|
+
ensure
|
40
|
+
Base.set :environment, env
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_upload_path
|
45
|
+
env = Base.settings.environment
|
46
|
+
begin
|
47
|
+
Base.set :environment, :production
|
48
|
+
expected = File.join(Base.settings.data_path, 'uploads', 'production')
|
49
|
+
assert_equal expected, Base.upload_path
|
50
|
+
ensure
|
51
|
+
Base.set :environment, env
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_log_path
|
56
|
+
expected = File.join(Base.settings.data_path, 'log')
|
57
|
+
assert_equal expected, Base.log_path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
class TestDataUploader < Coupler::Test::UnitTest
|
5
|
+
def test_carrierwave_subclass
|
6
|
+
assert_equal CarrierWave::Uploader::Base, DataUploader.superclass
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_store_dir_same_as_upload_path
|
10
|
+
Base.expects(:upload_path).returns("/path/to/uploads")
|
11
|
+
uploader = DataUploader.new
|
12
|
+
assert_equal "/path/to/uploads", uploader.store_dir
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_cache_dir_uses_upload_path
|
16
|
+
Base.expects(:upload_path).returns("/path/to/uploads")
|
17
|
+
uploader = DataUploader.new
|
18
|
+
assert_equal "/path/to/uploads/tmp", uploader.cache_dir
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_filename_uniqueness
|
22
|
+
uploader = DataUploader.new
|
23
|
+
uploader.store!(fixture_file_upload('people.csv'))
|
24
|
+
assert_match /^people-[a-f0-9]+.csv$/, uploader.filename
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Coupler
|
4
|
+
class TestDatabase < Coupler::Test::UnitTest
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@database = Coupler::Database.instance
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_connection
|
11
|
+
assert_kind_of Sequel::JDBC::Database, @database.__getobj__
|
12
|
+
|
13
|
+
expected = Base.connection_string('coupler')
|
14
|
+
assert_equal expected, @database.uri
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_migrate
|
18
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "db", "migrate"))
|
19
|
+
Sequel::Migrator.expects(:apply).with(@database.__getobj__, dir)
|
20
|
+
@database.migrate!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|