robotframework-openapitools 1.0.0b2__py3-none-any.whl → 1.0.0b3__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.
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-04-03T11:37:57+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="358">
2
+ <keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-04-10T08:09:09+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="358">
3
3
  <version>1.0.0b2</version>
4
4
  <doc>&lt;p&gt;Visit the &lt;a href="https://github.com/MarketSquare/robotframework-openapidriver"&gt;library page&lt;/a&gt; for an introduction and examples.&lt;/p&gt;</doc>
5
5
  <tags>
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-04-03T11:37:50+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiLibCore/openapi_libcore.py" lineno="170">
2
+ <keywordspec name="OpenApiLibCore" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-04-10T08:09:02+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiLibCore/openapi_libcore.py" lineno="170">
3
3
  <version>1.0.0b2</version>
4
4
  <doc>&lt;p&gt;Main class providing the keywords and core logic to interact with an OpenAPI server.&lt;/p&gt;
5
5
  &lt;p&gt;Visit the &lt;a href="https://github.com/MarketSquare/robotframework-openapi-libcore"&gt;library page&lt;/a&gt; for an introduction.&lt;/p&gt;</doc>
@@ -40,11 +40,13 @@ BODY_TEMPLATE = BodyTemplate(BODY_TEMPLATE_)
40
40
  class OperationDetails:
41
41
  path: str
42
42
  method: str
43
- operation_id: str
44
43
  parameters: list[dict[str, Any]]
45
44
  request_body: dict[str, Any]
46
45
  summary: str
47
46
  description: str
47
+ operation_id: str | None = (
48
+ None # operationId MUST be unique within the spec, so no default ""
49
+ )
48
50
 
49
51
 
50
52
  @dataclass
