psdi-data-conversion 0.0.37__py3-none-any.whl → 0.0.38__py3-none-any.whl

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.
@@ -4,12 +4,12 @@
4
4
  Utilities to aid in testing of the GUI
5
5
  """
6
6
 
7
-
8
7
  import os
9
8
  import shutil
10
9
  from tempfile import TemporaryDirectory
11
10
 
12
11
  import time
12
+ from dataclasses import dataclass
13
13
  import pytest
14
14
  from selenium.common.exceptions import TimeoutException
15
15
  from selenium.webdriver.common.alert import Alert
@@ -24,7 +24,9 @@ from psdi_data_conversion.converters.base import (FileConverterAbortException, F
24
24
  FileConverterInputException)
25
25
  from psdi_data_conversion.converters.openbabel import (COORD_GEN_KEY, COORD_GEN_QUAL_KEY, DEFAULT_COORD_GEN_QUAL,
26
26
  L_ALLOWED_COORD_GEN_QUALS, L_ALLOWED_COORD_GENS)
27
+ from psdi_data_conversion.database import get_format_info
27
28
  from psdi_data_conversion.file_io import split_archive_ext
29
+ from psdi_data_conversion.testing.constants import DEFAULT_ORIGIN
28
30
  from psdi_data_conversion.testing.utils import (ConversionTestInfo, ConversionTestSpec, SingleConversionTestSpec,
29
31
  get_input_test_data_loc)
30
32
 
@@ -43,324 +45,384 @@ def wait_and_find_element(root: WebDriver | EC.WebElement, xpath: str, by=By.XPA
43
45
  return root.find_element(by, xpath)
44
46
 
45
47
 
46
- def run_test_conversion_with_gui(test_spec: ConversionTestSpec,
47
- driver: WebDriver,
48
- origin: str):
49
- """Runs a test conversion or series thereof through the GUI. Note that this requires the server to be started before
50
- this is called.
51
-
52
- Parameters
53
- ----------
54
- test_spec : ConversionTestSpec
55
- The specification for the test or series of tests to be run
56
- driver : WebDriver
57
- The WebDriver to be used for testing
58
- origin : str
59
- The address of the homepage of the testing server
60
- """
61
- # Make temporary directories for the input and output files to be stored in
62
- with TemporaryDirectory("_input") as input_dir, TemporaryDirectory("_output") as output_dir:
63
- # Iterate over the test spec to run each individual test it defines
64
- for single_test_spec in test_spec:
65
- if single_test_spec.skip:
66
- print(f"Skipping single test spec {single_test_spec}")
67
- continue
68
- print(f"Running single test spec: {single_test_spec}")
69
- _run_single_test_conversion_with_gui(test_spec=single_test_spec,
70
- input_dir=input_dir,
71
- output_dir=output_dir,
72
- driver=driver,
73
- origin=origin)
74
- print(f"Success for test spec: {single_test_spec}")
75
-
76
-
77
- def _run_single_test_conversion_with_gui(test_spec: SingleConversionTestSpec,
78
- input_dir: str,
79
- output_dir: str,
80
- driver: WebDriver,
81
- origin: str):
82
- """Runs a single test conversion through the GUI.
83
-
84
- Parameters
85
- ----------
86
- test_spec : SingleConversionTestSpec
87
- The specification for the test to be run
88
- input_dir : str
89
- A directory which can be used to store input data before uploading
90
- output_dir : str
91
- A directory which can be used to create output data after downloading
92
- driver : WebDriver
93
- The WebDriver to be used for testing
94
- origin : str
95
- The address of the homepage of the testing server
48
+ @dataclass
49
+ class GuiTestSpecRunner():
50
+ """Class which provides an interface to run test conversions through the GUI
96
51
  """
97
52
 
