typingpool 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +452 -0
  3. data/lib/typingpool/amazon/hit/assignment/empty.rb +19 -0
  4. data/lib/typingpool/amazon/hit/assignment.rb +43 -0
  5. data/lib/typingpool/amazon/hit/full/fromsearchhits.rb +44 -0
  6. data/lib/typingpool/amazon/hit/full.rb +105 -0
  7. data/lib/typingpool/amazon/hit.rb +458 -0
  8. data/lib/typingpool/amazon/question.rb +45 -0
  9. data/lib/typingpool/amazon.rb +3 -677
  10. data/lib/typingpool/app/cli/formatter.rb +16 -0
  11. data/lib/typingpool/app/cli.rb +64 -0
  12. data/lib/typingpool/app/friendlyexceptions.rb +34 -0
  13. data/lib/typingpool/app.rb +2 -97
  14. data/lib/typingpool/config/root.rb +114 -0
  15. data/lib/typingpool/config.rb +13 -119
  16. data/lib/typingpool/filer/audio.rb +84 -0
  17. data/lib/typingpool/filer/csv.rb +57 -0
  18. data/lib/typingpool/filer/dir.rb +76 -0
  19. data/lib/typingpool/filer/files/audio.rb +63 -0
  20. data/lib/typingpool/filer/files.rb +55 -0
  21. data/lib/typingpool/filer.rb +4 -313
  22. data/lib/typingpool/project/local.rb +117 -0
  23. data/lib/typingpool/project/remote/s3.rb +135 -0
  24. data/lib/typingpool/project/remote/sftp.rb +100 -0
  25. data/lib/typingpool/project/remote.rb +65 -0
  26. data/lib/typingpool/project.rb +2 -396
  27. data/lib/typingpool/template/assignment.rb +17 -0
  28. data/lib/typingpool/template/env.rb +77 -0
  29. data/lib/typingpool/template.rb +2 -87
  30. data/lib/typingpool/test/script.rb +310 -0
  31. data/lib/typingpool/test.rb +1 -306
  32. data/lib/typingpool/transcript/chunk.rb +129 -0
  33. data/lib/typingpool/transcript.rb +1 -125
  34. data/lib/typingpool/utility/castable.rb +65 -0
  35. data/lib/typingpool/utility.rb +1 -61
  36. data/test/test_integration_script_6_tp_finish.rb +1 -0
  37. metadata +135 -81
