doi_extractor 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +54 -0
  3. data/Capfile +34 -0
  4. data/Gemfile +6 -0
  5. data/README.md +50 -0
  6. data/Rakefile +43 -0
  7. data/bin/doi_extractor +18 -0
  8. data/config/deploy.rb +34 -0
  9. data/config/deploy/production.rb +65 -0
  10. data/doi_extractor.gemspec +29 -0
  11. data/lib/doi_extractor.rb +25 -0
  12. data/lib/doi_extractor/cancel_command.rb +24 -0
  13. data/lib/doi_extractor/command.rb +81 -0
  14. data/lib/doi_extractor/command_line_parser.rb +154 -0
  15. data/lib/doi_extractor/create_command.rb +32 -0
  16. data/lib/doi_extractor/download_command.rb +109 -0
  17. data/lib/doi_extractor/download_location.rb +86 -0
  18. data/lib/doi_extractor/errors.rb +34 -0
  19. data/lib/doi_extractor/ipums_client.rb +159 -0
  20. data/lib/doi_extractor/ipums_uri_builder.rb +51 -0
  21. data/lib/doi_extractor/old_ruby_patch.rb +25 -0
  22. data/lib/doi_extractor/options.rb +132 -0
  23. data/lib/doi_extractor/secrets.rb +18 -0
  24. data/lib/doi_extractor/status_command.rb +62 -0
  25. data/lib/doi_extractor/version.rb +3 -0
  26. data/spec/fixtures/api_creds.yml +2 -0
  27. data/spec/reports/SPEC-DoiExtractor-CancelCommand-when-successful.xml +7 -0
  28. data/spec/reports/SPEC-DoiExtractor-CancelCommand.xml +3 -0
  29. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-a-valid-create-command-with-email.xml +14 -0
  30. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-a-valid-create-command.xml +9 -0
  31. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-a-valid-download-command.xml +9 -0
  32. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-a-valid-status-command.xml +9 -0
  33. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-an-invalid-command.xml +9 -0
  34. data/spec/reports/SPEC-DoiExtractor-CommandLineParser-with-an-unknown-option.xml +5 -0
  35. data/spec/reports/SPEC-DoiExtractor-CommandLineParser.xml +3 -0
  36. data/spec/reports/SPEC-DoiExtractor-CreateCommand-when-an-existing-extract-is-processing.xml +7 -0
  37. data/spec/reports/SPEC-DoiExtractor-CreateCommand-when-successful.xml +7 -0
  38. data/spec/reports/SPEC-DoiExtractor-CreateCommand.xml +3 -0
  39. data/spec/reports/SPEC-DoiExtractor-DownloadCommand-user-cancels-download.xml +7 -0
  40. data/spec/reports/SPEC-DoiExtractor-DownloadCommand-when-an-extract-is-available-when-force-is-not-set.xml +5 -0
  41. data/spec/reports/SPEC-DoiExtractor-DownloadCommand-when-an-extract-is-available.xml +13 -0
  42. data/spec/reports/SPEC-DoiExtractor-DownloadCommand.xml +3 -0
  43. data/spec/reports/SPEC-DoiExtractor-DownloadLocation.xml +11 -0
  44. data/spec/reports/SPEC-DoiExtractor-IpumsClient.xml +7 -0
  45. data/spec/reports/SPEC-DoiExtractor-IpumsUriBuilder-internal-environment.xml +5 -0
  46. data/spec/reports/SPEC-DoiExtractor-IpumsUriBuilder-live-environment.xml +5 -0
  47. data/spec/reports/SPEC-DoiExtractor-IpumsUriBuilder-local-environment.xml +5 -0
  48. data/spec/reports/SPEC-DoiExtractor-IpumsUriBuilder.xml +3 -0
  49. data/spec/reports/SPEC-DoiExtractor-Options-for-command-with-create-command-with-invalid-doi-version.xml +5 -0
  50. data/spec/reports/SPEC-DoiExtractor-Options-for-command-with-create-command.xml +7 -0
  51. data/spec/reports/SPEC-DoiExtractor-Options-for-command-with-download-command.xml +7 -0
  52. data/spec/reports/SPEC-DoiExtractor-Options-for-command-with-status-command.xml +7 -0
  53. data/spec/reports/SPEC-DoiExtractor-Options-for-command.xml +3 -0
  54. data/spec/reports/SPEC-DoiExtractor-Options-when-setting-path-values.xml +9 -0
  55. data/spec/reports/SPEC-DoiExtractor-Options.xml +5 -0
  56. data/spec/reports/SPEC-DoiExtractor-Secrets.xml +7 -0
  57. data/spec/reports/SPEC-DoiExtractor-StatusCommand.xml +5 -0
  58. data/spec/spec_helper.rb +20 -0
  59. data/spec/support/test_input.rb +36 -0
  60. data/spec/unit/cancel_command_spec.rb +28 -0
  61. data/spec/unit/command_line_parser_spec.rb +68 -0
  62. data/spec/unit/create_command_spec.rb +44 -0
  63. data/spec/unit/download_command_spec.rb +139 -0
  64. data/spec/unit/download_location_spec.rb +71 -0
  65. data/spec/unit/ipums_client_spec.rb +23 -0
  66. data/spec/unit/ipums_uri_builder_spec.rb +26 -0
  67. data/spec/unit/options_spec.rb +86 -0
  68. data/spec/unit/secrets_spec.rb +14 -0
  69. data/spec/unit/status_command_spec.rb +46 -0
  70. metadata +282 -0