98
- exc_info: pytest.ExceptionInfo | None = None
99
- if test_spec.expect_success:
100
- try:
101
- run_converter_through_gui(test_spec=test_spec,
102
- input_dir=input_dir,
103
- output_dir=output_dir,
104
- driver=driver,
105
- origin=origin,
106
- **test_spec.conversion_kwargs)
107
- success = True
108
- except Exception:
109
- print(f"Unexpected exception raised for single test spec {test_spec}")
110
- raise
111
- else:
112
- with pytest.raises(FileConverterException) as exc_info:
113
- run_converter_through_gui(test_spec=test_spec,
114
- input_dir=input_dir,
115
- output_dir=output_dir,
116
- driver=driver,
117
- origin=origin,
118
- **test_spec.conversion_kwargs)
119
- success = False
120
-
121
- # Compile output info for the test and call the callback function if one is provided
122
- if test_spec.callback:
123
- test_info = ConversionTestInfo(run_type="gui",
124
- test_spec=test_spec,
125
- input_dir=input_dir,
126
- output_dir=output_dir,
127
- success=success,
128
- exc_info=exc_info)
129
- callback_msg = test_spec.callback(test_info)
130
- assert not callback_msg, callback_msg
131
-
132
-
133
- def run_converter_through_gui(test_spec: SingleConversionTestSpec,
134
- input_dir: str,
135
- output_dir: str,
136
- driver: WebDriver,
137
- origin: str,
138
- **conversion_kwargs):
139
- """_summary_
140
-
141
- Parameters
142
- ----------
143
- test_spec : SingleConversionTestSpec
144
- The specification for the test to be run
145
- input_dir : str
146
- The directory which contains the input file
147
- output_dir : str
148
- The directory which contains the output file
149
- driver : WebDriver
150
- The WebDriver to be used for testing
151
- origin : str
152
- The address of the homepage of the testing server
153
- """
53
+ driver: WebDriver
54
+ """The WebDriver to be used for testing"""
154
55
 
155
- # Get just the local filename
156
- filename = os.path.split(test_spec.filename)[1]
157
-
158
- # Default options for conversion
159
- base_filename, from_format = split_archive_ext(filename)
160
- strict = True
161
- from_flags: str | None = None
162
- to_flags: str | None = None
163
- from_options: str | None = None
164
- to_options: str | None = None
165
- coord_gen = None
166
- coord_gen_qual = None
167
-
168
- # For each argument in the conversion kwargs, interpret it as the appropriate option for this conversion, overriding
169
- # defaults set above
170
- for key, val in conversion_kwargs.items():
171
- if key == "from_format":
172
- from_format = val
173
- elif key == "log_mode":
174
- raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
175
- elif key == "delete_input":
176
- raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
177
- elif key == "strict":
178
- strict = val
179
- elif key == "max_file_size":
180
- raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
181
- elif key == "data":
182
- for subkey, subval in val.items():
183
- if subkey == "from_flags":
184
- from_flags = subval
185
- elif subkey == "to_flags":
186
- to_flags = subval
187
- elif subkey == "from_options":
188
- from_options = subval
189
- elif subkey == "to_options":
190
- to_options = subval
191
- elif subkey == COORD_GEN_KEY:
192
- coord_gen = subval
193
- if COORD_GEN_QUAL_KEY in val:
194
- coord_gen_qual = val[COORD_GEN_QUAL_KEY]
195
- else:
196
- coord_gen_qual = DEFAULT_COORD_GEN_QUAL
197
- elif subkey == COORD_GEN_QUAL_KEY:
198
- # Handled alongside COORD_GEN_KEY above
199
- pass
200
- else:
201
- pytest.fail(f"The key 'data[\"{subkey}\"]' was passed to `conversion_kwargs` but could not be "
202
- "interpreted")
203
- else:
204
- pytest.fail(f"The key '{key}' was passed to `conversion_kwargs` but could not be interpreted")
56
+ origin: str = DEFAULT_ORIGIN
57
+ """The address of the homepage of the testing server"""
205
58
 
206
- # Cleanup of arguments
207
- if from_format.startswith("."):
208
- from_format = from_format[1:]
59
+ def run(self, test_spec: ConversionTestSpec):
60
+ """Run the test conversions outlined in a test spec"""
209
61
 
210
- # Set up the input file where we expect it to be
211
- source_input_file = os.path.realpath(os.path.join(get_input_test_data_loc(), test_spec.filename))
212
- input_file = os.path.join(input_dir, test_spec.filename)
213
- if (os.path.isfile(input_file)):
214
- os.unlink(input_file)
215
- os.symlink(source_input_file, input_file)
62
+ self._test_spec = test_spec
216
63
 
217
- # Remove test files from Downloads directory if they exist.
64
+ # Make temporary directories for the input and output files to be stored in
65
+ with TemporaryDirectory("_input") as input_dir, TemporaryDirectory("_output") as output_dir:
218
66
 