@@ -0,0 +1,310 @@
1
+ module Typingpool
2
+ class Test
3
+ class Script < Test
4
+ require 'typingpool'
5
+ require 'yaml'
6
+ require 'open3'
7
+
8
+
9
+ def audio_files(subdir='mp3')
10
+ dir = File.join(audio_dir, subdir)
11
+ Dir.entries(dir).reject{|entry| entry.match(/^\./) }.map{|entry| File.join(dir, entry)}.select{|path| File.file?(path) }
12
+ end
13
+
14
+ def config_path(dir)
15
+ ::File.join(dir, project_default[:config_filename])
16
+ end
17
+
18
+ def config_from_dir(dir)
19
+ Config.file(config_path(dir))
20
+ end
21
+
22
+
23
+ def setup_amazon(dir)
24
+ Amazon.setup(:sandbox => true, :config => config_from_dir(dir))
25
+ end
26
+
27
+
28
+ def in_temp_tp_dir
29
+ ::Dir.mktmpdir('typingpool_') do |dir|
30
+ setup_temp_tp_dir(dir)
31
+ yield(dir)
32
+ end
33
+ end
34
+
35
+ def setup_temp_tp_dir(dir)
36
+ make_temp_tp_dir_config(dir)
37
+ Dir.mkdir(File.join(dir, 'projects'))
38
+ end
39
+
40
+ def setup_s3_config(dir, config=config_from_dir(dir), filename='.config_s3')
41
+ return unless s3_credentials?(config)
42
+ config.to_hash.delete('sftp')
43
+ write_config(config, dir, filename)
44
+ end
45
+
46
+ def setup_s3_config_with_bad_password(dir, config=config_from_dir(dir))
47
+ bad_password = 'f'
48
+ refute_equal(config.to_hash['amazon']['secret'], bad_password)
49
+ config.to_hash['amazon']['secret'] = bad_password
50
+ setup_s3_config(dir, config, '.config_s3_bad')
51
+ end
52
+
53
+ def make_temp_tp_dir_config(dir, config=self.config)
54
+ config.transcripts = File.join(dir, 'projects')
55
+ config.cache = File.join(dir, '.cache')
56
+ config['assign']['reward'] = '0.02'
57
+ config.assign.to_hash.delete('qualify')
58
+ write_config(config, dir, project_default[:config_filename])
59
+ end
60
+
61
+ def write_config(config, dir, filename=project_default[:config_filename])
62
+ path = ::File.join(dir, filename)
63
+ ::File.open(path, 'w') do |out|
64
+ out << YAML.dump(config.to_hash)
65
+ end
66
+ path
67
+ end
68
+
69
+ def temp_tp_dir_project_dir(temp_tp_dir)
70
+ ::File.join(temp_tp_dir, 'projects', project_default[:title])
71
+ end
72
+
73
+ def temp_tp_dir_project(dir, config=config_from_dir(dir))
74
+ Project.new(project_default[:title], config)
75
+ end
76
+
77
+ def call_script(*args)
78
+ Utility.system_quietly(*args)
79
+ end
80
+
81
+ def path_to_tp_make
82
+ ::File.join(self.class.app_dir, 'bin', 'tp-make')
83
+ end
84
+
85
+ def call_tp_make(*args)
86
+ call_script(path_to_tp_make, *args)
87
+ end
88
+
89
+ def tp_make(in_dir, config=config_path(in_dir), audio_subdir='mp3')
90
+ call_tp_make(
91
+ '--config', config,
92
+ '--chunks', project_default[:chunks],
93
+ *[:title, :subtitle].map{|param| ["--#{param}", project_default[param]] }.flatten,
94
+ *[:voice, :unusual].map{|param| project_default[param].map{|value| ["--#{param}", value] } }.flatten,
95
+ *audio_files(audio_subdir).map{|path| ['--file', path]}.flatten
96
+ )
97
+ end
98
+
99
+ def path_to_tp_finish
100
+ ::File.join(self.class.app_dir, 'bin', 'tp-finish')
101
+ end
102
+
103
+ def call_tp_finish(*args)
104
+ call_script(path_to_tp_finish, *args)
105
+ end
106
+
107
+ def tp_finish(dir, config_path=self.config_path(dir))
108
+ tp_finish_inside_sandbox(dir, config_path)
109
+ tp_finish_outside_sandbox(dir, config_path)
110
+ end
111
+
112
+
113
+ def tp_finish_inside_sandbox(dir, config_path=self.config_path(dir))
114
+ tp_finish_outside_sandbox(dir, config_path, '--sandbox')
115
+ end
116
+
117
+ def tp_finish_outside_sandbox(dir, config_path=self.config_path(dir), *args)
118
+ call_tp_finish(
119
+ project_default[:title],
120
+ '--config', config_path,
121
+ *args
122
+ )
123
+ end
124
+
125
+ def path_to_tp_assign
126
+ File.join(self.class.app_dir, 'bin', 'tp-assign')
127
+ end
128
+
129
+ def call_tp_assign(*args)
130
+ call_script(path_to_tp_assign, '--sandbox', *args)
131
+ end
132
+
133
+ def assign_default
134
+ Hash[
135
+ :template => 'interview/phone',
136
+ :deadline => '5h',
137
+ :lifetime => '10h',
138
+ :approval => '10h',
139
+ :qualify => ['approval_rate >= 90', 'hits_approved > 10'],
140
+ :keyword => ['test', 'mp3', 'typingpooltest']
141
+ ]
142
+ end
143
+
144
+ def tp_assign(dir, config_path=config_path(dir))
145
+ call_tp_assign(
146
+ project_default[:title],
147
+ assign_default[:template],
148
+ '--config', config_path,
149
+ *[:deadline, :lifetime, :approval].map{|param| ["--#{param}", assign_default[param]] }.flatten,
150
+ *[:qualify, :keyword].map{|param| assign_default[param].map{|value| ["--#{param}", value] } }.flatten
151
+ )
152
+ end
153
+
154
+ def path_to_tp_collect
155
+ File.join(self.class.app_dir, 'bin', 'tp-collect')
156
+ end
157
+
158
+ def call_tp_collect(fixture_path, *args)
159
+ call_script(path_to_tp_collect, '--sandbox', '--fixture', fixture_path, *args)
160
+ end
161
+
162
+ def tp_collect_with_fixture(dir, fixture_path)
163
+ call_tp_collect(
164
+ fixture_path,
165
+ '--config', config_path(dir)
166
+ )
167
+ end
168
+
169
+
170
+ def path_to_tp_review
171
+ File.join(self.class.app_dir, 'bin', 'tp-review')
172
+ end
173
+
174
+ def tp_review_with_fixture(dir, fixture_path, choices)
175
+ output = {}
176
+ Open3.popen3(path_to_tp_review, '--sandbox', '--fixture', fixture_path, '--config', config_path(dir), project_default[:title]) do |stdin, stdout, stderr, wait_thr|
177
+ choices.each do |choice|
178
+ stdin.puts(choice)
179
+ if choice.strip.match(/^r/i)
180
+ stdin.puts("No reason - this is a test")
181
+ end
182
+ end
183
+ output[:out] = stdout.gets(nil)
184
+ output[:err] = stderr.gets(nil)
185
+ [stdin, stdout, stderr].each{|stream| stream.close }
186
+ output[:status] = wait_thr.value
187
+ end
188
+ output
189
+ end
190
+
191
+ def path_to_tp_config
192
+ File.join(self.class.app_dir, 'bin', 'tp-config')
193
+ end
194
+
195
+ def tp_config(*args)
196
+ call_script(path_to_tp_config, *args)
197
+ end
198
+
199
+ def tp_config_with_input(args, input)
200
+ output = {}
201
+ Open3.popen3(path_to_tp_config, *args) do |stdin, stdout, stderr, wait_thr|
202
+ input.each do |sending|
203
+ stdin.puts(sending)
204
+ end
205
+ output[:out] = stdout.gets(nil)
206
+ output[:err] = stderr.gets(nil)
207
+ [stdin, stdout, stderr].each{|stream| stream.close }
208
+ output[:status] = wait_thr.value
209
+ end #Open3.popen3...
210
+ output
211
+ end
212
+
213
+ def fixture_project_dir(name)
214
+ File.join(fixtures_dir, name)
215
+ end
216
+
217
+ def make_fixture_project_dir(name)
218
+ dir = fixture_project_dir(name)
219
+ if File.exists? dir
220
+ raise Error::Test, "Fixture project already exists for #{name} at #{dir}"
221
+ end
222
+ ::Dir.mkdir(dir)
223
+ dir
224
+ end
225
+
226
+ def remove_fixture_project_dir(name)
227
+ FileUtils.remove_entry_secure(fixture_project_dir(name), :secure => true)
228
+ end
229
+
230
+ def with_fixtures_in_temp_tp_dir(dir, fixture_prefix)
231
+ fixtures = Dir.entries(fixtures_dir).select{|entry| entry.include?(fixture_prefix) && entry.index(fixture_prefix) == 0 }.select{|entry| File.file?(File.join(fixtures_dir, entry)) }
232
+ fixtures.map!{|fixture| fixture[fixture_prefix.size .. -1] }
233
+ fixtures.each do |fixture|
234
+ project_path = File.join(temp_tp_dir_project_dir(dir), 'data', fixture)
235
+ fixture_path = File.join(fixtures_dir, [fixture_prefix, fixture].join )
236
+ yield(fixture_path, project_path)
237
+ end
238
+ end
239
+
240
+ def copy_fixtures_to_temp_tp_dir(dir, fixture_prefix)
241
+ with_fixtures_in_temp_tp_dir(dir, fixture_prefix) do |fixture_path, project_path|
242
+ if File.exists? project_path
243
+ FileUtils.mv(project_path, File.join(File.dirname(project_path), "orig_#{File.basename(project_path)}"))
244
+ end
245
+ FileUtils.cp(fixture_path, project_path)
246
+ end
247
+ end
248
+
249
+ def rm_fixtures_from_temp_tp_dir(dir, fixture_prefix)
250
+ with_fixtures_in_temp_tp_dir(dir, fixture_prefix) do |fixture_path, project_path|
251
+ FileUtils.rm(project_path)
252
+ path_to_orig = File.join(File.dirname(project_path), "orig_#{File.basename(project_path)}")
253
+ if File.exists?(path_to_orig)
254
+ FileUtils.mv(path_to_orig, project_path)
255
+ end
256
+ end
257
+ end
258
+
259
+ def assert_has_transcript(dir, transcript_file='transcript.html')
260
+ transcript_path = File.join(temp_tp_dir_project_dir(dir), transcript_file)
261
+ assert(File.exists?(transcript_path))
262
+ assert(not((transcript = IO.read(transcript_path)).empty?))
263
+ transcript
264
+ end
265
+
266
+ def assert_has_partial_transcript(dir)
267
+ assert_has_transcript(dir, 'transcript_in_progress.html')
268
+ end
269
+
270
+ def assert_assignment_csv_has_transcription_count(count, project, which_csv='assignment.csv')
271
+ assert_equal(count, project.local.file('data', which_csv).as(:csv).reject{|assignment| assignment['transcript'].to_s.empty?}.size)
272
+ end
273
+
274
+ def assert_html_has_audio_count(count, html)
275
+ assert_equal(count, noko(html).css('audio').size)
276
+ end
277
+
278
+ def assert_all_assets_have_upload_status(assignment_csv, types, status)
279
+ types.each do |type|
280
+ recorded_uploads = assignment_csv.map{|assignment| assignment["#{type}_uploaded"] }
281
+ refute_empty(recorded_uploads)
282
+ assert_equal(recorded_uploads.count, recorded_uploads.select{|uploaded| uploaded == status }.count)
283
+ end
284
+ end
285
+
286
+ def assert_shell_error_match(regex)
287
+ exception = assert_raise(Typingpool::Error::Shell) do
288
+ yield
289
+ end
290
+ assert_match(exception.message, regex)
291
+ end
292
+
293
+ def assert_script_abort_match(args, regex)
294
+ in_temp_tp_dir do |dir|
295
+ assert_shell_error_match(regex) do
296
+ yield([*args, '--config', config_path(dir)])
297
+ end
298
+ end #in_temp_tp_dir do...
299
+ end
300
+
301
+ def noko(html)
302
+ Nokogiri::HTML(html)
303
+ end
304
+
305
+ def vcr_dir
306
+ File.join(fixtures_dir, 'vcr')
307
+ end
308
+ end #Script
309
+ end #Test
310
+ end #Typingpool
@@ -108,311 +108,6 @@ module Typingpool
108
108
  Typingpool::Utility.fetch_url(*args)