@@ -0,0 +1,51 @@
1
+ module DoiExtractor
2
+ class IpumsUriBuilder
3
+
4
+ IpumsConfig = Struct.new(:base_domain, :live_prefix, :action_name)
5
+
6
+ CONFIGS = {
7
+ ahtus: IpumsConfig.new('ahtusdata.org', 'www.'),
8
+ atus: IpumsConfig.new('atusdata.org', 'www.'),
9
+ cps: IpumsConfig.new('cps.ipums.org'),
10
+ dhs: IpumsConfig.new('idhsdata.org', 'www.', 'idhs'),
11
+ highered: IpumsConfig.new('highered.ipums.org'),
12
+ nhis: IpumsConfig.new('nhis.ipums.org'),
13
+ ipumsi: IpumsConfig.new('international.ipums.org', nil, 'international'),
14
+ mtus: IpumsConfig.new('mtusdata.org', 'www.'),
15
+ napp: IpumsConfig.new('nappdata.org', 'www.'),
16
+ usa: IpumsConfig.new('usa.ipums.org'),
17
+ }
18
+
19
+ attr_reader :project, :environment, :config
20
+
21
+ def initialize(project, environment)
22
+ @project = project.to_sym
23
+ @environment = environment.to_sym
24
+ @config = CONFIGS[@project]
25
+ end
26
+
27
+ def protocol
28
+ environment == :local ? 'http' : 'https'
29
+ end
30
+
31
+ def domain
32
+ case environment
33
+ when :local
34
+ 'localhost:3003'
35
+ when :live
36
+ config.live_prefix.to_s + config.base_domain
37
+ else
38
+ environment.to_s + '.' + config.base_domain
39
+ end
40
+ end
41
+
42
+ def path
43
+ (config.action_name || project).to_s + '-action'
44
+ end
45
+
46
+ def url
47
+ "#{protocol}://#{domain}/#{path}"
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+
2
+ if RUBY_VERSION.start_with?('1.9')
3
+
4
+ # Previous to 2.0 ruby doesn't define the index methods on OpenStruct. These are used in the IpumsClient when parsing
5
+ # json into OpenStruct objects.
6
+ class OpenStruct
7
+ def [](key)
8
+ self.send(key.to_sym)
9
+ end
10
+
11
+ def []=(key, value)
12
+ self.send("#{key}=".to_sym, value)
13
+ end
14
+ end
15
+
16
+ # 1.9 doesn't implement the 422 http code
17
+ module Net
18
+ class HTTPUnprocessableEntity < HTTPClientError
19
+ HAS_BODY = true
20
+ end
21
+
22
+ HTTPResponse::CODE_TO_OBJ['422'] = HTTPUnprocessableEntity
23
+ end
24
+
25
+ end
@@ -0,0 +1,132 @@
1
+ module DoiExtractor
2
+ class Options
3
+
4
+ PROJECTS = %w(ahtus atus cps dhs highered nhis ipumsi mtus napp usa)
5
+ ENVIRONMENTS = %w(local demo internal staging live)
6
+ COMMANDS = %w(create download status cancel)
7
+
8
+ OPTIONS = [
9
+ :command,
10
+ :verbose,
11
+ :environment,
12
+ :project,
13
+ :api_uri,
14
+ :api_username,
15
+ :api_password,
16
+ :download_base_path,
17
+ :doi_version,
18
+ :year,
19
+ :email,
20
+ :force,
21
+ :extract_group_id
22
+ ]
23
+
24
+ def self.for_command(cmd, attrs = nil)
25
+ if COMMANDS.include? cmd
26
+ new({command: cmd}.merge(attrs || {}))
27
+ else
28
+ raise 'Invalid Command'
29
+ end
30
+ end
31
+
32
+ attr_reader :errors
33
+ attr_accessor *OPTIONS
34
+
35
+ def initialize(attrs = nil)
36
+ assign_attrs(attrs, OPTIONS)
37
+ end
38
+
39
+ def validate
40
+ @errors = []
41
+
42
+ if environment.nil?
43
+ self.environment = 'live'
44
+ end
45
+
46
+ if !COMMANDS.include?(command)
47
+ errors << 'Invalid Command'
48
+ end
49
+
50
+ if !ENVIRONMENTS.include?(environment)
51
+ errors << 'Invalid Environment'
52
+ end
53
+
54
+ if !PROJECTS.include?(project)
55
+ errors << 'Invalid Project'
56
+ end
57
+
58
+ # if command, env or project are invalid, stop performing further validation
59
+ return if errors.any?
60
+
61
+ self.api_uri = calculate_api_uri if api_uri.nil?
62
+ errors << 'Missing API URI' if self.api_uri.nil?
63
+
64
+ # For demo, internal, and staging envs, use the basic auth creds by default
65
+ if %w(demo internal staging).include?(environment)
66
+ self.api_username ||= 'hcp'
67
+ self.api_password ||= '1234'
68
+ end
69
+
70
+ if command == 'create'
71
+ self.year ||= Time.now.year.to_s
72
+
73
+ if self.year !~ /^\d{4}$/
74
+ errors << 'Year must be a 4 digit year'
75
+ end
76
+
77
+ if m = /[vV]?(\d+\.\d+)/.match(self.doi_version)
78
+ self.doi_version = m[1]
79
+ else
80
+ errors << 'DOI version is required and must match the pattern VX.X'
81
+ end
82
+ end
83
+
84
+ if %w(download status).include?(command)
85
+ self.download_base_path ||= calculate_download_base_path
86
+
87
+ if self.download_base_path.nil? || self.download_base_path.strip.empty?
88
+ errors << 'Unable to determine download base path'
89
+ end
90
+ end
91
+
92
+ if %w(download cancel).include?(command)
93
+ unless self.extract_group_id
94
+ errors << 'Missing extract request group id'
95
+ end
96
+ end
97
+ end
98
+
99
+ def valid?
100
+ validate
101
+ errors.empty?
102
+ end
103
+
104
+ private
105
+
106
+ def calculate_api_uri
107
+ if project && environment
108
+ IpumsUriBuilder.new(project, environment).url
109
+ else
110
+ nil
111
+ end
112
+ end
113
+
114
+ def calculate_download_base_path
115
+ if project && environment
116
+ # "/pkg/ipums/programming/#{project}/#{environment}"
117
+ "/pkg/ipums/programming/doi_extractor/temp_archive/#{project}/#{environment}"
118
+ else
119
+ nil
120
+ end
121
+ end
122
+
123
+ def assign_attrs(attrs, known_keys)
124
+ if attrs
125
+ known_keys.each do |k|
126
+ self.send("#{k}=", attrs[k]) if attrs[k]
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
@@ -0,0 +1,18 @@
1
+ module DoiExtractor
2
+ class Secrets
3
+ DEFAULT_API_PATH = '/pkg/mpctools/secrets/api_creds.yml'
4
+ DEFAULT_API_USERNAME = 'terrapop' # 'doi_extractor'
5
+
6
+ attr_reader :api_path, :api_username, :api_password
7
+
8
+ def initialize(overrides = {})
9
+ @api_path = overrides[:api_path] || DEFAULT_API_PATH
10
+ @api_username = overrides[:api_username] || DEFAULT_API_USERNAME
11
+ @api_password = overrides[:api_password] || read_yaml(@api_path)[@api_username]
12
+ end
13
+
14
+ def read_yaml(path)
15
+ YAML.load(ERB.new(IO.read(path)).result)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,62 @@
1
+ module DoiExtractor
2
+ class StatusCommand < Command
3
+
4
+ def _execute
5
+ if options.extract_group_id
6
+ report_group(options.extract_group_id)
7
+ else
8
+ report_recent
9
+ end
10
+ end
11
+
12
+ def report_group(id)
13
+ doi_extract = ipums_client.get_doi_extract(id)
14
+
15
+ unless doi_extract
16
+ fail("no extract for #{id} found")
17
+ end
18
+
19
+ location = DownloadLocation.new(options.download_base_path, doi_extract)
20
+
21
+ say_doi_summary(doi_extract, location)
22
+ say("Extract Requests:")
23
+
24
+ fmt = '%-10s%25s%20s%12s'
25
+
26
+ say(sprintf(fmt.sub('i', 's'), 'ID', 'Status', 'Sample', 'Downloaded'))
27
+ doi_extract.extract_requests.each do |er|
28
+ say(sprintf(fmt, er.id, er.completion_status, er.samples.first.name, location.complete_extract_request?(er)))
29
+ end
30
+
31
+ end
32
+
33
+ def report_recent
34
+ recent = ipums_client.recent_doi_extracts
35
+
36
+ if recent.nil? || recent.empty?
37
+ say("There are no DOI extracts")
38
+ else
39
+ recent.each do |doi|
40
+ location = DownloadLocation.new(options.download_base_path, doi)
41
+ say_doi_summary(doi, location)
42
+ say("\tExtracts: #{doi.extract_requests.count}")
43
+ end
44
+ end
45
+ end
46
+
47
+ def say_doi_summary(doi_extract, location)
48
+ count_hsh = Hash.new { |h, k| h[k] = 0 }
49
+ extract_counts = doi_extract.extract_requests.reduce(count_hsh) { |h, e| h[e.completion_status] += 1; h }
50
+
51
+ say("DOI Extract (ID: #{doi_extract.id})")
52
+ say("\tStatus: #{doi_extract.status}")
53
+ say("\tSubmitted: #{doi_extract.submit_date}")
54
+ say("\tFinished: #{doi_extract.finish_date}")
55
+ say("\tData Available: #{doi_extract.all_data_available}")
56
+ say("\tPath: #{location.path}")
57
+ say("\tExtract Counts: #{extract_counts.map { |k, v| "#{k}: #{v}" }.join(', ')}")
58
+ say("\tDownloaded: #{doi_extract.extract_requests.any? && doi_extract.extract_requests.all? { |er| location.complete_extract_request?(er) }}")
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,3 @@
1
+ module DoiExtractor
2
+ VERSION = '1.0.5'
3
+ end
@@ -0,0 +1,2 @@
1
+ terrapop: testPassword
2
+ doi_extractor: testPassword
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CancelCommand when successful" tests="2" time="0.01088" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:52-05:00">
3
+ <testcase name="DoiExtractor::CancelCommand when successful makes two API calls" time="0.005551">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CancelCommand when successful writes to sdtout" time="0.004845">
6
+ </testcase>
7
+ </testsuite>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CancelCommand" tests="0" time="0.000107" skipped="0" timestamp="2017-09-12T12:47:52-05:00">
3
+ </testsuite>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with a valid create command with email" tests="4" time="0.009902" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command with email should be valid" time="0.002419">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command with email should contain options" time="0.002116">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command with email should set options attributes" time="0.002968">
8
+ </testcase>
9
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command with email should set the email option" time="0.00192">
10
+ </testcase>
11
+ <system-out>
12
+ #&lt;DoiExtractor::Options:0x007ff44e85cdd0 @command="create", @environment="live", @project="cps", @errors=[], @api_uri="https://cps.ipums.org/cps-action", @doi_version="1.2", @year="2017", @email="roland@tet.com"&gt;
13
+ </system-out>
14
+ </testsuite>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with a valid create command" tests="3" time="0.010797" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:52-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command should be valid" time="0.003975">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command should contain options" time="0.003727">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::CommandLineParser with a valid create command should set options attributes" time="0.002684">
8
+ </testcase>
9
+ </testsuite>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with a valid download command" tests="3" time="0.007531" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with a valid download command should be valid" time="0.00285">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CommandLineParser with a valid download command should contain options" time="0.00228">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::CommandLineParser with a valid download command should set options attributes" time="0.001983">
8
+ </testcase>
9
+ </testsuite>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with a valid status command" tests="3" time="0.007673" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with a valid status command should be valid" time="0.001887">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CommandLineParser with a valid status command should contain options" time="0.001957">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::CommandLineParser with a valid status command should set options attributes" time="0.00351">
8
+ </testcase>
9
+ </testsuite>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with an invalid command" tests="3" time="0.013999" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with an invalid command should not be valid" time="0.003411">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CommandLineParser with an invalid command should have a reasonable error message" time="0.003179">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::CommandLineParser with an invalid command should not have any options" time="0.006824">
8
+ </testcase>
9
+ </testsuite>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser with an unknown option" tests="1" time="0.005251" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CommandLineParser with an unknown option should not be valid" time="0.00477">
4
+ </testcase>
5
+ </testsuite>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CommandLineParser" tests="0" time="6.8e-05" skipped="0" timestamp="2017-09-12T12:47:52-05:00">
3
+ </testsuite>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CreateCommand when an existing extract is processing" tests="2" time="0.005917" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CreateCommand when an existing extract is processing makes 1 API call" time="0.002311">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CreateCommand when an existing extract is processing raises a CommandFailError" time="0.003323">
6
+ </testcase>
7
+ </testsuite>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CreateCommand when successful" tests="2" time="0.01331" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::CreateCommand when successful makes 2 API calls" time="0.008916">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::CreateCommand when successful writes to sdtout" time="0.004134">
6
+ </testcase>
7
+ </testsuite>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::CreateCommand" tests="0" time="8.4e-05" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ </testsuite>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::DownloadCommand user cancels download" tests="2" time="0.008309" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::DownloadCommand user cancels download asks for input" time="0.005059">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::DownloadCommand user cancels download does not create the output path" time="0.002841">
6
+ </testcase>
7
+ </testsuite>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::DownloadCommand when an extract is available when force is not set" tests="1" time="0.060445" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available when force is not set asks for user input" time="0.060068">
4
+ </testcase>
5
+ </testsuite>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="DoiExtractor::DownloadCommand when an extract is available" tests="5" time="0.338937" failures="0" errors="0" skipped="0" timestamp="2017-09-12T12:47:53-05:00">
3
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available executes all requests" time="0.081153">
4
+ </testcase>
5
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available packages everything" time="0.069818">
6
+ </testcase>
7
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available adds the citation to the summary file" time="0.064809">
8
+ </testcase>
9
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available cleans up the tmp folder" time="0.060621">
10
+ </testcase>
11
+ <testcase name="DoiExtractor::DownloadCommand when an extract is available does not prompt the user when forced it true" time="0.061706">
12
+ </testcase>
13
+ </testsuite>