219
- log_file = os.path.realpath(os.path.join(os.path.expanduser("~/Downloads"), test_spec.log_filename))
220
- if (os.path.isfile(log_file)):
221
- os.remove(log_file)
67
+ # Iterate over the test spec to run each individual test it defines
68
+ for single_test_spec in test_spec:
69
+ if single_test_spec.skip:
70
+ print(f"Skipping single test spec {single_test_spec}")
71
+ continue
222
72
 
223
- output_file = os.path.realpath(os.path.join(os.path.expanduser("~/Downloads"), test_spec.out_filename))
224
- if (os.path.isfile(output_file)):
225
- os.remove(output_file)
73
+ print(f"Running single test spec: {single_test_spec}")
226
74
 
227
- # Get the homepage
228
- driver.get(f"{origin}/")
75
+ GuiSingleTestSpecRunner(parent=self,
76
+ input_dir=input_dir,
77
+ output_dir=output_dir,
78
+ single_test_spec=single_test_spec).run()
229
79
 
230
- wait_for_element(driver, "//select[@id='fromList']/option")
80
+ print(f"Success for test spec: {single_test_spec}")
231
81
 
232
- # Select from_format from the 'from' list.
233
- driver.find_element(By.XPATH, f"//select[@id='fromList']/option[starts-with(.,'{from_format}:')]").click()
234
82
 
235
- # Select to_format from the 'to' list.
236
- driver.find_element(By.XPATH, f"//select[@id='toList']/option[starts-with(.,'{test_spec.to_format}:')]").click()
83
+ class GuiSingleTestSpecRunner:
84
+ """Class which handles running an individual test conversion
85
+ """
237
86
 