109
109
  end
110
110
 
111
- class Script < Test
112
- require 'typingpool'
113
- require 'yaml'
114
- require 'open3'
115
-
116
-
117
- def audio_files(subdir='mp3')
118
- dir = File.join(audio_dir, subdir)
119
- Dir.entries(dir).reject{|entry| entry.match(/^\./) }.map{|entry| File.join(dir, entry)}.select{|path| File.file?(path) }
120
- end
121
-
122
- def config_path(dir)
123
- ::File.join(dir, project_default[:config_filename])
124
- end
125
-
126
- def config_from_dir(dir)
127
- Config.file(config_path(dir))
128
- end
129
-
130
-
131
- def setup_amazon(dir)
132
- Amazon.setup(:sandbox => true, :config => config_from_dir(dir))
133
- end
134
-
135
-
136
- def in_temp_tp_dir
137
- ::Dir.mktmpdir('typingpool_') do |dir|
138
- setup_temp_tp_dir(dir)
139
- yield(dir)
140
- end
141
- end
142
-
143
- def setup_temp_tp_dir(dir)
144
- make_temp_tp_dir_config(dir)
145
- Dir.mkdir(File.join(dir, 'projects'))
146
- end
147
-
148
- def setup_s3_config(dir, config=config_from_dir(dir), filename='.config_s3')
149
- return unless s3_credentials?(config)
150
- config.to_hash.delete('sftp')
151
- write_config(config, dir, filename)
152
- end
153
-
154
- def setup_s3_config_with_bad_password(dir, config=config_from_dir(dir))
155
- bad_password = 'f'
156
- refute_equal(config.to_hash['amazon']['secret'], bad_password)
157
- config.to_hash['amazon']['secret'] = bad_password
158
- setup_s3_config(dir, config, '.config_s3_bad')
159
- end
160
-
161
- def make_temp_tp_dir_config(dir, config=self.config)
162
- config.transcripts = File.join(dir, 'projects')
163
- config.cache = File.join(dir, '.cache')
164
- config['assign']['reward'] = '0.02'
165
- config.assign.to_hash.delete('qualify')
166
- write_config(config, dir, project_default[:config_filename])
167
- end
168
-
169
- def write_config(config, dir, filename=project_default[:config_filename])
170
- path = ::File.join(dir, filename)
171
- ::File.open(path, 'w') do |out|
172
- out << YAML.dump(config.to_hash)
173
- end
174
- path
175
- end
176
-
177
- def temp_tp_dir_project_dir(temp_tp_dir)
178
- ::File.join(temp_tp_dir, 'projects', project_default[:title])
179
- end
180
-
181
- def temp_tp_dir_project(dir, config=config_from_dir(dir))
182
- Project.new(project_default[:title], config)
183
- end
184
-
185
- def call_script(*args)
186
- Utility.system_quietly(*args)
187
- end
188
-
189
- def path_to_tp_make
190
- ::File.join(self.class.app_dir, 'bin', 'tp-make')
191
- end
192
-
193
- def call_tp_make(*args)
194
- call_script(path_to_tp_make, *args)
195
- end
196
-
197
- def tp_make(in_dir, config=config_path(in_dir), audio_subdir='mp3')
198
- call_tp_make(
199
- '--config', config,
200
- '--chunks', project_default[:chunks],
201
- *[:title, :subtitle].map{|param| ["--#{param}", project_default[param]] }.flatten,
202
- *[:voice, :unusual].map{|param| project_default[param].map{|value| ["--#{param}", value] } }.flatten,
203
- *audio_files(audio_subdir).map{|path| ['--file', path]}.flatten
204
- )
205
- end
206
-
207
- def path_to_tp_finish
208
- ::File.join(self.class.app_dir, 'bin', 'tp-finish')
209
- end
210
-
211
- def call_tp_finish(*args)
212
- call_script(path_to_tp_finish, *args)
213
- end
214
-
215
- def tp_finish(dir, config_path=self.config_path(dir))
216
- tp_finish_inside_sandbox(dir, config_path)
217
- tp_finish_outside_sandbox(dir, config_path)
218
- end
219
-
220
-
221
- def tp_finish_inside_sandbox(dir, config_path=self.config_path(dir))
222
- tp_finish_outside_sandbox(dir, config_path, '--sandbox')
223
- end
224
-
225
- def tp_finish_outside_sandbox(dir, config_path=self.config_path(dir), *args)
226
- call_tp_finish(
227
- project_default[:title],
228
- '--config', config_path,
229
- *args
230
- )
231
- end
232
-
233
- def path_to_tp_assign
234
- File.join(self.class.app_dir, 'bin', 'tp-assign')
235
- end
236
-
237
- def call_tp_assign(*args)
238
- call_script(path_to_tp_assign, '--sandbox', *args)
239
- end
240
-
241
- def assign_default
242
- Hash[
243
- :template => 'interview/phone',
244
- :deadline => '5h',
245
- :lifetime => '10h',
246
- :approval => '10h',
247
- :qualify => ['approval_rate >= 90', 'hits_approved > 10'],
248
- :keyword => ['test', 'mp3', 'typingpooltest']
249
- ]
250
- end
251
-
252
- def tp_assign(dir, config_path=config_path(dir))
253
- call_tp_assign(
254
- project_default[:title],
255
- assign_default[:template],
256
- '--config', config_path,
257
- *[:deadline, :lifetime, :approval].map{|param| ["--#{param}", assign_default[param]] }.flatten,
258
- *[:qualify, :keyword].map{|param| assign_default[param].map{|value| ["--#{param}", value] } }.flatten
259
- )
260
- end
261
-
262
- def path_to_tp_collect
263
- File.join(self.class.app_dir, 'bin', 'tp-collect')
264
- end
265
-
266
- def call_tp_collect(fixture_path, *args)
267
- call_script(path_to_tp_collect, '--sandbox', '--fixture', fixture_path, *args)
268
- end
269
-
270
- def tp_collect_with_fixture(dir, fixture_path)
271
- call_tp_collect(
272
- fixture_path,
273
- '--config', config_path(dir)
274
- )
275
- end
276
-
277
-
278
- def path_to_tp_review
279
- File.join(self.class.app_dir, 'bin', 'tp-review')
280
- end
281
-
282
- def tp_review_with_fixture(dir, fixture_path, choices)
283
- output = {}
284
- Open3.popen3(path_to_tp_review, '--sandbox', '--fixture', fixture_path, '--config', config_path(dir), project_default[:title]) do |stdin, stdout, stderr, wait_thr|
285
- choices.each do |choice|
286
- stdin.puts(choice)
287
- if choice.strip.match(/^r/i)
288
- stdin.puts("No reason - this is a test")
289
- end
290
- end
291
- output[:out] = stdout.gets(nil)
292
- output[:err] = stderr.gets(nil)
293
- [stdin, stdout, stderr].each{|stream| stream.close }
294
- output[:status] = wait_thr.value
295
- end
296
- output
297
- end
298
-
299
- def path_to_tp_config
300
- File.join(self.class.app_dir, 'bin', 'tp-config')
301
- end
302
-
303
- def tp_config(*args)
304
- call_script(path_to_tp_config, *args)
305
- end
306
-
307
- def tp_config_with_input(args, input)
308
- output = {}
309
- Open3.popen3(path_to_tp_config, *args) do |stdin, stdout, stderr, wait_thr|
310
- input.each do |sending|
311
- stdin.puts(sending)
312
- end
313
- output[:out] = stdout.gets(nil)
314
- output[:err] = stderr.gets(nil)
315
- [stdin, stdout, stderr].each{|stream| stream.close }
316
- output[:status] = wait_thr.value
317
- end #Open3.popen3...
318
- output
319
- end
320
-
321
- def fixture_project_dir(name)
322
- File.join(fixtures_dir, name)
323
- end
324
-
325
- def make_fixture_project_dir(name)
326
- dir = fixture_project_dir(name)
327
- if File.exists? dir
328
- raise Error::Test, "Fixture project already exists for #{name} at #{dir}"
329
- end
330
- ::Dir.mkdir(dir)
331
- dir
332
- end
333
-
334
- def remove_fixture_project_dir(name)
335
- FileUtils.remove_entry_secure(fixture_project_dir(name), :secure => true)
336
- end
337
-
338
- def with_fixtures_in_temp_tp_dir(dir, fixture_prefix)
339
- fixtures = Dir.entries(fixtures_dir).select{|entry| entry.include?(fixture_prefix) && entry.index(fixture_prefix) == 0 }.select{|entry| File.file?(File.join(fixtures_dir, entry)) }
340
- fixtures.map!{|fixture| fixture[fixture_prefix.size .. -1] }
341
- fixtures.each do |fixture|
342
- project_path = File.join(temp_tp_dir_project_dir(dir), 'data', fixture)
343
- fixture_path = File.join(fixtures_dir, [fixture_prefix, fixture].join )
344
- yield(fixture_path, project_path)
345
- end
346
- end
347
-
348
- def copy_fixtures_to_temp_tp_dir(dir, fixture_prefix)
349
- with_fixtures_in_temp_tp_dir(dir, fixture_prefix) do |fixture_path, project_path|
350
- if File.exists? project_path
351
- FileUtils.mv(project_path, File.join(File.dirname(project_path), "orig_#{File.basename(project_path)}"))
352
- end
353
- FileUtils.cp(fixture_path, project_path)
354
- end
355
- end
356
-
357
- def rm_fixtures_from_temp_tp_dir(dir, fixture_prefix)
358
- with_fixtures_in_temp_tp_dir(dir, fixture_prefix) do |fixture_path, project_path|
359
- FileUtils.rm(project_path)
360
- path_to_orig = File.join(File.dirname(project_path), "orig_#{File.basename(project_path)}")
361
- if File.exists?(path_to_orig)
362
- FileUtils.mv(path_to_orig, project_path)
363
- end
364
- end
365
- end
366
-
367
- def assert_has_transcript(dir, transcript_file='transcript.html')
368
- transcript_path = File.join(temp_tp_dir_project_dir(dir), transcript_file)
369
- assert(File.exists?(transcript_path))
370
- assert(not((transcript = IO.read(transcript_path)).empty?))
371
- transcript
372
- end
373
-
374
- def assert_has_partial_transcript(dir)
375
- assert_has_transcript(dir, 'transcript_in_progress.html')
376
- end
377
-
378
- def assert_assignment_csv_has_transcription_count(count, project, which_csv='assignment.csv')
379
- assert_equal(count, project.local.file('data', which_csv).as(:csv).reject{|assignment| assignment['transcript'].to_s.empty?}.size)
380
- end
381
-
382
- def assert_html_has_audio_count(count, html)
383
- assert_equal(count, noko(html).css('audio').size)
384
- end
385
-
386
- def assert_all_assets_have_upload_status(assignment_csv, types, status)
387
- types.each do |type|
388
- recorded_uploads = assignment_csv.map{|assignment| assignment["#{type}_uploaded"] }
389
- refute_empty(recorded_uploads)
390
- assert_equal(recorded_uploads.count, recorded_uploads.select{|uploaded| uploaded == status }.count)
391
- end
392
- end
393
-
394
- def assert_shell_error_match(regex)
395
- exception = assert_raise(Typingpool::Error::Shell) do
396
- yield
397
- end
398
- assert_match(exception.message, regex)
399
- end
400
-
401
- def assert_script_abort_match(args, regex)
402
- in_temp_tp_dir do |dir|
403
- assert_shell_error_match(regex) do
404
- yield([*args, '--config', config_path(dir)])
405
- end
406
- end #in_temp_tp_dir do...
407
- end
408
-
409
- def noko(html)
410
- Nokogiri::HTML(html)
411
- end
412
-
413
- def vcr_dir
414
- File.join(fixtures_dir, 'vcr')
415
- end
416
- end #Script
111
+ require 'typingpool/test/script'
417
112
  end #Test
418
113
  end #Typingpool