@@ -65,7 +67,7 @@ def get_path_items(paths: dict[str, Any]) -> Generator[OperationDetails, None, N
65
67
  operation_details = OperationDetails(
66
68
  path=path,
67
69
  method=method,
68
- operation_id=method_item["operationId"],
70
+ operation_id=method_item.get("operationId", None),
69
71
  parameters=method_item.get("parameters", []),
70
72
  request_body=method_item.get("requestBody", {}),
71
73
  summary=method_item.get("summary"),
@@ -114,10 +116,14 @@ def get_keyword_signature(operation_details: OperationDetails) -> str:
114
116
  keyword_name = remove_unsafe_characters_from_string(
115
117
  operation_details.summary
116
118
  ).lower()
117
- else:
119
+ elif operation_details.operation_id:
118
120
  keyword_name = remove_unsafe_characters_from_string(
119
121
  operation_details.operation_id
120
122
  ).lower()
123
+ else:
124
+ keyword_name = remove_unsafe_characters_from_string(
125
+ f"{operation_details.method}_{operation_details.path}"
126
+ )
121
127
 
122
128
  parameters = get_parameter_details(operation_details=operation_details)
123
129
  path_parameters = [p for p in parameters if p.type == "path"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotframework-openapitools
3
- Version: 1.0.0b2
3
+ Version: 1.0.0b3
4
4
  Summary: A set of Robot Framework libraries to test APIs for which the OAS is available.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -235,3 +235,99 @@ OpenApiTools is a set of libraries centered around the OpenAPI Specification:
235
235
  - [OpenApiDriver](./driver.md)
236
236
  - [OpenApiLibCore](./libcore.md)
237
237
 
238
+
239
+ ## New in OpenApiTools v1.0.0
240
+
241
+ Inspired by the work Bartlomiej and Mateusz did on #roboswag, I've created a CLI tool that generates a fully functional Robot Framework (Python) library that builds on OpenApiLibCore for automatic request data generation and request execution.
242
+
243
+ ### So how does it work?
244
+ After installing / updating to the v1.0.0 beta (`pip install robotframework-openapitools==1.0.0b3`) , there's a new CLI command available in your (virtual) environment: `generate-library`. You'll have to provide a path to the openapi spec (json or yaml, can be a url or path to the file), provide a path to where to generate the library and (optionally) a name for the library:
245
+
246
+ ```
247
+ $ generate-library
248
+ Please provide a source for the generation:
249
+ $ http://127.0.0.1:8000/openapi.json
250
+ Please provide a path to where the library will be generated:
251
+ $ ./generated
252
+ Please provide a name for the library [default: FastAPI]:
253
+ $ My Generated Library
254
+ generated/MyGeneratedLibrary/__init__.py created
255
+ generated/MyGeneratedLibrary/my_generated_library.py created
256
+ ```
257
+
258
+ > Note: there's currently 2 environment variables that are taken into account by the generator; USE_SUMMARY_AS_KEYWORD_NAME can result in nicer keyword names (but: uniqueness is not guaranteed, so you might need to rename some of the generated keywords manually) and EXPAND_BODY_ARGUMENTS is what a recent poll in #api-testing was about.
259
+
260
+ If the location where the library is located is in your Python search path, you'll be able to use it like a regular Robot Framework library (in fact, it's a drop-in replacement for OpenApiLibCore):
261
+
262
+ ```{robot}
263
+ *** Settings ***
264
+ Library MyGeneratedLibrary
265
+ ... source=${ORIGIN}/openapi.json
266
+ ... origin=${ORIGIN}
267
+ ... base_path=${EMPTY}
268
+ ... mappings_path=${ROOT}/tests/user_implemented/custom_user_mappings.py
269
+ Variables ${ROOT}/tests/variables.py
270
+
271
+
272
+ *** Variables ***
273
+ ${ORIGIN}= http://localhost:8000
274
+
275
+
276
+ *** Test Cases ***
277
+ Test Generated Keywords: Get Employees
278
+ ${response}= Get Employees
279
+ Should Be Equal As Integers ${response.status_code} 200
280
+
281
+ Test Generated Keywords: Post Employee
282
+ VAR &{body} name=Robin the Robot
283
+ ${response}= Post Employee body=${body}
284
+ # ${response}= Post Employee name=Robin the Robot
285
+ Should Be Equal As Integers ${response.status_code} 201
286
+ Should Be Equal ${response.json()}[name] Robin the Robot
287
+
288
+ Test Generated Keywords: Get Employee
289
+ ${response}= Get Employee
290
+ Should Be Equal As Integers ${response.status_code} 200
291
+
292
+ Test Generated Keywords: Patch Employee
293
+ ${employee_id}= Get Valid Id For Path path=/employees/{employee_id}
294
+ VAR &{body} date_of_birth=2021-12-31
295
+ ${response}= Patch Employee employee_id=${employee_id} body=${body}
296
+ # ${response}= Patch Employee employee_id=${employee_id} date_of_birth=2021-12-31
297
+ Should Be Equal As Integers ${response.status_code} 403
298
+
299
+ Test Generated Keywords: Post WageGroup
300
+ VAR &{body} hourly_rate=99.99
301
+ ${response}= Post Wagegroup body=${body}
302
+ # ${response}= Post Wagegroup hourly_rate=99.99
303
+ Should Be Equal As Integers ${response.status_code} 201
304
+ Should Be Equal As Numbers ${response.json()}[hourly-rate] 99.99
305
+
306
+ Test Generated Keywords: Get Energy Label
307
+ ${response}= Get Energy Label
308
+ ... zipcode=1111AA
309
+ ... home_number=10
310
+ ... extension=too long to be acceptable
311
+ ... validate_against_schema=${FALSE}
312
+ Should Be Equal As Integers ${response.status_code} 422
313
+
314
+ VAR @{omit} extension
315
+ ${response}= Get Energy Label
316
+ ... zipcode=1111AA
317
+ ... home_number=10
318
+ ... extension=too long to be acceptable
319
+ ... omit_parameters=${omit}
320
+ Should Be Equal As Integers ${response.status_code} 200
321
+ ```
322
+
323
+ ### Contributions and feedback
324
+
325
+ So now I need your feedback! Does the library generator work for your openapi spec? Does the library work / do all the generated keywords work? Please let me know of any issues you run into!
326
+ Things I'd like to address / improve before an official release:
327
+ - parameters with union types (e.g. int or float) are currently annotated as Any.
328
+ - support for lists / arrays is limited (i.e. not supported as body)
329
+ - objects / dicts are currently only typed as dict; I'm looking into TypedDict annotation for better auto-complete / auto-conversion
330
+ - a documentation rework
331
+
332
+ Subscribe to https://app.slack.com/client/T07PJQ9S7/CKK0X68KD for updates
333
+
@@ -1,7 +1,7 @@
1
1
  OpenApiDriver/__init__.py,sha256=YjHr-j8g9KwRriNCw_ABvCEbUEp118J70xeJ_t7qcas,1453
2
2
  OpenApiDriver/openapi_executors.py,sha256=NsHhcP6CM3DsQgxqOcKhpAAOM0zjhMmCsrEygIxJleY,12534
3
3
  OpenApiDriver/openapi_reader.py,sha256=BPD_T8PUjfB-NBajogErI2ATmzlUGFJT8Nx5WpM5N5Y,4478
4
- OpenApiDriver/openapidriver.libspec,sha256=ObsSKxKimuui6KcJ6PifLJtfOitHbg7bl_TGW-cPpB8,28220
4
+ OpenApiDriver/openapidriver.libspec,sha256=O5gfWifWEvOmZ8sJoEdGcsP6Wak2zHYdEVB1TPIub6Y,28220
5
5
  OpenApiDriver/openapidriver.py,sha256=vypR00YZS3ygGfFxdUedLdCm_f_bWDLMpD1vb49-O0A,15321
6
6
  OpenApiDriver/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  OpenApiLibCore/__init__.py,sha256=R6n4FTEz0IGD_LehKkOFSQrlt9Bk4Ugl3OicsZ_h84I,1775
@@ -13,7 +13,7 @@ OpenApiLibCore/data_invalidation.py,sha256=HSzbeJnzxrlS2NlPfXnCRXvGzGzXvBwiaJ3WX
13
13
  OpenApiLibCore/dto_base.py,sha256=m41QZyL6ChIcC3DcBCpDFkok5wpCZ6K9gjmADyMGOWc,12132
14
14
  OpenApiLibCore/dto_utils.py,sha256=5dvMYM2Nt9gXq6GGTGJjU5Z75x9p9ky-1V01aLTZgX8,3177
15
15
  OpenApiLibCore/oas_cache.py,sha256=Z2v0mn6JwKchbUKojYVt9sXi8Mc4LoENtN_ekTUtzfI,387
16
- OpenApiLibCore/openapi_libcore.libspec,sha256=45xzp_QdGtaH4F_RjDDlL6mEKH12f6NndY0nrZi4yaA,53175
16
+ OpenApiLibCore/openapi_libcore.libspec,sha256=5NrzbwAsk-qUs504hu0DLjtvDhYJfgpvWiqjSPksGZg,53175
17
17
  OpenApiLibCore/openapi_libcore.py,sha256=30FtvsNHkfWZhz55bJq8bnWiHKvX6dEbGyLhbdNAtqY,36257
18
18
  OpenApiLibCore/parameter_utils.py,sha256=_P2GRc_teIixTgPsRgCxY2Bj6nsZq41GoSOhVgfXE0Y,3251
19
19
  OpenApiLibCore/path_functions.py,sha256=757f655yLg5HzvXxlOIQ76i48gK91Ct7KM-D9OAEA3A,8055
@@ -27,11 +27,11 @@ OpenApiLibCore/value_utils.py,sha256=M4k5m0YW1B20-6KD0f9-5xMERWKG8ncu2-5ahC2_VzU
27
27
  openapi_libgen/__init__.py,sha256=9ZfgPSI8AUAcJ59hBRZE1VImhMVRyt6G_w1nYIPORgQ,1543
28
28
  openapi_libgen/command_line.py,sha256=GppzNAAMomd0Dl5c5HGK8chDQw-kaIztD0hqQ2iUEXE,2783
29
29
  openapi_libgen/parsing_utils.py,sha256=d_N-v619SR6iyolz65IGN12H5wMUA8dzPuG1l7rv5gg,821
30
- openapi_libgen/spec_parser.py,sha256=9WCuCCDpMMr9jhA8fgzjBhhoF_DEWFc0lBwFcGBDqs4,8509
30
+ openapi_libgen/spec_parser.py,sha256=2swZDlr8pHkNHCaLZMkl9fZbi9GWDFfnstPbLB12jTU,8792
31
31
  openapi_libgen/templates/__init__.jinja,sha256=92OFwNzeO7lEiUBv04GfjKXA1088V7GbeneASBShbmc,102
32
32
  openapi_libgen/templates/library.jinja,sha256=tIwJuGerOUJmMt928P_38MMfcnSHZqcPDPEJ56R6wT0,952
33
- robotframework_openapitools-1.0.0b2.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
34
- robotframework_openapitools-1.0.0b2.dist-info/METADATA,sha256=Nu-LfVU0r_z8VCFX5UeM3r9eFScb9eiFmyalTBEiF10,14491
35
- robotframework_openapitools-1.0.0b2.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
36
- robotframework_openapitools-1.0.0b2.dist-info/entry_points.txt,sha256=_yd5PITEJf85hIEsrRkkWxXePf_O9YOOUjON3TYLy0c,69
37
- robotframework_openapitools-1.0.0b2.dist-info/RECORD,,
33
+ robotframework_openapitools-1.0.0b3.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
34
+ robotframework_openapitools-1.0.0b3.dist-info/METADATA,sha256=d99DolkNRk-sYtseHrh82lY2MJHZW6wLpJvZTpMfsUk,19067
35
+ robotframework_openapitools-1.0.0b3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
36
+ robotframework_openapitools-1.0.0b3.dist-info/entry_points.txt,sha256=_yd5PITEJf85hIEsrRkkWxXePf_O9YOOUjON3TYLy0c,69
37
+ robotframework_openapitools-1.0.0b3.dist-info/RECORD,,