238
- # Select converter from the available conversion options list.
239
- driver.find_element(By.XPATH, f"//select[@id='success']/option[contains(.,'{test_spec.converter_name}')]").click()
87
+ def __init__(self,
88
+ parent: GuiTestSpecRunner,
89
+ input_dir: str,
90
+ output_dir: str,
91
+ single_test_spec: SingleConversionTestSpec):
92
+ """
93
+
94
+ Parameters
95
+ ----------
96
+ parent : GuiTestSpecRunner
97
+ The GuiTestSpecRunner which created this and is running it
98
+ input_dir : str
99
+ The temporary directory to be used for input data
100
+ output_dir : str
101
+ The temporary directory to be used for output data
102
+ single_test_spec : SingleConversionTestSpec
103
+ The test spec that is currently being tested
104
+ """
105
+
106
+ self.input_dir: str = input_dir
107
+ self.output_dir: str = output_dir
108
+ self.single_test_spec: SingleConversionTestSpec = single_test_spec
109
+
110
+ # Inherit data from the parent class
111
+
112
+ self.driver: WebDriver = parent.driver
113
+ """The WebDriver to be used for testing"""
114
+
115
+ self.origin: str = parent.origin
116
+ """The address of the homepage of the testing server"""
117
+
118
+ # Interpret information from the test spec that we'll need for testing
119
+
120
+ # Get just the local filename
121
+ self._filename = os.path.split(self.single_test_spec.filename)[1]
122
+
123
+ # Default options for conversion
124
+ self._base_filename, ext = split_archive_ext(self._filename)
125
+ self._strict = True
126
+ self._from_flags: str | None = None
127
+ self._to_flags: str | None = None
128
+ self._from_options: str | None = None
129
+ self._to_options: str | None = None
130
+ self._coord_gen = None
131
+ self._coord_gen_qual = None
132
+
133
+ # Get the from_format from the extension if not provided
134
+ from_format = single_test_spec.from_format
135
+ if not from_format:
136
+ from_format = ext
137
+
138
+ # Get the format info for each format, which we'll use to get the name and note of each
139
+ self._from_format_info = get_format_info(from_format, which=0)
140
+ self._to_format_info = get_format_info(single_test_spec.to_format, which=0)
141
+
142
+ # For each argument in the conversion kwargs, interpret it as the appropriate option for this conversion,
143
+ # overriding defaults set above
144
+ for key, val in self.single_test_spec.conversion_kwargs.items():
145
+ if key == "log_mode":
146
+ raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
147
+ elif key == "delete_input":
148
+ raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
149
+ elif key == "strict":
150
+ self._strict = val
151
+ elif key == "max_file_size":
152
+ raise ValueError(f"The conversion kwarg {key} is not valid with conversions through the GUI")
153
+ elif key == "data":
154
+ for subkey, subval in val.items():
155
+ if subkey == "from_flags":
156
+ self._from_flags = subval
157
+ elif subkey == "to_flags":
158
+ self._to_flags = subval
159
+ elif subkey == "from_options":
160
+ self._from_options = subval
161
+ elif subkey == "to_options":
162
+ self._to_options = subval
163
+ elif subkey == COORD_GEN_KEY:
164
+ self._coord_gen = subval
165
+ if COORD_GEN_QUAL_KEY in val:
166
+ self._coord_gen_qual = val[COORD_GEN_QUAL_KEY]
167
+ else:
168
+ self._coord_gen_qual = DEFAULT_COORD_GEN_QUAL
169
+ elif subkey == COORD_GEN_QUAL_KEY:
170
+ # Handled alongside COORD_GEN_KEY above
171
+ pass
172
+ else:
173
+ pytest.fail(f"The key 'data[\"{subkey}\"]' was passed to `conversion_kwargs` but could not be "
174
+ "interpreted")
175
+ else:
176
+ pytest.fail(f"The key '{key}' was passed to `conversion_kwargs` but could not be interpreted")
177
+
178
+ def run(self):
179
+ """Run the conversion outlined in the test spec"""
180
+
181
+ exc_info: pytest.ExceptionInfo | None = None
182
+ if self.single_test_spec.expect_success:
183
+ try:
184
+ self._run_conversion()
185
+ success = False
186
+ except Exception:
187
+ print(f"Unexpected exception raised for single test spec {self.single_test_spec}")
188
+ raise
189
+ else:
190
+ with pytest.raises(FileConverterException) as exc_info:
191
+ self._run_conversion()
192
+ success = False
193
+
194
+ # Compile output info for the test and call the callback function if one is provided
195
+ if self.single_test_spec.callback:
196
+ test_info = ConversionTestInfo(run_type="gui",
197
+ test_spec=self.single_test_spec,
198
+ input_dir=self.input_dir,
199
+ output_dir=self.output_dir,
200
+ success=success,
201
+ exc_info=exc_info)
202
+ callback_msg = self.single_test_spec.callback(test_info)
203
+ if callback_msg:
204
+ pytest.fail(callback_msg)
205
+
206
+ def _run_conversion(self):
207
+ """Run a conversion through the GUI
208
+ """
209
+
210
+ self._set_up_files()
211
+
212
+ self._select_formats_and_converter()
213
+
214
+ self._set_conversion_settings()
215
+
216
+ self._provide_input_file()
217
+
218
+ self._request_conversion()
219
+
220
+ self._move_output()
221
+
222
+ def _set_up_files(self):
223
+ """Set up the filenames we expect and initialize them - delete any leftover files and symlink the input file
224
+ to the desired location
225
+ """
226
+ # Set up the expected filenames
227
+ source_input_file = os.path.realpath(os.path.join(get_input_test_data_loc(), self.single_test_spec.filename))
228
+ self._input_file = os.path.join(self.input_dir, self.single_test_spec.filename)
229
+
230
+ self._log_file = os.path.realpath(os.path.join(os.path.expanduser("~/Downloads"),
231
+ self.single_test_spec.log_filename))
232
+
233
+ self._output_file = os.path.realpath(os.path.join(os.path.expanduser("~/Downloads"),
234
+ self.single_test_spec.out_filename))
235
+
236
+ # Clean up any leftover files
237
+ if (os.path.isfile(self._input_file)):
238
+ os.unlink(self._input_file)
239
+ if (os.path.isfile(self._log_file)):
240
+ os.remove(self._log_file)
241
+ if (os.path.isfile(self._output_file)):
242
+ os.remove(self._output_file)
243
+
244
+ # Symlink the input file to the desired location
245
+ os.symlink(source_input_file, self._input_file)
246
+
247
+ def _select_formats_and_converter(self):
248
+ """Handle the tasks on the format and converter selection page when running a test:
249
+
250
+ 1. Load the main page (waiting for it to fully load)
251
+ 2. Select the input and output formats
252
+ 3. Select the converter
253
+ 4. Click the "Yes" button to confirm and go to the convert page
254
+ """
255
+
256
+ # Get the homepage
257
+ self.driver.get(f"{self.origin}/")
258
+
259
+ wait_for_element(self.driver, "//select[@id='fromList']/option")
260
+
261
+ # Select from_format from the 'from' list.
262
+ self.driver.find_element(
263
+ By.XPATH, f"//select[@id='fromList']/option[starts-with(.,'{self._from_format_info.name}:')]").click()
264
+
265
+ # Select to_format from the 'to' list.
266
+ self.driver.find_element(
267
+ By.XPATH, f"//select[@id='toList']/option[starts-with(.,'{self._to_format_info.name}:')]").click()
268
+
269
+ # Select converter from the available conversion options list.
270
+ self.driver.find_element(
271
+ By.XPATH, f"//select[@id='success']/option[contains(.,'{self.single_test_spec.converter_name}')]").click()
272
+
273
+ # Click on the "Yes" button to accept the converter and go to the conversion page
274
+ self.driver.find_element(By.XPATH, "//input[@id='yesButton']").click()
275
+
276
+ def _set_conversion_settings(self):
277
+ """Set settings on the convert page appropriately for the desired conversion
278
+ """
279
+ # Request non-strict filename checking if desired
280
+ if not self._strict:
281
+ wait_and_find_element(self.driver, "//input[@id='extCheck']").click()
282
+
283
+ # Request the log file
284
+ wait_and_find_element(self.driver, "//input[@id='requestLog']").click()
285
+
286
+ # Set appropriate format and converter settings for this conversion
287
+ self._select_format_flags()
288
+ self._set_format_options()
289
+ self._apply_radio_settings()
290
+
291
+ def _provide_input_file(self):
292
+ """Provide the input file for the conversion, checking if any alert is raised in response
293
+ """
294
+ # Select the input file
295
+ wait_and_find_element(self.driver, "//input[@id='fileToUpload']").send_keys(str(self._input_file))
240
296
 
