edq-utils 0.0.4__py3-none-any.whl → 0.0.6__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.

Potentially problematic release.


This version of edq-utils might be problematic. Click here for more details.

Files changed (71) hide show
  1. edq/__init__.py +1 -1
  2. edq/cli/config/__init__.py +3 -0
  3. edq/cli/config/list.py +69 -0
  4. edq/cli/http/__init__.py +3 -0
  5. edq/cli/http/exchange-server.py +71 -0
  6. edq/cli/http/send-exchange.py +45 -0
  7. edq/cli/http/verify-exchanges.py +38 -0
  8. edq/cli/testing/__init__.py +3 -0
  9. edq/cli/testing/cli-test.py +12 -5
  10. edq/cli/version.py +2 -1
  11. edq/core/argparser.py +28 -3
  12. edq/core/config.py +268 -0
  13. edq/core/config_test.py +1038 -0
  14. edq/procedure/verify_exchanges.py +85 -0
  15. edq/testing/asserts.py +0 -1
  16. edq/testing/cli.py +107 -29
  17. edq/testing/cli_test.py +8 -1
  18. edq/testing/httpserver.py +553 -0
  19. edq/testing/httpserver_test.py +424 -0
  20. edq/testing/run.py +40 -10
  21. edq/testing/testdata/cli/data/configs/empty/edq-config.json +1 -0
  22. edq/testing/testdata/cli/data/configs/simple-1/edq-config.json +4 -0
  23. edq/testing/testdata/cli/data/configs/simple-2/edq-config.json +3 -0
  24. edq/testing/testdata/cli/data/configs/value-number/edq-config.json +3 -0
  25. edq/testing/testdata/cli/tests/config/list/config_list_base.txt +16 -0
  26. edq/testing/testdata/cli/tests/config/list/config_list_config_value_number.txt +10 -0
  27. edq/testing/testdata/cli/tests/config/list/config_list_ignore_config.txt +14 -0
  28. edq/testing/testdata/cli/tests/config/list/config_list_no_config.txt +8 -0
  29. edq/testing/testdata/cli/tests/config/list/config_list_show_origin.txt +13 -0
  30. edq/testing/testdata/cli/tests/config/list/config_list_skip_header.txt +10 -0
  31. edq/testing/testdata/cli/tests/platform_skip.txt +5 -0
  32. edq/testing/testdata/http/exchanges/simple.httpex.json +5 -0
  33. edq/testing/testdata/http/exchanges/simple_anchor.httpex.json +5 -0
  34. edq/testing/testdata/http/exchanges/simple_file.httpex.json +10 -0
  35. edq/testing/testdata/http/exchanges/simple_file_binary.httpex.json +10 -0
  36. edq/testing/testdata/http/exchanges/simple_file_get_params.httpex.json +14 -0
  37. edq/testing/testdata/http/exchanges/simple_file_multiple.httpex.json +13 -0
  38. edq/testing/testdata/http/exchanges/simple_file_name.httpex.json +11 -0
  39. edq/testing/testdata/http/exchanges/simple_file_post_multiple.httpex.json +13 -0
  40. edq/testing/testdata/http/exchanges/simple_file_post_params.httpex.json +14 -0
  41. edq/testing/testdata/http/exchanges/simple_headers.httpex.json +8 -0
  42. edq/testing/testdata/http/exchanges/simple_jsonresponse_dict.httpex.json +7 -0
  43. edq/testing/testdata/http/exchanges/simple_jsonresponse_list.httpex.json +9 -0
  44. edq/testing/testdata/http/exchanges/simple_params.httpex.json +9 -0
  45. edq/testing/testdata/http/exchanges/simple_post.httpex.json +5 -0
  46. edq/testing/testdata/http/exchanges/simple_post_params.httpex.json +9 -0
  47. edq/testing/testdata/http/exchanges/simple_post_urlparams.httpex.json +5 -0
  48. edq/testing/testdata/http/exchanges/simple_urlparams.httpex.json +5 -0
  49. edq/testing/testdata/http/exchanges/specialcase_listparams_explicit.httpex.json +8 -0
  50. edq/testing/testdata/http/exchanges/specialcase_listparams_url.httpex.json +5 -0
  51. edq/testing/testdata/http/files/tiny.png +0 -0
  52. edq/testing/unittest.py +26 -6
  53. edq/util/dirent.py +2 -0
  54. edq/util/dirent_test.py +43 -32
  55. edq/util/json.py +21 -4
  56. edq/util/net.py +894 -0
  57. edq_utils-0.0.6.dist-info/METADATA +156 -0
  58. edq_utils-0.0.6.dist-info/RECORD +78 -0
  59. edq/util/testdata/dirent-operations/dir_1/b.txt +0 -1
  60. edq/util/testdata/dirent-operations/dir_1/dir_2/c.txt +0 -1
  61. edq/util/testdata/dirent-operations/symlink_a.txt +0 -1
  62. edq/util/testdata/dirent-operations/symlink_dir_1/b.txt +0 -1
  63. edq/util/testdata/dirent-operations/symlink_dir_1/dir_2/c.txt +0 -1
  64. edq/util/testdata/dirent-operations/symlink_file_empty +0 -0
  65. edq_utils-0.0.4.dist-info/METADATA +0 -63
  66. edq_utils-0.0.4.dist-info/RECORD +0 -41
  67. /edq/{util/testdata/dirent-operations/file_empty → procedure/__init__.py} +0 -0
  68. /edq/{util/testdata/dirent-operations → testing/testdata/http/files}/a.txt +0 -0
  69. {edq_utils-0.0.4.dist-info → edq_utils-0.0.6.dist-info}/WHEEL +0 -0
  70. {edq_utils-0.0.4.dist-info → edq_utils-0.0.6.dist-info}/licenses/LICENSE +0 -0
  71. {edq_utils-0.0.4.dist-info → edq_utils-0.0.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,424 @@
1
+ import os
2
+
3
+ import edq.testing.httpserver
4
+ import edq.util.net
5
+
6
+ THIS_DIR: str = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
7
+ TEST_EXCHANGES_DIR: str = os.path.join(THIS_DIR, "testdata", "http", 'exchanges')
8
+
9
+ class HTTPTestServerTest(edq.testing.httpserver.HTTPServerTest):
10
+ """ Test the HTTP test server. """
11
+
12
+ @classmethod
13
+ def setup_server(cls, server: edq.testing.httpserver.HTTPTestServer) -> None:
14
+ edq.testing.httpserver.HTTPServerTest.setup_server(server)
15
+ server.load_exchanges_dir(TEST_EXCHANGES_DIR)
16
+
17
+ def test_exchange_validation(self):
18
+ """ Test validation of exchanges. """
19
+
20
+ # [(kwargs, expected, error substring), ...]
21
+ test_cases = [
22
+ # Base
23
+
24
+ (
25
+ {
26
+ 'method': 'GET',
27
+ 'url': 'simple',
28
+ },
29
+ edq.util.net.HTTPExchange(
30
+ method = 'GET',
31
+ url = 'simple',
32
+ ),
33
+ None,
34
+ ),
35
+
36
+ (
37
+ {
38
+ 'method': 'ZZZ',
39
+ 'url': 'simple',
40
+ },
41
+ None,
42
+ 'unknown/disallowed method',
43
+ ),
44
+
45
+ (
46
+ {
47
+ },
48
+ None,
49
+ 'URL path cannot be empty',
50
+ ),
51
+
52
+ # URL Components
53
+
54
+ (
55
+ {
56
+ 'url': 'foo?a=b#c',
57
+ },
58
+ edq.util.net.HTTPExchange(
59
+ url_path = 'foo',
60
+ url_anchor = 'c',
61
+ parameters = {
62
+ 'a': 'b',
63
+ },
64
+ ),
65
+ None,
66
+ ),
67
+
68
+ (
69
+ {
70
+ 'url': 'for',
71
+ 'url_path': 'bar',
72
+ },
73
+ None,
74
+ 'Mismatched URL paths',
75
+ ),
76
+
77
+ (
78
+ {
79
+ 'url': 'for#a',
80
+ 'url_anchor': 'b',
81
+ },
82
+ None,
83
+ 'Mismatched URL anchors',
84
+ ),
85
+
86
+ # Files
87
+
88
+ (
89
+ {
90
+ 'url': 'foo',
91
+ 'files': [
92
+ {
93
+ 'path': 'test.txt',
94
+ }
95
+ ],
96
+ },
97
+ edq.util.net.HTTPExchange(
98
+ url_path = 'foo',
99
+ files = [
100
+ edq.util.net.FileInfo(name = 'test.txt', path = 'test.txt'),
101
+ ]
102
+ ),
103
+ None,
104
+ ),
105
+
106
+ (
107
+ {
108
+ 'url': 'foo',
109
+ 'files': [
110
+ {
111
+ 'content': '',
112
+ }
113
+ ],
114
+ },
115
+ None,
116
+ 'No name was provided for file',
117
+ ),
118
+
119
+ (
120
+ {
121
+ 'url': 'foo',
122
+ 'files': [
123
+ {
124
+ 'name': 'foo.txt',
125
+ }
126
+ ],
127
+ },
128
+ None,
129
+ 'File must have either path or content',
130
+ ),
131
+
132
+ # JSON Response Body
133
+
134
+ (
135
+ {
136
+ 'url': 'foo',
137
+ 'response_body': {
138
+ 'a': 1,
139
+ }
140
+ },
141
+ edq.util.net.HTTPExchange(
142
+ url_path = 'foo',
143
+ json_body = True,
144
+ response_body = '{"a": 1}',
145
+ ),
146
+ None,
147
+ ),
148
+
149
+ (
150
+ {
151
+ 'url': 'foo',
152
+ 'response_body': [{
153
+ 'a': 1,
154
+ }]
155
+ },
156
+ edq.util.net.HTTPExchange(
157
+ url_path = 'foo',
158
+ json_body = True,
159
+ response_body = '[{"a": 1}]',
160
+ ),
161
+ None,
162
+ ),
163
+ ]
164
+
165
+ for (i, test_case) in enumerate(test_cases):
166
+ (kwargs, expected, error_substring) = test_case
167
+
168
+ with self.subTest(msg = f"Case {i}:"):
169
+ try:
170
+ actual = edq.util.net.HTTPExchange(**kwargs)
171
+ except Exception as ex:
172
+ error_string = self.format_error_string(ex)
173
+ if (error_substring is None):
174
+ self.fail(f"Unexpected error: '{error_string}'.")
175
+
176
+ self.assertIn(error_substring, error_string, 'Error is not as expected.')
177
+
178
+ continue
179
+
180
+ if (error_substring is not None):
181
+ self.fail(f"Did not get expected error: '{error_substring}'.")
182
+
183
+ self.assertJSONDictEqual(expected, actual)
184
+
185
+ def test_exchange_matching_base(self):
186
+ """ Test matching exchanges against queries. """
187
+
188
+ # {<file basename no ext>: exchange, ...}
189
+ exchanges = {}
190
+ for exchange in self.get_server().get_exchanges():
191
+ key = os.path.basename(exchange.source_path).replace(edq.util.net.DEFAULT_HTTP_EXCHANGE_EXTENSION, '')
192
+ exchanges[key] = exchange
193
+
194
+ # [(target, query, match?, hint substring), ...]
195
+ test_cases = [
196
+ # Base
197
+ (
198
+ exchanges['simple'],
199
+ edq.util.net.HTTPExchange(
200
+ method = 'GET',
201
+ url = 'simple',
202
+ ),
203
+ {},
204
+ True,
205
+ None,
206
+ ),
207
+
208
+ # Params
209
+ (
210
+ exchanges['simple_params'],
211
+ edq.util.net.HTTPExchange(
212
+ method = 'GET',
213
+ url = 'simple',
214
+ parameters = {
215
+ 'a': '1',
216
+ 'b': '2',
217
+ },
218
+ ),
219
+ {},
220
+ True,
221
+ None,
222
+ ),
223
+
224
+ # Params, skip missing.
225
+ (
226
+ exchanges['simple'],
227
+ exchanges['simple_params'],
228
+ {
229
+ 'params_to_skip': ['a', 'b'],
230
+ },
231
+ True,
232
+ None,
233
+ ),
234
+
235
+ # Headers, skip missing.
236
+ (
237
+ exchanges['simple'],
238
+ exchanges['simple_headers'],
239
+ {
240
+ 'headers_to_skip': ['a'],
241
+ },
242
+ True,
243
+ None,
244
+ ),
245
+
246
+ # Param, skip unmatching.
247
+ (
248
+ exchanges['simple_params'],
249
+ edq.util.net.HTTPExchange(
250
+ method = 'GET',
251
+ url = 'simple',
252
+ parameters = {
253
+ 'a': '1',
254
+ 'b': 'ZZZ',
255
+ },
256
+ ),
257
+ {
258
+ 'params_to_skip': ['b'],
259
+ },
260
+ True,
261
+ None,
262
+ ),
263
+
264
+ (
265
+ exchanges['simple'],
266
+ exchanges['simple_headers'],
267
+ {
268
+ 'match_headers': False,
269
+ },
270
+ True,
271
+ None,
272
+ ),
273
+
274
+ # Misses
275
+
276
+ # Missed method.
277
+ (
278
+ exchanges['simple'],
279
+ edq.util.net.HTTPExchange(
280
+ method = 'POST',
281
+ url = 'simple',
282
+ ),
283
+ {},
284
+ False,
285
+ 'method does not match',
286
+ ),
287
+ (
288
+ exchanges['simple'],
289
+ exchanges['simple_post'],
290
+ {},
291
+ False,
292
+ 'method does not match',
293
+ ),
294
+
295
+ # Missed URL path.
296
+ (
297
+ exchanges['simple'],
298
+ edq.util.net.HTTPExchange(
299
+ method = 'GET',
300
+ url = 'ZZZ',
301
+ ),
302
+ {},
303
+ False,
304
+ 'URL path does not match',
305
+ ),
306
+
307
+ # Missed URL anchor.
308
+ (
309
+ exchanges['simple'],
310
+ edq.util.net.HTTPExchange(
311
+ method = 'GET',
312
+ url = 'simple#1',
313
+ ),
314
+ {},
315
+ False,
316
+ 'URL anchor does not match',
317
+ ),
318
+
319
+ # Missed number of params.
320
+ (
321
+ exchanges['simple'],
322
+ edq.util.net.HTTPExchange(
323
+ method = 'GET',
324
+ url = 'simple',
325
+ parameters = {'a': '1'},
326
+ ),
327
+ {},
328
+ False,
329
+ 'Parameter keys do not match',
330
+ ),
331
+ (
332
+ exchanges['simple_post'],
333
+ exchanges['simple_post_params'],
334
+ {},
335
+ False,
336
+ 'Parameter keys do not match',
337
+ ),
338
+ (
339
+ exchanges['simple_post'],
340
+ exchanges['simple_post_urlparams'],
341
+ {},
342
+ False,
343
+ 'Parameter keys do not match',
344
+ ),
345
+
346
+ # Missed param value.
347
+ (
348
+ exchanges['simple_params'],
349
+ edq.util.net.HTTPExchange(
350
+ method = 'GET',
351
+ url = 'simple',
352
+ parameters = {
353
+ 'a': '1',
354
+ 'b': 'ZZZ',
355
+ },
356
+ ),
357
+ {},
358
+ False,
359
+ "Parameter 'b' has a non-matching value",
360
+ ),
361
+
362
+ # Missed number of headers.
363
+ (
364
+ exchanges['simple'],
365
+ exchanges['simple_headers'],
366
+ {
367
+ 'match_headers': True,
368
+ },
369
+ False,
370
+ 'Header keys do not match',
371
+ ),
372
+
373
+ # Missed header value.
374
+ (
375
+ exchanges['simple_headers'],
376
+ edq.util.net.HTTPExchange(
377
+ method = 'GET',
378
+ url = 'simple',
379
+ headers = {
380
+ 'a': 'ZZZ',
381
+ },
382
+ ),
383
+ {
384
+ 'match_headers': True,
385
+ },
386
+ False,
387
+ "Header 'a' has a non-matching value",
388
+ ),
389
+
390
+ # Param, with skip.
391
+ (
392
+ exchanges['simple_params'],
393
+ edq.util.net.HTTPExchange(
394
+ method = 'GET',
395
+ url = 'simple',
396
+ parameters = {
397
+ 'a': '1',
398
+ 'b': 'ZZZ',
399
+ },
400
+ ),
401
+ {
402
+ 'params_to_skip': ['a'],
403
+ },
404
+ False,
405
+ "Parameter 'b' has a non-matching value",
406
+ ),
407
+ ]
408
+
409
+ for (i, test_case) in enumerate(test_cases):
410
+ (target, query, match_options, expected_match, hint_substring) = test_case
411
+ base_name = os.path.basename(target.source_path).replace(edq.util.net.DEFAULT_HTTP_EXCHANGE_EXTENSION, '')
412
+
413
+ with self.subTest(msg = f"Case {i} ('{base_name}'):"):
414
+ actual_match, hint = target.match(query, **match_options)
415
+
416
+ self.assertEqual(expected_match, actual_match, f"Match status does not agree (hint: '{hint}').")
417
+
418
+ if (hint is not None):
419
+ if (hint_substring is None):
420
+ self.fail(f"Unexpected hint: '{hint}'.")
421
+
422
+ self.assertIn(hint_substring, hint, 'Hint is not as expected.')
423
+ elif (hint_substring is not None):
424
+ self.fail(f"Did not get expected hint: '{hint_substring}'.")
edq/testing/run.py CHANGED
@@ -12,6 +12,13 @@ import typing
12
12
  import unittest
13
13
 
14
14
  DEFAULT_TEST_FILENAME_PATTERN: str = '*_test.py'
15
+ """ The default pattern for test files. """
16
+
17
+ CLEANUP_FUNC_NAME: str = 'suite_cleanup'
18
+ """
19
+ If a test class has a function with this name,
20
+ then the function will be run after the test suite finishes.
21
+ """
15
22
 
16
23
  def _collect_tests(suite: typing.Union[unittest.TestCase, unittest.suite.TestSuite]) -> typing.List[unittest.TestCase]:
17
24
  """
@@ -30,44 +37,67 @@ def _collect_tests(suite: typing.Union[unittest.TestCase, unittest.suite.TestSui
30
37
 
31
38
  return test_cases
32
39
 
33
- def run(args: argparse.Namespace) -> int:
40
+ def run(args: typing.Union[argparse.Namespace, typing.Dict[str, typing.Any], None] = None) -> int:
34
41
  """
35
42
  Discover and run unit tests.
36
43
  This function may change your working directory.
37
44
  Will raise if tests fail to load (e.g. syntax errors) and a suggested exit code otherwise.
38
45
  """
39
46
 
40
- if (args.work_dir is not None):
41
- os.chdir(args.work_dir)
47
+ if (args is None):
48
+ args = {}
49
+
50
+ if (not isinstance(args, dict)):
51
+ args = vars(args)
52
+
53
+ if (args.get('work_dir', None) is not None):
54
+ os.chdir(args['work_dir'])
42
55
 
43
- if (args.path_additions is not None):
44
- for path in args.path_additions:
56
+ if (args.get('path_additions', None) is not None):
57
+ for path in args['path_additions']:
45
58
  sys.path.append(path)
46
59
 
47
- if (args.test_dirs is None):
48
- args.test_dirs = ['.']
60
+ test_dirs = args.get('test_dirs', None)
61
+ if (test_dirs is None):
62
+ test_dirs = []
63
+
64
+ if (len(test_dirs) == 0):
65
+ test_dirs.append('.')
49
66
 
50
67
  runner = unittest.TextTestRunner(verbosity = 3)
51
68
  test_cases = []
52
69
 
53
- for test_dir in args.test_dirs:
54
- discovered_suite = unittest.TestLoader().discover(test_dir, pattern = args.filename_pattern)
70
+ for test_dir in test_dirs:
71
+ discovered_suite = unittest.TestLoader().discover(test_dir, pattern = args.get('filename_pattern', DEFAULT_TEST_FILENAME_PATTERN))
55
72
  test_cases += _collect_tests(discovered_suite)
56
73
 
74
+ # Cleanup class functions from test classes.
75
+ # {class: function, ...}
76
+ cleanup_funcs = {}
77
+
57
78
  tests = unittest.suite.TestSuite()
58
79
 
59
80
  for test_case in test_cases:
60
81
  if (isinstance(test_case, unittest.loader._FailedTest)): # type: ignore[attr-defined]
61
82
  raise ValueError(f"Failed to load test: '{test_case.id()}'.") from test_case._exception
62
83
 
63
- if (args.pattern is None or re.search(args.pattern, test_case.id())):
84
+ pattern = args.get('pattern', None)
85
+ if ((pattern is None) or re.search(pattern, test_case.id())):
64
86
  tests.addTest(test_case)
87
+
88
+ # Check for a cleanup function.
89
+ if (hasattr(test_case.__class__, CLEANUP_FUNC_NAME)):
90
+ cleanup_funcs[test_case.__class__] = getattr(test_case.__class__, CLEANUP_FUNC_NAME)
65
91
  else:
66
92
  print(f"Skipping {test_case.id()} because of match pattern.")
67
93
 
68
94
  result = runner.run(tests)
69
95
  faults = len(result.errors) + len(result.failures)
70
96
 
97
+ # Perform any cleanup.
98
+ for cleanup_func in cleanup_funcs.values():
99
+ cleanup_func()
100
+
71
101
  if (not result.wasSuccessful()):
72
102
  # This value will be used as an exit status, so it should not be larger than a byte.
73
103
  # (Some higher values are used specially, so just keep it at a round number.)
@@ -0,0 +1,4 @@
1
+ {
2
+ "user": "user@test.edulinq.org",
3
+ }
4
+
@@ -0,0 +1,3 @@
1
+ {
2
+ "api-key": "KEY-1234567890",
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "timeout": 60
3
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
5
+ "--config-file", "__DATA_DIR__(configs/simple-1/edq-config.json)",
6
+ "--config-file", "__DATA_DIR__(configs/simple-2/edq-config.json)",
7
+ "--config", "pass=password1234",
8
+ "--config", "server=http://test.edulinq.org"
9
+ ],
10
+ }
11
+ ---
12
+ Key Value
13
+ api-key KEY-1234567890
14
+ pass password1234
15
+ server http://test.edulinq.org
16
+ user user@test.edulinq.org
@@ -0,0 +1,10 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
5
+ "--config-file", "__DATA_DIR__(configs/value-number/edq-config.json)",
6
+ ],
7
+ }
8
+ ---
9
+ Key Value
10
+ timeout 60
@@ -0,0 +1,14 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--ignore-config-option", "pass",
5
+ "--ignore-config-option", "api-key",
6
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
7
+ "--config-file", "__DATA_DIR__(configs/simple-1/edq-config.json)",
8
+ "--config-file", "__DATA_DIR__(configs/simple-2/edq-config.json)",
9
+ "--config", "pass=password1234",
10
+ ],
11
+ }
12
+ ---
13
+ Key Value
14
+ user user@test.edulinq.org
@@ -0,0 +1,8 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
5
+ ],
6
+ }
7
+ ---
8
+ Key Value
@@ -0,0 +1,13 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--config-file", "__DATA_DIR__(configs/simple-1/edq-config.json)",
5
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
6
+ "--config", "pass=password1234",
7
+ "--show-origin",
8
+ ],
9
+ }
10
+ ---
11
+ Key Value Origin
12
+ pass password1234 <cli argument>
13
+ user user@test.edulinq.org __ABS_DATA_DIR__(configs/simple-1/edq-config.json)
@@ -0,0 +1,10 @@
1
+ {
2
+ "cli": "edq.cli.config.list",
3
+ "arguments": [
4
+ "--config-global", "__DATA_DIR__(configs/empty/edq-config.json)",
5
+ "--config", "user=user@test.edulinq.org",
6
+ "--skip-header",
7
+ ],
8
+ }
9
+ ---
10
+ user user@test.edulinq.org
@@ -0,0 +1,5 @@
1
+ {
2
+ "cli": "package.that.does.not.exist.and.should.never.be.called",
3
+ "platform_skip": ".*"
4
+ }
5
+ ---
@@ -0,0 +1,5 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple",
4
+ "response_body": "simple"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple#a",
4
+ "response_body": "simple_anchor"
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple",
4
+ "files": [
5
+ {
6
+ "path": "../files/a.txt"
7
+ }
8
+ ],
9
+ "response_body": "simple_file"
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple",
4
+ "files": [
5
+ {
6
+ "path": "../files/tiny.png"
7
+ }
8
+ ],
9
+ "response_body": "simple_file_binary"
10
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple",
4
+ "parameters": {
5
+ "a": "1",
6
+ "b": "2"
7
+ },
8
+ "files": [
9
+ {
10
+ "path": "../files/a.txt"
11
+ }
12
+ ],
13
+ "response_body": "simple_file_get_params"
14
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "method": "GET",
3
+ "url": "simple",
4
+ "files": [
5
+ {
6
+ "path": "../files/a.txt"
7
+ },
8
+ {
9
+ "path": "../files/tiny.png"
10
+ }
11
+ ],
12
+ "response_body": "simple_file_multiple"
13
+ }