typingpool 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +452 -0
- data/lib/typingpool/amazon/hit/assignment/empty.rb +19 -0
- data/lib/typingpool/amazon/hit/assignment.rb +43 -0
- data/lib/typingpool/amazon/hit/full/fromsearchhits.rb +44 -0
- data/lib/typingpool/amazon/hit/full.rb +105 -0
- data/lib/typingpool/amazon/hit.rb +458 -0
- data/lib/typingpool/amazon/question.rb +45 -0
- data/lib/typingpool/amazon.rb +3 -677
- data/lib/typingpool/app/cli/formatter.rb +16 -0
- data/lib/typingpool/app/cli.rb +64 -0
- data/lib/typingpool/app/friendlyexceptions.rb +34 -0
- data/lib/typingpool/app.rb +2 -97
- data/lib/typingpool/config/root.rb +114 -0
- data/lib/typingpool/config.rb +13 -119
- data/lib/typingpool/filer/audio.rb +84 -0
- data/lib/typingpool/filer/csv.rb +57 -0
- data/lib/typingpool/filer/dir.rb +76 -0
- data/lib/typingpool/filer/files/audio.rb +63 -0
- data/lib/typingpool/filer/files.rb +55 -0
- data/lib/typingpool/filer.rb +4 -313
- data/lib/typingpool/project/local.rb +117 -0
- data/lib/typingpool/project/remote/s3.rb +135 -0
- data/lib/typingpool/project/remote/sftp.rb +100 -0
- data/lib/typingpool/project/remote.rb +65 -0
- data/lib/typingpool/project.rb +2 -396
- data/lib/typingpool/template/assignment.rb +17 -0
- data/lib/typingpool/template/env.rb +77 -0
- data/lib/typingpool/template.rb +2 -87
- data/lib/typingpool/test/script.rb +310 -0
- data/lib/typingpool/test.rb +1 -306
- data/lib/typingpool/transcript/chunk.rb +129 -0
- data/lib/typingpool/transcript.rb +1 -125
- data/lib/typingpool/utility/castable.rb +65 -0
- data/lib/typingpool/utility.rb +1 -61
- data/test/test_integration_script_6_tp_finish.rb +1 -0
- 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
|
data/lib/typingpool/test.rb
CHANGED
@@ -108,311 +108,6 @@ module Typingpool
|
|
108
108
|
Typingpool::Utility.fetch_url(*args)
|
109
109
|
end
|
110
110
|
|
111
|
-
|
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
|