241
- # Click on the "Yes" button to accept the converter and go to the conversion page
242
- driver.find_element(By.XPATH, "//input[@id='yesButton']").click()
297
+ # An alert may be present here, which we check for using a try block
298
+ try:
299
+ WebDriverWait(self.driver, 0.2).until(EC.alert_is_present())
300
+ alert = Alert(self.driver)
301
+ alert_text = alert.text
302
+ alert.dismiss()
303
+ raise FileConverterInputException(alert_text)
304
+ except TimeoutException:
305
+ pass
306
+
307
+ def _select_format_flags(self):
308
+ """Select desired format flags. The options in the select box only have a text attribute, so we need to find
309
+ the one that starts with each flag - since we don't have too many, iterating over all possible combinations is
310
+ the easiest way
311
+ """
312
+ for (l_flags, select_id) in ((self._from_flags, "inFlags"),
313
+ (self._to_flags, "outFlags")):
314
+ if not l_flags:
315
+ continue
316
+ flags_select = Select(wait_and_find_element(self.driver, f"//select[@id='{select_id}']"))
317
+ for flag in l_flags:
318
+ found = False
319
+ for option in flags_select.options:
320
+ if option.text.startswith(f"{flag}:"):
321
+ flags_select.select_by_visible_text(option.text)
322
+ found = True
323
+ break
324
+ if not found:
325
+ raise ValueError(f"Flag {flag} was not found in {select_id} selection box for conversion from "
326
+ f"{self._from_format_info.name} to {self._to_format_info.name} with "
327
+ f"converter {self.single_test_spec.converter_name}")
328
+
329
+ def _set_format_options(self):
330
+ """Set desired format options
331
+ """
332
+ for (options_string, table_id) in ((self._from_options, "in_argFlags"),
333
+ (self._to_options, "out_argFlags")):
334
+ if not options_string:
335
+ continue
243
336
 
244
- # Request non-strict filename checking if desired
245
- if not strict:
246
- wait_and_find_element(driver, "//input[@id='extCheck']").click()
337
+ # Split each option into words, of which the first letter of each is the key and the remainder is the value
338
+ l_options = options_string.split()
247
339
 
