typingpool 0.7.0

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.
Files changed (90) hide show
  1. data/Rakefile +23 -0
  2. data/bin/tp-assign +240 -0
  3. data/bin/tp-collect +50 -0
  4. data/bin/tp-config +114 -0
  5. data/bin/tp-finish +101 -0
  6. data/bin/tp-make +169 -0
  7. data/bin/tp-review +175 -0
  8. data/lib/typingpool/amazon.rb +732 -0
  9. data/lib/typingpool/app.rb +634 -0
  10. data/lib/typingpool/config.rb +344 -0
  11. data/lib/typingpool/error.rb +22 -0
  12. data/lib/typingpool/filer.rb +396 -0
  13. data/lib/typingpool/project.rb +593 -0
  14. data/lib/typingpool/template.rb +175 -0
  15. data/lib/typingpool/templates/assignment/amazon-init.js +38 -0
  16. data/lib/typingpool/templates/assignment/interview/nameless.html.erb +13 -0
  17. data/lib/typingpool/templates/assignment/interview/noisy.html.erb +12 -0
  18. data/lib/typingpool/templates/assignment/interview/partials/voices.html.erb +10 -0
  19. data/lib/typingpool/templates/assignment/interview/phone.html.erb +12 -0
  20. data/lib/typingpool/templates/assignment/interview.html.erb +11 -0
  21. data/lib/typingpool/templates/assignment/main.css +20 -0
  22. data/lib/typingpool/templates/assignment/partials/entry.html.erb +19 -0
  23. data/lib/typingpool/templates/assignment/partials/footer.html.erb +3 -0
  24. data/lib/typingpool/templates/assignment/partials/header.html.erb +11 -0
  25. data/lib/typingpool/templates/assignment/partials/labeling-example.html.erb +4 -0
  26. data/lib/typingpool/templates/assignment/partials/labeling.html.erb +5 -0
  27. data/lib/typingpool/templates/assignment/partials/length-description.html.erb +6 -0
  28. data/lib/typingpool/templates/assignment/partials/voices.html.erb +10 -0
  29. data/lib/typingpool/templates/assignment/speech.html.erb +11 -0
  30. data/lib/typingpool/templates/config.yml +21 -0
  31. data/lib/typingpool/templates/project/audio/chunks/.empty_directory +0 -0
  32. data/lib/typingpool/templates/project/audio/originals/.empty_directory +0 -0
  33. data/lib/typingpool/templates/project/data/.empty_directory +0 -0
  34. data/lib/typingpool/templates/project/etc/ About these files - read me.txt +8 -0
  35. data/lib/typingpool/templates/project/etc/audio-compat.js +25 -0
  36. data/lib/typingpool/templates/project/etc/player/audio-player.js +4 -0
  37. data/lib/typingpool/templates/project/etc/player/license.txt +19 -0
  38. data/lib/typingpool/templates/project/etc/player/player.swf +0 -0
  39. data/lib/typingpool/templates/project/etc/transcript.css +49 -0
  40. data/lib/typingpool/templates/transcript.html.erb +23 -0
  41. data/lib/typingpool/test/fixtures/amazon-question-html.html +95 -0
  42. data/lib/typingpool/test/fixtures/amazon-question-url.txt +1 -0
  43. data/lib/typingpool/test/fixtures/audio/mp3/interview.1.mp3 +0 -0
  44. data/lib/typingpool/test/fixtures/audio/mp3/interview.2.mp3 +0 -0
  45. data/lib/typingpool/test/fixtures/audio/wma/VN620007.WMA +0 -0
  46. data/lib/typingpool/test/fixtures/audio/wma/VN620052.WMA +0 -0
  47. data/lib/typingpool/test/fixtures/config-1 +20 -0
  48. data/lib/typingpool/test/fixtures/config-2 +25 -0
  49. data/lib/typingpool/test/fixtures/not_yaml.txt +4 -0
  50. data/lib/typingpool/test/fixtures/template-2.html.erb +10 -0
  51. data/lib/typingpool/test/fixtures/template-3.html.erb +22 -0
  52. data/lib/typingpool/test/fixtures/template.html.erb +10 -0
  53. data/lib/typingpool/test/fixtures/tp_collect_id.txt +1 -0
  54. data/lib/typingpool/test/fixtures/tp_collect_sandbox-assignment.csv +8 -0
  55. data/lib/typingpool/test/fixtures/tp_review_id.txt +1 -0
  56. data/lib/typingpool/test/fixtures/tp_review_sandbox-assignment.csv +8 -0
  57. data/lib/typingpool/test/fixtures/transcript-chunks.csv +226 -0
  58. data/lib/typingpool/test/fixtures/utf8_transcript.txt +7 -0
  59. data/lib/typingpool/test/fixtures/vcr/tp-collect-1.yml +2712 -0
  60. data/lib/typingpool/test/fixtures/vcr/tp-collect-2.yml +2718 -0
  61. data/lib/typingpool/test/fixtures/vcr/tp-collect-3.yml +2768 -0
  62. data/lib/typingpool/test/fixtures/vcr/tp-review-1.yml +570 -0
  63. data/lib/typingpool/test/fixtures/vcr/tp-review-2.yml +351 -0
  64. data/lib/typingpool/test.rb +418 -0
  65. data/lib/typingpool/transcript.rb +181 -0
  66. data/lib/typingpool/utility.rb +272 -0
  67. data/lib/typingpool.rb +500 -0
  68. data/test/make_amazon_question_fixture.rb +24 -0
  69. data/test/make_tp_collect_fixture_1.rb +26 -0
  70. data/test/make_tp_collect_fixture_2.rb +16 -0
  71. data/test/make_tp_collect_fixture_3.rb +15 -0
  72. data/test/make_tp_collect_fixture_4.rb +17 -0
  73. data/test/make_tp_review_fixture_1.rb +26 -0
  74. data/test/make_tp_review_fixture_2.rb +30 -0
  75. data/test/make_transcript_chunks_fixture.rb +53 -0
  76. data/test/test_integration_script_1_tp_config.rb +108 -0
  77. data/test/test_integration_script_2_tp_make.rb +119 -0
  78. data/test/test_integration_script_3_tp_assign.rb +152 -0
  79. data/test/test_integration_script_4_tp_review.rb +72 -0
  80. data/test/test_integration_script_5_tp_collect.rb +44 -0
  81. data/test/test_integration_script_6_tp_finish.rb +123 -0
  82. data/test/test_unit_amazon.rb +153 -0
  83. data/test/test_unit_config.rb +94 -0
  84. data/test/test_unit_filer.rb +202 -0
  85. data/test/test_unit_project.rb +168 -0
  86. data/test/test_unit_project_local.rb +68 -0
  87. data/test/test_unit_project_remote.rb +157 -0
  88. data/test/test_unit_template.rb +111 -0
  89. data/test/test_unit_transcript.rb +77 -0
  90. metadata +234 -0
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+
7
+ lines_each = 2
8
+ if ARGV.last.to_s.match(/^\d+$/)
9
+ lines_each = ARGV.pop.to_i
10
+ end
11
+
12
+ if ARGV.empty?
13
+ abort "USAGE: #{File.basename($PROGRAM_NAME)} PROJECT_DIR [PROJECT_DIR...] [LINES_EACH=2]"
14
+ end
15
+
16
+ data_files = ARGV.map do |path|
17
+ data_file = nil
18
+ expanded = File.expand_path(path)
19
+ if not(File.exists? expanded)
20
+ abort "No such dir #{path}"
21
+ end
22
+ if not(File.directory? expanded)
23
+ abort "Not a dir: #{path}"
24
+ end
25
+ %w(data csv).each do |data_dir_name|
26
+ possible_data_file = File.join(expanded, data_dir_name, 'assignment.csv')
27
+ if File.exists? possible_data_file
28
+ data_file = possible_data_file
29
+ end
30
+ end #%w().each do...
31
+ if not(data_file)
32
+ abort "Dir #{path} has no data/assignment.csv or csv/assignment.csv"
33
+ end
34
+ data_file
35
+ end #ARGV.map
36
+
37
+ assignments=[]
38
+ data_files.each do |path|
39
+ csv = Typingpool::Filer::CSV.new(path)
40
+ with_transcripts = csv.reject{|assignment| assignment['transcript'].to_s.empty? }
41
+ next if with_transcripts.empty?
42
+ seeking = with_transcripts.count
43
+ if seeking > lines_each
44
+ seeking = lines_each
45
+ end
46
+ assignments.push(*with_transcripts.sample(seeking))
47
+ end #data_files.each do...
48
+
49
+ if assignments.empty?
50
+ abort "No transcripts found"
51
+ end
52
+ fixtures_dir = File.join(Typingpool::Utility.lib_dir, 'test', 'fixtures')
53
+ Typingpool::Filer::CSV.new(File.join(fixtures_dir, 'transcript-chunks.csv')).write(assignments)
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpConfig < Typingpool::Test::Script
9
+
10
+ def test_abort_with_invalid_file
11
+ exception = assert_raise(Typingpool::Error::Shell) do
12
+ tp_config(File.join(fixtures_dir, 'not_yaml.txt'))
13
+ end
14
+ assert_match(exception.message, /not valid yaml/i)
15
+ end
16
+
17
+ def test_abort_with_directory_path
18
+ dir = File.join(fixtures_dir, 'vcr')
19
+ assert(File.exists? dir)
20
+ assert(File.directory? dir)
21
+ exception = assert_raise(Typingpool::Error::Shell) do
22
+ tp_config(dir)
23
+ end
24
+ assert_match(exception.message, /not a file/i)
25
+ end
26
+
27
+ def test_abort_with_invalid_path
28
+ path = '/jksdljs/euwiroeuw'
29
+ refute(File.exists? path)
30
+ exception = assert_raise(Typingpool::Error::Shell) do
31
+ tp_config(path)
32
+ end
33
+ assert_match(exception.message, /valid path/i)
34
+ end
35
+
36
+ def test_usage_message
37
+ assert(output = tp_config('--help'))
38
+ assert_match(output, /\bUSAGE:/)
39
+ end
40
+
41
+ def test_new_config_creation
42
+ in_temp_dir do |dir|
43
+ path = {
44
+ :config => File.join(dir, 'config.yml'),
45
+ :transcript_dir => File.join(dir, 'transcriptionz')
46
+ }
47
+ path.values.each{|path| refute(File.exists? path) }
48
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
49
+ assert_match(output[:err], /wrote config to/i)
50
+ path.values.each{|path| assert(File.exists? path) }
51
+ assert(File.file? path[:config] )
52
+ assert(File.directory? path[:transcript_dir] )
53
+ assert(config = Typingpool::Config.file(path[:config]))
54
+ assert_equal(path[:transcript_dir], config.transcripts)
55
+ assert_equal(File.join(path[:transcript_dir], 'templates').downcase, config.templates.downcase)
56
+ assert_equal('keykey', config.amazon.key)
57
+ assert_equal('secretsecret', config.amazon.secret)
58
+ refute_empty(config.amazon.bucket.to_s)
59
+ end #in_temp_dir do |dir|
60
+ end
61
+
62
+ def test_config_editing
63
+ in_temp_dir do |dir|
64
+ path = {
65
+ :config => File.join(dir, 'config.yml'),
66
+ :fixture => File.join(fixtures_dir, 'config-1'),
67
+ :transcript_dir => File.join(dir, 'transcriptionz')
68
+ }
69
+ assert(File.exists? path[:fixture])
70
+ refute(File.exists? path[:config])
71
+ FileUtils.cp(path[:fixture], path[:config])
72
+ assert(File.exists? path[:config])
73
+ assert(original_config = Typingpool::Config.file(path[:config]))
74
+ [:key, :secret, :bucket].each{|param| refute_empty(original_config.amazon.send(param).to_s) }
75
+ [:transcripts, :templates, :cache].each{|param| refute_empty(original_config.send(param).to_s) }
76
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
77
+ assert(edited_config = Typingpool::Config.file(path[:config]))
78
+ [:key, :secret].each{|param| refute_equal(original_config.amazon.send(param), edited_config.amazon.send(param)) }
79
+ assert_equal(original_config.amazon.bucket, edited_config.amazon.bucket)
80
+ [:templates, :cache].each{|param| assert_equal(original_config.send(param), edited_config.send(param)) }
81
+ refute_equal(original_config.transcripts, edited_config.transcripts)
82
+ assert_equal('keykey', edited_config.amazon.key)
83
+ assert_equal('secretsecret', edited_config.amazon.secret)
84
+ assert_equal(path[:transcript_dir], edited_config.transcripts)
85
+ end #in_temp_dir |dir| do
86
+ end
87
+
88
+ def test_skips_bucket_when_sftp_params_exist
89
+ in_temp_dir do |dir|
90
+ path = {
91
+ :config => File.join(dir, 'config.yml'),
92
+ :fixture => File.join(fixtures_dir, 'config-2'),
93
+ :transcript_dir => File.join(dir, 'transcriptionz')
94
+ }
95
+ assert(File.exists? path[:fixture])
96
+ refute(File.exists? path[:config])
97
+ FileUtils.cp(path[:fixture], path[:config])
98
+ assert(File.exists? path[:config])
99
+ assert(original_config = Typingpool::Config.file(path[:config]))
100
+ assert_empty(original_config.amazon.bucket.to_s)
101
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
102
+ assert_match(output[:err], /wrote config to/i)
103
+ assert(edited_config = Typingpool::Config.file(path[:config]))
104
+ assert_empty(edited_config.amazon.bucket.to_s)
105
+ end #in_temp_dir do |dir|
106
+ end
107
+
108
+ end #class TestTpConfig
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+ require 'csv'
8
+
9
+ class TestTpMake < Typingpool::Test::Script
10
+ def test_abort_with_no_files
11
+ assert_tp_make_abort_match(['--title', 'Foo', '--chunks', '0:20'], /no files/i)
12
+ end
13
+
14
+ def test_abort_with_no_title
15
+ assert_tp_make_abort_match(['--file', audio_files[0]], /no title/i)
16
+ end
17
+
18
+ def test_abort_with_invalid_title
19
+ assert_tp_make_abort_match(['--file', audio_files[0], '--title', 'Foo/Bar'], /illegal character/i)
20
+ end
21
+
22
+ def test_abort_with_no_args
23
+ assert_tp_make_abort_match([], /\bUSAGE:/)
24
+ end
25
+
26
+ def assert_tp_make_abort_match(args, regex)
27
+ assert_script_abort_match(args, regex) do |args|
28
+ call_tp_make(*args)
29
+ end
30
+ end
31
+
32
+ def tp_make_with(dir, config_path, subdir='mp3')
33
+ begin
34
+ tp_make(dir, config_path, subdir)
35
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(config_path)))
36
+ assert_not_nil(project.local)
37
+ assert_not_nil(project.local.id)
38
+ assert(project.local.subdir('audio','chunks').to_a.size <= 7)
39
+ assert(project.local.subdir('audio','chunks').to_a.size >= 6)
40
+ assert_equal(project_default[:subtitle], project.local.subtitle)
41
+ assignments = project.local.file('data', 'assignment.csv').as(:csv)
42
+ assert_equal(project.local.subdir('audio','chunks').to_a.size, assignments.count)
43
+ assert_all_assets_have_upload_status(assignments, ['audio'], 'yes')
44
+ assignments.each do |assignment|
45
+ assert_not_nil(assignment['audio_url'])
46
+ assert(working_url? assignment['audio_url'])
47
+ assert_equal(assignment['project_id'], project.local.id)
48
+ assert_equal(assignment['unusual'].split(/\s*,\s*/), project_default[:unusual])
49
+ project_default[:voice].each_with_index do |voice, i|
50
+ name, description = voice.split(/\s*,\s*/)
51
+ assert_equal(name, assignment["voice#{i+1}"])
52
+ if not(description.to_s.empty?)
53
+ assert_equal(description, assignment["voice#{i+1}title"])
54
+ end
55
+ end #project_default[:voice].each_with_index...
56
+ end #assignments.each d0....
57
+ ensure
58
+ tp_finish_outside_sandbox(dir, config_path)
59
+ end #begin
60
+ assert_all_assets_have_upload_status(assignments, ['audio'], 'no')
61
+ end
62
+
63
+ def test_tp_make
64
+ Dir.entries(audio_dir).select{|entry| File.directory?(File.join(audio_dir, entry))}.reject{|entry| entry.match(/^\./) }.each do |subdir|
65
+ in_temp_tp_dir do |dir|
66
+ config_path = self.config_path(dir)
67
+ skip_if_no_upload_credentials('tp-make integration test', Typingpool::Config.file(config_path))
68
+ tp_make_with(dir, config_path, subdir)
69
+ end #in_temp_tp_dir
70
+ end #Dir.entries
71
+ end
72
+
73
+ def test_tp_make_s3
74
+ in_temp_tp_dir do |dir|
75
+ skip_if_no_s3_credentials('tp-make S3 integration test', config)
76
+ config_path = setup_s3_config(dir)
77
+ tp_make_with(dir, config_path)
78
+ end #in_temp_tp_dir do...
79
+ end
80
+
81
+ def test_fixing_failed_tp_make
82
+ in_temp_tp_dir do |dir|
83
+ config = config_from_dir(dir)
84
+ skip_if_no_s3_credentials('tp-make failed upload integration test', config)
85
+ good_config_path = setup_s3_config(dir)
86
+ bad_config_path = setup_s3_config_with_bad_password(dir)
87
+ assert_raises(Typingpool::Error::Shell) do
88
+ tp_make(dir, bad_config_path, 'mp3')
89
+ end
90
+ project_dir = temp_tp_dir_project_dir(dir)
91
+ assert(File.exists? project_dir)
92
+ assert(File.directory? project_dir)
93
+ assert(File.exists? File.join(project_dir, 'data', 'assignment.csv'))
94
+ originals_dir = File.join(project_dir, 'audio', 'originals')
95
+ refute_empty(Dir.entries(originals_dir).reject{|entry| entry.match(/^\./) }.map{|entry| File.join(originals_dir, entry) }.select{|path| File.file? path })
96
+ assert(project = temp_tp_dir_project(dir))
97
+ assert(assignment_csv = project.local.file('data', 'assignment.csv').as(:csv))
98
+ refute_empty(assignment_csv.to_a)
99
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'maybe')
100
+ assert(audio_urls = assignment_csv.map{|assignment| assignment['audio_url'] })
101
+ refute_empty(audio_urls)
102
+ assert_empty(audio_urls.select{|url| working_url? url })
103
+ begin
104
+ tp_make(dir, good_config_path, 'mp3')
105
+ refute_empty(assignment_csv.read)
106
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'yes')
107
+ refute_empty(audio_urls2 = assignment_csv.map{|assignment| assignment['audio_url'] })
108
+ audio_urls.each_with_index do |original_url, i|
109
+ assert_equal(original_url, audio_urls2[i])
110
+ end
111
+ assert_equal(audio_urls.count, audio_urls2.select{|url| working_url? url }.count)
112
+ ensure
113
+ tp_finish_outside_sandbox(dir, good_config_path)
114
+ end #begin
115
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'no')
116
+ end #in_temp_tp_dir do...
117
+ end
118
+
119
+ end #TestTpMake
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpAssign < Typingpool::Test::Script
9
+ #TODO: test that qualifications are sent (will need heroic effort
10
+ #(or at least some xml parsing) since rturk doesn't provide an
11
+ #easy way to look at HIT qualifications)
12
+ def test_abort_with_no_input
13
+ assert_raise(Typingpool::Error::Shell){call_tp_assign}
14
+ end
15
+
16
+ def test_abort_with_no_template
17
+ assert_tp_assign_abort_match([project_default[:title]], /Missing\b[^\n\r\f]*\btemplate/i)
18
+ end
19
+
20
+ def test_abort_with_bad_timespec
21
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--lifetime', '4u'], /can't convert/i)
22
+ end
23
+
24
+ def test_abort_with_bad_qualification
25
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--qualify', 'approval_rate &= 8'], /\bsense of --qualify.+\bunknown comparator\b/i)
26
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--qualify', 'fake_rate > 8'], /\bsense of --qualify\b.+unknown\b[^\n\r\f]*\btype\b/i)
27
+ end
28
+
29
+ def test_abort_with_bad_reward
30
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--reward', 'foo'], /sense of --reward/i)
31
+ end
32
+
33
+ def assert_tp_assign_abort_match(args, regex)
34
+ assert_script_abort_match(args, regex) do |args|
35
+ call_tp_assign(*args)
36
+ end
37
+ end
38
+
39
+ def test_tp_assign
40
+ skip_if_no_amazon_credentials('tp-assign integration test')
41
+ skip_if_no_upload_credentials('tp-assign integration test')
42
+ in_temp_tp_dir do |dir|
43
+ tp_make(dir)
44
+ begin
45
+ tp_assign(dir)
46
+ assign_time = Time.now
47
+ config = config_from_dir(dir)
48
+ project = temp_tp_dir_project(dir)
49
+ setup_amazon(dir)
50
+ results = nil
51
+ refute_empty(results = Typingpool::Amazon::HIT.all_for_project(project.local.id))
52
+ assert_equal(project.local.subdir('audio','chunks').to_a.size, results.size)
53
+ assert_equal(Typingpool::Utility.timespec_to_seconds(assign_default[:deadline]), results[0].full.assignments_duration.to_i)
54
+ #These numbers will be apart due to clock differences and
55
+ #timing vagaries of the assignment.
56
+ assert_in_delta((assign_time + Typingpool::Utility.timespec_to_seconds(assign_default[:lifetime])).to_f, results[0].full.expires_at.to_f, 60)
57
+ keywords = results[0].at_amazon.keywords
58
+ assign_default[:keyword].each{|keyword| assert_includes(keywords, keyword)}
59
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
60
+ refute_empty(assignment_urls = sandbox_csv.map{|assignment| assignment['assignment_url'] })
61
+ assert(assignment_html = fetch_url(assignment_urls.first).body)
62
+ assert_match(assignment_html, /\b20[\s-]+second\b/)
63
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'yes')
64
+ ensure
65
+ tp_finish(dir)
66
+ end #begin
67
+ assert_empty(Typingpool::Amazon::HIT.all_for_project(project.local.id))
68
+ end # in_temp_tp_dir
69
+ end
70
+
71
+ def test_uploads_audio_when_needed
72
+ skip_if_no_amazon_credentials('tp-assign unuploaded audio integration test')
73
+ skip_if_no_s3_credentials('tp-assign unuploaded audio integration test')
74
+ in_temp_tp_dir do |dir|
75
+ good_config_path = setup_s3_config(dir)
76
+ bad_config_path = setup_s3_config_with_bad_password(dir)
77
+ assert_raises(Typingpool::Error::Shell) do
78
+ tp_make(dir, bad_config_path, 'mp3')
79
+ end
80
+ project_dir = temp_tp_dir_project_dir(dir)
81
+ assert(File.exists? project_dir)
82
+ assert(File.directory? project_dir)
83
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(bad_config_path)))
84
+ csv = project.local.file('data', 'assignment.csv').as(:csv)
85
+ assert_empty(csv.select{|assignment| working_url? assignment['audio_url']})
86
+ assert_all_assets_have_upload_status(csv, ['audio'], 'maybe')
87
+ begin
88
+ tp_assign(dir, good_config_path)
89
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
90
+ assert_equal(csv.count, sandbox_csv.count)
91
+ assert_equal(sandbox_csv.count, sandbox_csv.select{|assignment| working_url? assignment['audio_url'] }.count)
92
+ assert_all_assets_have_upload_status(csv, ['audio'], 'yes')
93
+ ensure
94
+ tp_finish(dir, good_config_path)
95
+ end #begin
96
+ end # in_temp_tp_dir do...
97
+ end
98
+
99
+ def test_fixing_failed_assignment_html_upload
100
+ skip_if_no_amazon_credentials('tp-assign failed assignment upload integration test')
101
+ skip_if_no_s3_credentials('tp-assign failed assignment upload integration test')
102
+ in_temp_tp_dir do |dir|
103
+ good_config_path = setup_s3_config(dir)
104
+ bad_config_path = setup_s3_config_with_bad_password(dir)
105
+ tp_make(dir, good_config_path, 'mp3')
106
+ begin
107
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(good_config_path)))
108
+ assert(project.local)
109
+ get_assignment_urls = lambda{|csv| csv.map{|assignment| assignment['assignment_url'] }.select{|url| url } }
110
+ assert_empty(get_assignment_urls.call(project.local.file('data', 'assignment.csv').as(:csv)))
111
+ exception = assert_raises(Typingpool::Error::Shell) do
112
+ tp_assign(dir, bad_config_path)
113
+ end #assert_raises...
114
+ assert_match(exception.message, /s3 operation fail/i)
115
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
116
+ refute_empty(get_assignment_urls.call(sandbox_csv))
117
+ check_assignment_urls = lambda{ get_assignment_urls.call(sandbox_csv).map{|url| Typingpool::Utility.working_url? url } }
118
+ check_assignment_urls.call.each{|checked_out| refute(checked_out) }
119
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'maybe')
120
+ tp_assign(dir, good_config_path)
121
+ check_assignment_urls.call.each{|checked_out| assert(checked_out) }
122
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'yes')
123
+ ensure
124
+ tp_finish(dir, good_config_path)
125
+ end #begin
126
+ end #in_temp_tp_dir do...
127
+ end
128
+
129
+ def test_abort_on_config_mismatch
130
+ skip_if_no_s3_credentials('tp-assign abort on config mismatch test')
131
+ in_temp_tp_dir do |dir|
132
+ config = config_from_dir(dir)
133
+ good_config_path = setup_s3_config(dir, config, '.config_s3_good')
134
+ tp_make(dir, good_config_path)
135
+ begin
136
+ tp_finish_outside_sandbox(dir, good_config_path)
137
+ assert(config.amazon.bucket)
138
+ new_bucket = 'configmismatch-test'
139
+ refute_equal(new_bucket, config.amazon.bucket)
140
+ config.amazon.bucket = new_bucket
141
+ bad_config_path = setup_s3_config(dir, config, '.config_s3_bad')
142
+ exception = assert_raises(Typingpool::Error::Shell) do
143
+ tp_assign(dir, bad_config_path)
144
+ end #assert_raises...
145
+ assert_match(exception.message, /\burls don't look right\b/i)
146
+ ensure
147
+ tp_finish(dir, good_config_path)
148
+ end #begin
149
+ end #in_temp_tp_dir do...
150
+ end
151
+
152
+ end #TestTpAssign
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpReview < Typingpool::Test::Script
9
+
10
+ def test_tp_review
11
+ in_temp_tp_dir do |dir|
12
+ skip_if_no_upload_credentials('tp-review integration test')
13
+ skip_if_no_amazon_credentials('tp-review integration test')
14
+ tp_make(dir)
15
+ copy_fixtures_to_temp_tp_dir(dir, 'tp_review_')
16
+ assert(File.exists? File.join(temp_tp_dir_project_dir(dir), 'data','sandbox-assignment.csv'))
17
+ project = temp_tp_dir_project(dir)
18
+ assert_equal(7, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
19
+ begin
20
+ output = nil
21
+ assert_nothing_raised do
22
+ output = tp_review_with_fixture(dir, File.join(fixtures_dir, 'vcr', 'tp-review-1'), %w(a r a r s q))
23
+ end
24
+ assert_equal(0, output[:status].to_i, "Bad exit code: #{output[:status]} err: #{output[:err]}")
25
+ assert_equal(5, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
26
+ reviews = split_reviews(output[:out])
27
+ assert_match(reviews[1], /Interview\.00\.00/)
28
+ #we can't specify leading \b boundaries because the ansi
29
+ #escape sequences mess that up
30
+ assert_match(reviews[1], /Approved\b/i)
31
+ assert_match(reviews[2], /Interview\.00\.20/)
32
+ assert_match(reviews[2], /reason\b/i)
33
+ assert_match(reviews[2], /Rejected\b/i)
34
+ assert_match(reviews[3], /Interview\.00\.40/)
35
+ assert_match(reviews[3], /Approved\b/i)
36
+ assert_match(reviews[4], /Interview\.01\.00/)
37
+ assert_match(reviews[4], /reason\b/i)
38
+ assert_match(reviews[4], /Rejected\b/i)
39
+ assert_match(reviews[5], /Interview\.01\.20/)
40
+ assert_match(reviews[5], /Skipping\b/i)
41
+ assert_match(reviews[6], /Interview\.02\.00/)
42
+ assert_match(reviews[6], /Quitting\b/i)
43
+ transcript = assert_has_partial_transcript(dir)
44
+ assert_html_has_audio_count(2, transcript)
45
+ assert_assignment_csv_has_transcription_count(2, project, 'sandbox-assignment.csv')
46
+
47
+ assert_nothing_raised do
48
+ output = tp_review_with_fixture(dir, File.join(fixtures_dir, 'vcr', 'tp-review-2'), %w(a r))
49
+ end
50
+ assert_equal(0, output[:status].to_i, "Bad exit code: #{output[:status]} err: #{output[:err]}")
51
+ assert_equal(4, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
52
+ reviews = split_reviews(output[:out])
53
+ assert_match(reviews[1], /Interview\.01\.20/)
54
+ assert_match(reviews[1], /Approved\b/i)
55
+ assert_match(reviews[2], /Interview\.02\.00/)
56
+ assert_match(reviews[2], /reason\b/i)
57
+ assert_match(reviews[2], /Rejected\b/i)
58
+ transcript = assert_has_partial_transcript(dir)
59
+ assert_html_has_audio_count(3, transcript)
60
+ assert_assignment_csv_has_transcription_count(3, project, 'sandbox-assignment.csv')
61
+ ensure
62
+ rm_fixtures_from_temp_tp_dir(dir, 'tp_review_')
63
+ tp_finish(dir)
64
+ end #begin
65
+ end #in_temp_tp_dir
66
+ end
67
+
68
+ def split_reviews(output)
69
+ output.split(/Transcript for\b/)
70
+ end
71
+
72
+ end #class TestTpReview
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpCollect < Typingpool::Test::Script
9
+ require 'fileutils'
10
+
11
+ def test_tp_collect
12
+ in_temp_tp_dir do |dir|
13
+ skip_if_no_upload_credentials('tp-collect integration test')
14
+ skip_if_no_amazon_credentials('tp-collect integration test')
15
+ tp_make(dir)
16
+ copy_fixtures_to_temp_tp_dir(dir, 'tp_collect_')
17
+ begin
18
+ project = temp_tp_dir_project(dir)
19
+ assert_nothing_raised do
20
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-1'))
21
+ end
22
+ transcript = assert_has_partial_transcript(dir)
23
+ assert_html_has_audio_count(2, transcript)
24
+ assert_assignment_csv_has_transcription_count(2, project, 'sandbox-assignment.csv')
25
+ assert_nothing_raised do
26
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-2'))
27
+ end
28
+ transcript = assert_has_partial_transcript(dir)
29
+ assert_html_has_audio_count(4, transcript)
30
+ assert_assignment_csv_has_transcription_count(4, project, 'sandbox-assignment.csv')
31
+ assert_nothing_raised do
32
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-3'))
33
+ end
34
+ # transcript = assert_has_transcript(dir) || assert_has_partial_transcript(dir)
35
+ # assert_html_has_audio_count(7, transcript)
36
+ # assert_assignment_csv_has_transcription_count(7, project, 'sandbox-assignment.csv')
37
+ ensure
38
+ rm_fixtures_from_temp_tp_dir(dir, 'tp_collect_')
39
+ tp_finish(dir)
40
+ end #begin
41
+ end #in_temp_tp_dir
42
+ end
43
+
44
+ end #TestTpCollect
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpFinish < Typingpool::Test::Script
9
+ def tp_finish_on_audio_files_with(dir, config_path)
10
+ skip_if_no_amazon_credentials('tp-finish audio test')
11
+ skip_if_no_upload_credentials('tp-finish audio test')
12
+ tp_make(dir, config_path)
13
+ project = temp_tp_dir_project(dir, Typingpool::Config.file(config_path))
14
+ csv = project.local.file('data', 'assignment.csv').as(:csv)
15
+ urls = csv.map{|assignment| assignment['audio_url'] }
16
+ refute_empty(urls)
17
+ assert_all_assets_have_upload_status(csv, ['audio'], 'yes')
18
+ assert_equal(urls.size, urls.select{|url| working_url? url}.size)
19
+ assert_nothing_raised do
20
+ tp_finish_outside_sandbox(dir, config_path)
21
+ end
22
+ assert_empty(urls.select{|url| working_url? url })
23
+ assert_all_assets_have_upload_status(csv, ['audio'], 'no')
24
+ end
25
+
26
+ def test_tp_finish_on_audio_files
27
+ in_temp_tp_dir do |dir|
28
+ config_path = self.config_path(dir)
29
+ tp_finish_on_audio_files_with(dir, config_path)
30
+ end
31
+ end
32
+
33
+ def test_tp_finish_on_audio_files_with_s3
34
+ in_temp_tp_dir do |dir|
35
+ config = config_from_dir(dir)
36
+ config.to_hash.delete('sftp')
37
+ config_path = write_config(config, dir)
38
+ tp_finish_on_audio_files_with(dir, config_path)
39
+ end
40
+ end
41
+
42
+ def test_tp_finish_on_amazon_hits
43
+ skip_if_no_amazon_credentials('tp-finish Amazon test')
44
+ skip_if_no_upload_credentials('tp-finish Amazon test')
45
+ in_temp_tp_dir do |dir|
46
+ tp_make(dir)
47
+ tp_assign(dir)
48
+ project = temp_tp_dir_project(dir)
49
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
50
+ assert_all_assets_have_upload_status(sandbox_csv, ['audio', 'assignment'], 'yes')
51
+ setup_amazon(dir)
52
+ results = Typingpool::Amazon::HIT.all_for_project(project.local.id)
53
+ refute_empty(results)
54
+ assert_nothing_raised do
55
+ tp_finish(dir)
56
+ end
57
+ assert_empty(Typingpool::Amazon::HIT.all_for_project(project.local.id))
58
+ results.each do |result|
59
+ #The original HIT might be gone, or there and marked
60
+ #'disposed', depending whether Amazon has swept the server for
61
+ #dead HITs yet
62
+ begin
63
+ hit = RTurk::Hit.find(result.id)
64
+ assert_match(hit.status, /^dispos/i)
65
+ rescue RTurk::InvalidRequest => exception
66
+ assert_match(exception.message, /HITDoesNotExist/i)
67
+ end #begin
68
+ end #results.each...
69
+ refute(File.exists? sandbox_csv)
70
+ assert_all_assets_have_upload_status(project.local.file('data', 'assignment.csv').as(:csv), ['audio'], 'no')
71
+ end #in_temp_tp_dir
72
+ end
73
+
74
+ def test_tp_finish_with_missing_files
75
+ skip_if_no_amazon_credentials('tp-finish missing files test')
76
+ skip_if_no_upload_credentials('tp-finish missing files test')
77
+ in_temp_tp_dir do |dir|
78
+ project = nil
79
+ tp_make(dir)
80
+ begin
81
+ project = temp_tp_dir_project(dir)
82
+ assignments = project.local.file('data', 'assignment.csv').as(:csv).read
83
+ urls = assignments.map{|assignment| assignment['audio_url'] }
84
+ assert_empty(urls.reject{|url| working_url? url })
85
+ bogus_url = urls.first.sub(/\.mp3/, '.foo.mp3')
86
+ refute_equal(urls.first, bogus_url)
87
+ refute(working_url? bogus_url)
88
+ bogus_assignment = assignments.first.dup
89
+ bogus_assignment['audio_url'] = bogus_url
90
+ assignments.insert(1, bogus_assignment)
91
+ project.local.file('data', 'assignment.csv').as(:csv).write(assignments)
92
+ assert_equal(1, project.local.file('data', 'assignment.csv').as(:csv).reject{|assignment| working_url? assignment['audio_url'] }.count)
93
+ ensure
94
+ tp_finish_outside_sandbox(dir)
95
+ end #begin
96
+ assert_empty(project.local.file('data', 'assignment.csv').as(:csv).select{|assignment| working_url? assignment['audio_url'] })
97
+ end #in_temp_tp_dir...
98
+ end
99
+
100
+ def test_abort_on_config_mismatch
101
+ skip_if_no_s3_credentials('tp-finish abort on config mismatch test')
102
+ in_temp_tp_dir do |dir|
103
+ config = config_from_dir(dir)
104
+ good_config_path = setup_s3_config(dir, config, '.config_s3_good')
105
+ tp_make(dir, good_config_path)
106
+ begin
107
+ assert(config.amazon.bucket)
108
+ new_bucket = 'configmismatch-test'
109
+ refute_equal(new_bucket, config.amazon.bucket)
110
+ config.amazon.bucket = new_bucket
111
+ bad_config_path = setup_s3_config(dir, config, '.config_s3_bad')
112
+ exception = assert_raises(Typingpool::Error::Shell) do
113
+ tp_finish_outside_sandbox(dir, bad_config_path)
114
+ end #assert_raises...
115
+ assert_match(exception.message, /\burls don't look right\b/i)
116
+ ensure
117
+ tp_finish_outside_sandbox(dir, good_config_path)
118
+ end #begin
119
+ end #in_temp_tp_dir do...
120
+
121
+ end
122
+
123
+ end #TestTpFinish