coupler 0.0.1-java
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.
- 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,13 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
[:projects, :projects_versions, :connections, :transformers, :transformers_versions].each do |name|
|
|
4
|
+
alter_table(name) { add_column(:last_accessed_at, Time) }
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
down do
|
|
9
|
+
[:projects, :projects_versions, :connections, :transformers, :transformers_versions].each do |name|
|
|
10
|
+
alter_table(name) { drop_column(:last_accessed_at) }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
alter_table(:results) do
|
|
4
|
+
drop_column(:score_set_id)
|
|
5
|
+
add_column(:run_number, Integer)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
down do
|
|
10
|
+
alter_table(:results) do
|
|
11
|
+
drop_column(:run_number)
|
|
12
|
+
add_column(:score_set_id, Integer)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
# Fix scenario run_count
|
|
4
|
+
scenarios = self[:scenarios]
|
|
5
|
+
ds = scenarios.join(:results, :scenario_id => :id)
|
|
6
|
+
run_counts = ds.group_and_count(:scenario_id).all
|
|
7
|
+
run_counts.each do |row|
|
|
8
|
+
run_count = row[:count] > 1 ? 1 : 0
|
|
9
|
+
scenarios.filter(:id => row[:scenario_id]).update(:run_count => run_count)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Delete all but the last result, since the other ones were overwritten
|
|
13
|
+
last_scenario_id = nil
|
|
14
|
+
results = self[:results]
|
|
15
|
+
results.order(:scenario_id, :id.desc).each do |result|
|
|
16
|
+
if result[:scenario_id] != last_scenario_id
|
|
17
|
+
last_scenario_id = result[:scenario_id]
|
|
18
|
+
results.filter(:id => result[:id]).update(:run_number => 1)
|
|
19
|
+
else
|
|
20
|
+
results.filter(:id => result[:id]).delete
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
down do
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
alter_table(:comparisons) do
|
|
4
|
+
rename_column :lhs_value, :raw_lhs_value
|
|
5
|
+
rename_column :rhs_value, :raw_rhs_value
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
down do
|
|
9
|
+
alter_table(:comparisons) do
|
|
10
|
+
rename_column :raw_lhs_value, :lhs_value
|
|
11
|
+
rename_column :raw_rhs_value, :rhs_value
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
alter_table(:imports) do
|
|
4
|
+
add_column :field_names, String, :text => true
|
|
5
|
+
add_column :primary_key_name, String
|
|
6
|
+
add_column :has_headers, TrueClass
|
|
7
|
+
add_column :has_duplicate_keys, TrueClass
|
|
8
|
+
add_column :occurred_at, DateTime
|
|
9
|
+
rename_column :fields, :field_types
|
|
10
|
+
rename_column :data, :file_name
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
down do
|
|
14
|
+
alter_table(:imports) do
|
|
15
|
+
rename_column :file_name, :data
|
|
16
|
+
rename_column :field_types, :fields
|
|
17
|
+
drop_column :field_names
|
|
18
|
+
drop_column :primary_key_name
|
|
19
|
+
drop_column :has_headers
|
|
20
|
+
drop_column :has_duplicate_keys
|
|
21
|
+
drop_column :occurred_at
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
up do
|
|
3
|
+
alter_table(:resources) { drop_column(:database_name) }
|
|
4
|
+
alter_table(:resources_versions) { drop_column(:database_name) }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
down do
|
|
8
|
+
alter_table(:resources) { add_column(:database_name, String) }
|
|
9
|
+
alter_table(:resources_versions) { add_column(:database_name, String) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Feature: managing connections
|
|
2
|
+
|
|
3
|
+
Scenario: creating a connection
|
|
4
|
+
When I go to the connections page
|
|
5
|
+
And I click the "New Connection" link
|
|
6
|
+
And I fill in the form:
|
|
7
|
+
| Name | Fake data |
|
|
8
|
+
| Type | MySQL |
|
|
9
|
+
| Host | localhost |
|
|
10
|
+
| Port | 12345 |
|
|
11
|
+
| Username | coupler |
|
|
12
|
+
| Password | cupla |
|
|
13
|
+
And I click the "Submit" button
|
|
14
|
+
Then it should show me a confirmation notice
|
|
15
|
+
|
|
16
|
+
Scenario: editing a connection
|
|
17
|
+
Given that I have created a connection called "My Connection"
|
|
18
|
+
When I go to the connections page
|
|
19
|
+
And I click the "Edit" link
|
|
20
|
+
And I change "Name" to "Server X"
|
|
21
|
+
And I click the "Submit" button
|
|
22
|
+
Then it should take me back to the connections page
|
|
23
|
+
|
|
24
|
+
Scenario: changing a connection that orphans resources
|
|
25
|
+
|
|
26
|
+
Scenario: deleting a connection
|
|
27
|
+
|
|
28
|
+
Scenario: deleting a connection that orphans resources
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Feature: managing matchers
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given that I have created a connection called "My Connection"
|
|
5
|
+
And that I have created a project called "My Project"
|
|
6
|
+
And that I have added the "People" resource
|
|
7
|
+
|
|
8
|
+
Scenario: creating a matcher for a self-linkage scenario
|
|
9
|
+
Given that I have created a self-linkage scenario called "Link by Last name"
|
|
10
|
+
When I go to the scenario page
|
|
11
|
+
And I click the "Add matcher" link
|
|
12
|
+
And I click the "Add comparison" link
|
|
13
|
+
And I select "Field" as the first type
|
|
14
|
+
And I select "last_name" for "People [1]" as the first value
|
|
15
|
+
And I select "Field" as the second type
|
|
16
|
+
And I select "last_name" for "People [2]" as the second value
|
|
17
|
+
And I click the "Add" button
|
|
18
|
+
And I click the "Submit" button
|
|
19
|
+
Then it should take me back to the scenario page
|
|
20
|
+
And it should show me a confirmation notice
|
|
21
|
+
|
|
22
|
+
Scenario: creating a matcher for a dual-join scenario
|
|
23
|
+
Given that I have added the "Pets" resource
|
|
24
|
+
And that I have created a dual-linkage scenario called "Link by Last name"
|
|
25
|
+
When I go to the scenario page
|
|
26
|
+
And I click the "Add matcher" link
|
|
27
|
+
And I click the "Add comparison" link
|
|
28
|
+
And I select "Field" as the first type
|
|
29
|
+
And I select "last_name" for "People" as the first value
|
|
30
|
+
And I select "Field" as the second type
|
|
31
|
+
And I select "owner_last_name" for "Pets" as the second value
|
|
32
|
+
And I click the "Add" button
|
|
33
|
+
And I click the "Submit" button
|
|
34
|
+
Then it should take me back to the scenario page
|
|
35
|
+
And it should show me a confirmation notice
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Feature: managing projects
|
|
2
|
+
|
|
3
|
+
Scenario: creating a project
|
|
4
|
+
When I go to the projects page
|
|
5
|
+
And I click the "New Project" link
|
|
6
|
+
And I fill in the form:
|
|
7
|
+
| Name | My Project |
|
|
8
|
+
| Description | This is a test project |
|
|
9
|
+
And I click the "Submit" button
|
|
10
|
+
Then it should show me a confirmation notice
|
|
11
|
+
And ask me to add a resource
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Feature: managing resources
|
|
2
|
+
Background:
|
|
3
|
+
Given that I have created a project called "My Project"
|
|
4
|
+
And that I have created a transformer called "My Transformer"
|
|
5
|
+
|
|
6
|
+
Scenario: adding a resource
|
|
7
|
+
Given that I have created a connection called "My Connection"
|
|
8
|
+
When I go to the project page
|
|
9
|
+
And I click the "Add resource" link
|
|
10
|
+
And I choose a "Database" resource
|
|
11
|
+
And I fill in the form:
|
|
12
|
+
| Name | People |
|
|
13
|
+
| Connection | My Connection |
|
|
14
|
+
| Database (2) | fake_data |
|
|
15
|
+
| Table | people |
|
|
16
|
+
And I click the "Submit" button
|
|
17
|
+
Then it should show me a confirmation notice
|
|
18
|
+
And ask me to choose which fields I wish to select
|
|
19
|
+
|
|
20
|
+
Scenario: adding a resource and connection at the same time
|
|
21
|
+
When I go to the project page
|
|
22
|
+
And I click the "Add resource" link
|
|
23
|
+
And I choose a "Database" resource
|
|
24
|
+
And I fill in the form:
|
|
25
|
+
| Name (1) | Fake data |
|
|
26
|
+
| Type | MySQL |
|
|
27
|
+
| Host | localhost |
|
|
28
|
+
| Port | 12345 |
|
|
29
|
+
| Username | coupler |
|
|
30
|
+
| Password | cupla |
|
|
31
|
+
| Name (2) | People |
|
|
32
|
+
| Database (2) | fake_data |
|
|
33
|
+
| Table | people |
|
|
34
|
+
And I click the "Submit" button
|
|
35
|
+
Then it should show me a confirmation notice
|
|
36
|
+
|
|
37
|
+
Scenario: adding a transformation
|
|
38
|
+
Given that I have created a connection called "My Connection"
|
|
39
|
+
And that I have added the "People" resource
|
|
40
|
+
When I go to the resource page
|
|
41
|
+
And I click on the hammer icon next to the "first_name" field
|
|
42
|
+
And I fill in the form:
|
|
43
|
+
| Transformer | My Transformer |
|
|
44
|
+
And I click the "Finish" button
|
|
45
|
+
Then it should show me a confirmation notice
|
|
46
|
+
|
|
47
|
+
Scenario: deleting a transformation
|
|
48
|
+
Given that I have created a connection called "My Connection"
|
|
49
|
+
And that I have added the "People" resource
|
|
50
|
+
And that I have added a transformation for "first_name"
|
|
51
|
+
When I go to the resource page
|
|
52
|
+
And I click on the cog icon next to the "first_name" field
|
|
53
|
+
And I click the "Delete" link
|
|
54
|
+
Then there should be no more transformations
|
|
55
|
+
|
|
56
|
+
Scenario: transforming a resource
|
|
57
|
+
Given that I have created a connection called "My Connection"
|
|
58
|
+
And that I have added the "People" resource
|
|
59
|
+
And that I have added a transformation for "first_name"
|
|
60
|
+
When I go to the resource page
|
|
61
|
+
And I click the "Transform now" button with confirmation
|
|
62
|
+
Then it should start transforming
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Feature: managing scenarios
|
|
2
|
+
Background:
|
|
3
|
+
Given that I have created a connection called "My Connection"
|
|
4
|
+
And that I have created a project called "My Project"
|
|
5
|
+
And that I have added the "People" resource
|
|
6
|
+
|
|
7
|
+
Scenario: creating a self-linkage scenario
|
|
8
|
+
When I go to the project page
|
|
9
|
+
And I click the "Create scenario" link
|
|
10
|
+
And I fill in the form:
|
|
11
|
+
| Name | Link by Last name |
|
|
12
|
+
And I click the "People" resource
|
|
13
|
+
And I click the "Submit" button
|
|
14
|
+
Then it should show me a confirmation notice
|
|
15
|
+
And ask me to add matchers
|
|
16
|
+
|
|
17
|
+
Scenario: creating a dual-linkage scenario
|
|
18
|
+
Given that I have added the "Pets" resource
|
|
19
|
+
When I go to the project page
|
|
20
|
+
And I click the "Create scenario" link
|
|
21
|
+
And I fill in the form:
|
|
22
|
+
| Name | Link by name |
|
|
23
|
+
And I click the "People" resource
|
|
24
|
+
And I click the "Pets" resource
|
|
25
|
+
And I click the "Submit" button
|
|
26
|
+
Then it should show me a confirmation notice
|
|
27
|
+
And ask me to add matchers
|
|
28
|
+
|
|
29
|
+
Scenario: running a self-linkage scenario
|
|
30
|
+
Given that I have created a self-linkage scenario called "Link by Last name"
|
|
31
|
+
And that I have added a matcher with these options:
|
|
32
|
+
| Type 1 | Value 1 | Operator | Type 2 | Value 2 |
|
|
33
|
+
| field | last_name | equals | field | last_name |
|
|
34
|
+
When I go to the scenario page
|
|
35
|
+
And I click the "Run now" button with confirmation
|
|
36
|
+
Then it should start the linkage process
|
|
37
|
+
|
|
38
|
+
Scenario: running a scenario with a non-equality matcher
|
|
39
|
+
Given that I have created a self-linkage scenario called "Link by Last name"
|
|
40
|
+
And that I have added a matcher with these options:
|
|
41
|
+
| Type 1 | Value 1 | Operator | Type 2 | Value 2 |
|
|
42
|
+
| field | last_name | does_not_equal | field | last_name |
|
|
43
|
+
When I go to the scenario page
|
|
44
|
+
And I click the "Run now" button with confirmation
|
|
45
|
+
Then it should start the linkage process
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Given /^that I have created a connection called "(.+?)"$/ do |connection_name|
|
|
2
|
+
@connection_name = connection_name
|
|
3
|
+
@connection = Factory(:connection, :name => connection_name)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
Given /^that I have created a project called "(.+?)"$/ do |project_name|
|
|
7
|
+
@project_name = project_name
|
|
8
|
+
@project = Factory(:project, :name => project_name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Given /^that I have created a transformer called "(.+?)"$/ do |transformer_name|
|
|
12
|
+
@transformer_name = transformer_name
|
|
13
|
+
@transformer = Factory(:transformer, :name => transformer_name)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Given /^that I have added the "(.+?)" resource$/ do |resource_name|
|
|
17
|
+
@resource_name = resource_name
|
|
18
|
+
options = case resource_name
|
|
19
|
+
when "People"
|
|
20
|
+
{ :table_name => "people" }
|
|
21
|
+
when "Pets"
|
|
22
|
+
{ :table_name => "pets" }
|
|
23
|
+
end
|
|
24
|
+
@resources ||= []
|
|
25
|
+
@resources << Factory(:resource, {:name => resource_name, :project => @project, :connection => @connection}.merge(options))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Given /^that I have added a transformation for "([^\"]*)"$/ do |field|
|
|
29
|
+
resource = @resources[0]
|
|
30
|
+
@transformation = Factory(:transformation, {
|
|
31
|
+
:resource => resource, :transformer => @transformer,
|
|
32
|
+
:source_field => resource.fields_dataset[:name => field]
|
|
33
|
+
})
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
Given /^that I have created a self-linkage scenario called "([^"]*)"$/ do |scenario_name|
|
|
37
|
+
@scenario = Factory(:scenario, {
|
|
38
|
+
:name => scenario_name, :resource_1_id => @resources[0].id,
|
|
39
|
+
:project => @project
|
|
40
|
+
})
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Given /^that I have created a dual-linkage scenario called "([^"]*)"$/ do |scenario_name|
|
|
44
|
+
@scenario = Factory(:scenario, {
|
|
45
|
+
:name => scenario_name, :project => @project,
|
|
46
|
+
:resource_1_id => @resources[0].id, :resource_2_id => @resources[1].id
|
|
47
|
+
})
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Given /^that I have added a matcher with these options:$/ do |table|
|
|
51
|
+
comparisons_attributes = []
|
|
52
|
+
resources = @scenario.resources
|
|
53
|
+
table.hashes.each do |hash|
|
|
54
|
+
lhs_value = hash["Type 1"] == "field" ? resources[0].fields_dataset[:name => hash["Value 1"]].id : hash["Value 1"]
|
|
55
|
+
rhs_value = hash["Type 2"] == "field" ? resources[-1].fields_dataset[:name => hash["Value 2"]].id : hash["Value 2"]
|
|
56
|
+
comparisons_attributes << {
|
|
57
|
+
"lhs_type" => hash["Type 1"], "lhs_value" => lhs_value,
|
|
58
|
+
"rhs_type" => hash["Type 2"], "rhs_value" => rhs_value,
|
|
59
|
+
"operator" => hash["Operator"]
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
@matcher = Factory(:matcher, {
|
|
63
|
+
:comparisons_attributes => comparisons_attributes,
|
|
64
|
+
:scenario => @scenario
|
|
65
|
+
})
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
When /^I go to the (.+?) page$/ do |page_name|
|
|
69
|
+
@page_name = page_name
|
|
70
|
+
path = case page_name
|
|
71
|
+
when "front"
|
|
72
|
+
"/"
|
|
73
|
+
when "connections"
|
|
74
|
+
"/connections"
|
|
75
|
+
when "projects"
|
|
76
|
+
"/projects"
|
|
77
|
+
when "project"
|
|
78
|
+
"/projects/#{@project.id}"
|
|
79
|
+
when "resource"
|
|
80
|
+
"/projects/#{@project.id}/resources/#{@resources[0].id}"
|
|
81
|
+
when "transformations"
|
|
82
|
+
"/projects/#{@project.id}/resources/#{@resources[0].id}/transformations"
|
|
83
|
+
when "scenario"
|
|
84
|
+
"/projects/#{@project.id}/scenarios/#{@scenario.id}"
|
|
85
|
+
end
|
|
86
|
+
visit("http://localhost:4567#{path}")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
When /^I click the "(.+?)" link$/ do |link_name|
|
|
90
|
+
link = browser.link(:text, link_name)
|
|
91
|
+
assert link.exist?, "can't find the '#{link_name}' link"
|
|
92
|
+
link.click
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
When /^I fill in the form:$/ do |table|
|
|
96
|
+
form = browser.forms.first
|
|
97
|
+
table.raw.each do |(label_or_name, value)|
|
|
98
|
+
md = label_or_name.match(/\s*\((\d+)\)\s*$/)
|
|
99
|
+
args = md ? [md.pre_match, md[1].to_i - 1] : [label_or_name]
|
|
100
|
+
elt = find_visible_element_by_label_or_id(*args)
|
|
101
|
+
if elt.nil?
|
|
102
|
+
puts current_page_source
|
|
103
|
+
end
|
|
104
|
+
assert elt && elt.exist?, "can't find element with label or name of '#{label_or_name}'"
|
|
105
|
+
|
|
106
|
+
case elt
|
|
107
|
+
when Celerity::TextField
|
|
108
|
+
elt.value = value
|
|
109
|
+
when Celerity::SelectList
|
|
110
|
+
value.split("/").each do |v|
|
|
111
|
+
elt.object.get_options.find do |option|
|
|
112
|
+
option.text_content == v || option.value_attribute == v
|
|
113
|
+
end.click
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
raise "unknown field type: #{elt.to_xml}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
When /^I click the "(.+?)" button$/ do |button_name|
|
|
122
|
+
click_button(button_name)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
When /^I click the "(.+?)" button with confirmation$/ do |button_name|
|
|
126
|
+
browser.confirm(true) do
|
|
127
|
+
click_button(button_name)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
Then /^(?:it should )?show me a confirmation notice$/ do
|
|
132
|
+
assert_match /successfully created|created successfully/, current_page_source
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
Then /^ask me to (.+)$/ do |question|
|
|
136
|
+
question = question.sub(/\bI\b/, "you")
|
|
137
|
+
assert current_page_source.include?(question)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
Then /^it should take me back to the (\w+) page$/ do |page_name|
|
|
141
|
+
case page_name
|
|
142
|
+
when 'resource'
|
|
143
|
+
assert_match %r{/projects/#{@project.id}/resources/#{@resources[0].id}$}, current_url
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
When /^I select "([^\"]*)" as the (first|second) type$/ do |type, which|
|
|
2
|
+
name = case which
|
|
3
|
+
when "first" then "lhs"
|
|
4
|
+
when "second" then "rhs"
|
|
5
|
+
else raise "bad which"
|
|
6
|
+
end
|
|
7
|
+
browser.select_list(:id => "#{name}_type").select(type)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
When /^I select "([^\"]*)" for "([^\"]*)" as the (first|second) value$/ do |field, resource, which|
|
|
11
|
+
name = case which
|
|
12
|
+
when "first" then "lhs"
|
|
13
|
+
when "second" then "rhs"
|
|
14
|
+
else raise "bad which"
|
|
15
|
+
end
|
|
16
|
+
s = browser.select_list(:id => "#{name}_value_select")
|
|
17
|
+
optgroup = s.object.child_nodes.detect do |node|
|
|
18
|
+
Java::ComGargoylesoftwareHtmlunitHtml::HtmlOptionGroup === node &&
|
|
19
|
+
node.label_attribute == resource
|
|
20
|
+
end
|
|
21
|
+
option = optgroup.child_nodes.detect do |node|
|
|
22
|
+
Java::ComGargoylesoftwareHtmlunitHtml::HtmlOption === node &&
|
|
23
|
+
node.text == field
|
|
24
|
+
end
|
|
25
|
+
s.object.set_selected_attribute(option, true)
|
|
26
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
When /I click on the (\w+) icon next to the "([^"]+)" field/ do |icon, field|
|
|
2
|
+
image = browser.cell(:text => field).parent.image(:src => /#{icon}/)
|
|
3
|
+
image.parent.click
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
When /I choose a "([^"]+)" resource/ do |name|
|
|
7
|
+
browser.execute_script(%{$('#resource-#{name.downcase}').show();})
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
Then /^it should start transforming$/ do
|
|
11
|
+
assert_match /running/, current_page_source
|
|
12
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test/helper"
|
|
2
|
+
require 'test/unit/assertions'
|
|
3
|
+
require 'celerity'
|
|
4
|
+
|
|
5
|
+
module CouplerWorld
|
|
6
|
+
include Test::Unit::Assertions
|
|
7
|
+
|
|
8
|
+
def app
|
|
9
|
+
Coupler::Base.set :environment, :test
|
|
10
|
+
Coupler::Base
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def browser
|
|
14
|
+
unless @browser
|
|
15
|
+
@browser = Celerity::Browser.new({
|
|
16
|
+
:javascript_exceptions => true, :viewer => "127.0.0.1:6429",
|
|
17
|
+
:resynchronize => true, :css => true
|
|
18
|
+
})
|
|
19
|
+
end
|
|
20
|
+
@browser
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def visit(url)
|
|
24
|
+
browser.goto(url)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def current_url
|
|
28
|
+
browser.page.web_response.request_url.to_string
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def current_page_source
|
|
32
|
+
return nil unless browser.page
|
|
33
|
+
|
|
34
|
+
string_writer = java.io.StringWriter.new
|
|
35
|
+
print_writer = java.io.PrintWriter.new(string_writer)
|
|
36
|
+
|
|
37
|
+
root = browser.page.document_element
|
|
38
|
+
node_to_xml(root, print_writer)
|
|
39
|
+
print_writer.close
|
|
40
|
+
string_writer.to_string
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Fill in a text field with a value
|
|
44
|
+
def fill_in(label_or_name, options = {})
|
|
45
|
+
elt = find_element_by_label_or_name(:text_field, label_or_name)
|
|
46
|
+
if elt.exist?
|
|
47
|
+
elt.value = options[:with]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def select(option_text, options = {})
|
|
52
|
+
elt = find_element_by_label_or_name(:select_list, options[:from])
|
|
53
|
+
if elt.exist?
|
|
54
|
+
begin
|
|
55
|
+
elt.select(option_text)
|
|
56
|
+
rescue Celerity::Exception::CelerityException
|
|
57
|
+
elt.select_value(option_text)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def click_button(button_value)
|
|
63
|
+
browser.button(button_value).click
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def find_visible_element_by_label_or_id(label_or_id, which = 0)
|
|
67
|
+
labels = browser.labels.select do |label|
|
|
68
|
+
object = label.object
|
|
69
|
+
object.textContent == label_or_id && object.displayed?
|
|
70
|
+
end
|
|
71
|
+
id = labels.empty? ? label_or_id : labels[which].for
|
|
72
|
+
browser.elements_by_xpath("id('#{id}')")[0]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
# NOTE: I have to do this because HtmlUnit's asXml likes to put spaces
|
|
77
|
+
# and newlines in the middle of whitespace-sensitive tags (like
|
|
78
|
+
# <a> and <textarea>). Fail.
|
|
79
|
+
def node_to_xml(node, print_writer)
|
|
80
|
+
closing_tag = false
|
|
81
|
+
|
|
82
|
+
case node
|
|
83
|
+
when HtmlUnit::Html::DomText
|
|
84
|
+
# just print out the text
|
|
85
|
+
print_writer.write(HtmlUnit::Util::StringUtils.escape_xml_chars(node.data))
|
|
86
|
+
when HtmlUnit::Html::DomCDataSection, HtmlUnit::Html::DomProcessingInstruction
|
|
87
|
+
# use default printXml here
|
|
88
|
+
node.print_xml("", print_writer)
|
|
89
|
+
when HtmlUnit::Html::DomComment
|
|
90
|
+
print_writer.write("<!-- #{node.data} -->")
|
|
91
|
+
when HtmlUnit::Html::HtmlTextArea
|
|
92
|
+
node_print_opening_tag(node, print_writer)
|
|
93
|
+
print_writer.write(node.text)
|
|
94
|
+
closing_tag = true
|
|
95
|
+
else
|
|
96
|
+
node_print_opening_tag(node, print_writer)
|
|
97
|
+
closing_tag = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
child = node.first_child
|
|
101
|
+
while child
|
|
102
|
+
node_to_xml(child, print_writer)
|
|
103
|
+
child = child.next_sibling
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
node_print_closing_tag(node, print_writer) if closing_tag
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def node_print_opening_tag(node, print_writer)
|
|
110
|
+
print_writer.write("<")
|
|
111
|
+
node.print_opening_tag_content_as_xml(print_writer)
|
|
112
|
+
print_writer.write(">")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def node_print_closing_tag(node, print_writer)
|
|
116
|
+
print_writer.write("</#{node.tag_name}>")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
Before do
|
|
121
|
+
database = Coupler::Database.instance
|
|
122
|
+
database.tables.each do |name|
|
|
123
|
+
next if name == :schema_info
|
|
124
|
+
database[name].delete
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
World(CouplerWorld)
|