248
- # Select the input file
249
- wait_and_find_element(driver, "//input[@id='fileToUpload']").send_keys(str(input_file))
340
+ # Get the rows in the options table
341
+ options_table = wait_and_find_element(self.driver, f"//table[@id='{table_id}']")
342
+ l_rows = options_table.find_elements(By.XPATH, "./tr")
343
+
344
+ # Look for and set each option
345
+ for option in l_options:
346
+ found = False
347
+ for row in l_rows:
348
+ l_items = row.find_elements(By.XPATH, "./td")
349
+ label = l_items[1]
350
+ if not label.text.startswith(option[0]):
351
+ continue
352
+
353
+ # Select the option by clicking the box at the first element in the row to make the input appear
354
+ l_items[0].click()
355
+
356
+ # Input the option in the input box that appears in the third position in the row
357
+ input_box = wait_and_find_element(l_items[2], "./input")
358
+ input_box.send_keys(option[1:])
250
359
 
251
- # An alert may be present here, which we check for using a try block
252
- try:
253
- WebDriverWait(driver, 0.2).until(EC.alert_is_present())
254
- alert = Alert(driver)
255
- alert_text = alert.text
256
- alert.dismiss()
257
- raise FileConverterInputException(alert_text)
258
- except TimeoutException:
259
- pass
260
-
261
- # Request the log file
262
- wait_and_find_element(driver, "//input[@id='requestLog']").click()
263
-
264
- # Select appropriate format args. The args only have a text attribute, so we need to find the one that starts with
265
- # each flag - since we don't have too many, iterating over all possible combinations is the easiest way
266
- for (l_flags, select_id) in ((from_flags, "inFlags"),
267
- (to_flags, "outFlags")):
268
- if not l_flags:
269
- continue
270
- flags_select = Select(wait_and_find_element(driver, f"//select[@id='{select_id}']"))
271
- for flag in l_flags:
272
- found = False
273
- for option in flags_select.options:
274
- if option.text.startswith(f"{flag}:"):
275
- flags_select.select_by_visible_text(option.text)
276
360
  found = True
277
361
  break
278
- if not found:
279
- raise ValueError(f"Flag {flag} was not found in {select_id} selection box for conversion from "
280
- f"{from_format} to {test_spec.to_format} with converter {test_spec.converter_name}")
281
-
282
- for (options_string, table_id) in ((from_options, "in_argFlags"),
283
- (to_options, "out_argFlags")):
284
- if not options_string:
285
- continue
286
-
287
- # Split each option into words, of which the first letter of each is the key and the remainder is the value
288
- l_options = options_string.split()
289
-
290
- # Get the rows in the options table
291
- options_table = wait_and_find_element(driver, f"//table[@id='{table_id}']")
292
- l_rows = options_table.find_elements(By.XPATH, "./tr")
293
-
294
- # Look for and set each option
295
- for option in l_options:
296
- found = False
297
- for row in l_rows:
298
- l_items = row.find_elements(By.XPATH, "./td")
299
- label = l_items[1]
300
- if not label.text.startswith(option[0]):
301
- continue
302
-
303
- # Select the option by clicking the box at the first element in the row to make the input appear
304
- l_items[0].click()
305
362
 
306
- # Input the option in the input box that appears in the third position in the row
307
- input_box = wait_and_find_element(l_items[2], "./input")
308
- input_box.send_keys(option[1:])
363
+ if not found:
364
+ raise ValueError(f"Option {option} was not found in {table_id} options table for conversion from "
365
+ f"{self._from_format_info.name} to {self._to_format_info.name} with "
366
+ f"converter {self.single_test_spec.converter_name}")
309
367
 
310
- found = True
311
- break
368
+ def _apply_radio_settings(self):
369
+ """Apply any radio-button settings desired for this conversion by clicking the appropriate radio buttons
370
+ """
312
371
 
313
- if not found:
314
- raise ValueError(f"Option {option} was not found in {table_id} options table for conversion from "
315
- f"{from_format} to {test_spec.to_format} with converter {test_spec.converter_name}")
372
+ for setting, name, l_allowed in ((self._coord_gen, "coord_gen", L_ALLOWED_COORD_GENS),
373
+ (self._coord_gen_qual, "coord_gen_qual", L_ALLOWED_COORD_GEN_QUALS)):
374
+ if not setting:
375
+ continue
316
376
 
317
- # If radio-button settings are supplied, apply them now
318
- for setting, name, l_allowed in ((coord_gen, "coord_gen", L_ALLOWED_COORD_GENS),
319
- (coord_gen_qual, "coord_gen_qual", L_ALLOWED_COORD_GEN_QUALS)):
320
- if not setting:
321
- continue
377
+ if setting not in l_allowed:
378
+ raise ValueError(f"Invalid {name} value supplied: {setting}. Allowed values are: " +
379
+ str(l_allowed))
322
380
 
323
- if setting not in l_allowed:
324
- raise ValueError(f"Invalid {name} value supplied: {setting}. Allowed values are: " +
325
- str(l_allowed))
381
+ setting_radio = wait_and_find_element(self.driver, f"//input[@value='{setting}']")
382
+ setting_radio.click()
326
383
 
327
- setting_radio = wait_and_find_element(driver, f"//input[@value='{setting}']")
328
- setting_radio.click()
384
+ def _request_conversion(self):
385
+ """Request the conversion, handle the alert box that appears, and wait for the files to be downloaded
386
+ """
387
+ # Click on the "Convert" button.
388
+ wait_and_find_element(self.driver, "//input[@id='uploadButton']").click()
329
389
 
330
- # Click on the "Convert" button.
331
- wait_and_find_element(driver, "//input[@id='uploadButton']").click()
390
+ # Handle alert box.
391
+ WebDriverWait(self.driver, TIMEOUT).until(EC.alert_is_present())
392
+ alert = Alert(self.driver)
393
+ alert_text = alert.text
394
+ alert.dismiss()
332
395
 
333
- # Handle alert box.
334
- WebDriverWait(driver, TIMEOUT).until(EC.alert_is_present())
335
- alert = Alert(driver)
336
- alert_text = alert.text
337
- alert.dismiss()
396
+ if alert_text.startswith("ERROR:"):
397
+ # Raise an appropriate exception type depending on if it's a recognised input issue or not
398
+ if "unexpected exception" in alert_text:
399
+ raise FileConverterAbortException(STATUS_CODE_GENERAL, alert_text)
400
+ raise FileConverterInputException(alert_text)
338
401
 
339
- if alert_text.startswith("ERROR:"):
340
- # Raise an appropriate exception type depending on if it's a recognised input issue or not
341
- if "unexpected exception" in alert_text:
342
- raise FileConverterAbortException(STATUS_CODE_GENERAL, alert_text)
343
- raise FileConverterInputException(alert_text)
402
+ # Wait until the log file exists, since it's downloaded second
403
+ time_elapsed = 0
404
+ while not os.path.isfile(self._log_file):
405
+ time.sleep(1)
406
+ time_elapsed += 1
407
+ if time_elapsed > TIMEOUT:
408
+ pytest.fail(f"Download of {self._output_file} and {self._log_file} timed out")
344
409
 
345
- # Wait until the log file exists, since it's downloaded second
346
- time_elapsed = 0
347
- while not os.path.isfile(log_file):
348
410
  time.sleep(1)
349
- time_elapsed += 1
350
- if time_elapsed > TIMEOUT:
351
- pytest.fail(f"Download of {output_file} and {log_file} timed out")
352
-
353
- time.sleep(1)
354
-
355
- if not os.path.isfile(output_file):
356
- raise FileConverterAbortException("ERROR: No output file was produced. Log contents:\n" +
357
- open(log_file, "r").read())
358
-
359
- # Move the output file and log file to the expected locations
360
- for qual_filename in output_file, log_file:
361
- base_filename = os.path.split(qual_filename)[1]
362
- target_filename = os.path.join(output_dir, base_filename)
363
- if os.path.isfile(target_filename):
364
- os.remove(target_filename)
365
- if os.path.isfile(qual_filename):
366
- shutil.move(qual_filename, target_filename)
411
+
412
+ def _move_output(self):
413
+ """Move the created output files out of the default Downloads directory and into the desired output files
414
+ directory.
415
+ """
416
+ # Check for the presence of the output file
417
+ if not os.path.isfile(self._output_file):
418
+ raise FileConverterAbortException("ERROR: No output file was produced. Log contents:\n" +
419
+ open(self._log_file, "r").read())
420
+
421
+ # Move the output file and log file to the expected locations
422
+ for qual_filename in self._output_file, self._log_file:
423
+ self._base_filename = os.path.split(qual_filename)[1]
424
+ target_filename = os.path.join(self.output_dir, self._base_filename)
425
+ if os.path.isfile(target_filename):
426
+ os.remove(target_filename)
427
+ if os.path.isfile(qual_filename):
428
+ shutil.move(qual_filename, target_filename)