1- from cloudharness .auth import get_token
21import os
32import logging
4-
53import schemathesis as st
4+ from schemathesis .hooks import HookContext
5+
6+ from cloudharness .auth import get_token
67st .experimental .OPEN_API_3_1 .enable ()
78
89
10+ import os
11+ import logging
12+ import schemathesis as st
13+
14+ # Enable experimental OpenAPI 3.1 support if needed
15+ st .experimental .OPEN_API_3_1 .enable ()
16+
917if "APP_URL" or "APP_SCHEMA_FILE" in os .environ :
1018 app_schema = os .environ .get ("APP_SCHEMA_FILE" , None )
1119 app_url = os .environ .get ("APP_URL" , "http://samples.ch.local/api" )
1220 logging .info ("Start schemathesis tests on %s" , app_url )
21+
1322 schema = None
23+
24+ # First, attempt to load the local file if provided
1425 if app_schema :
15- # Test locally with harness-test -- use local schema for convenience during test development
16- openapi_uri = app_schema
1726 try :
18- schema = st .from_file (openapi_uri )
27+ schema = st .from_file (app_schema )
28+ logging .info ("Successfully loaded schema from local file: %s" , app_schema )
1929 except st .exceptions .SchemaError :
20- logging .exception ("The local schema file %s cannot be loaded. Attempting loading from URL" , openapi_uri )
30+ logging .exception ("The local schema file %s cannot be loaded. Attempting loading from URL" , app_schema )
2131
32+ # If no schema from file, then loop over URL candidates
2233 if not schema :
23- # Try app_url/openapi.json
24- try :
25- openapi_uri = app_url .rstrip ("/" ) + "/openapi.json"
26- logging .info ("Using openapi spec at %s" , openapi_uri )
27- schema = st .from_uri (openapi_uri )
28- except st .exceptions .SchemaError :
29- logging .warning ("Failed to load schema from %s" , openapi_uri )
30-
31- # Then try app_url/api/openapi.json
34+ candidates = [
35+ app_url .rstrip ("/" ) + "/openapi.json" ,
36+ app_url .rstrip ("/" ) + "/api/openapi.json" ,
37+ ]
38+ for candidate in candidates :
3239 try :
33- openapi_uri = app_url .rstrip ("/" ) + "/api/openapi.json"
34- logging .info ("Using openapi spec at %s" , openapi_uri )
35- schema = st .from_uri (openapi_uri )
40+ logging .info ("Attempting to load schema from URI: %s" , candidate )
41+ schema = st .from_uri (candidate )
42+ logging .info ("Successfully loaded schema from %s" , candidate )
43+ break # Exit loop on successful load
3644 except st .exceptions .SchemaError as e :
37- raise Exception (
38- f"Cannot setup api tests: { openapi_uri } not valid. Check your deployment is up and configuration" ) from e
45+ logging .warning ("Failed to load schema from %s: %s" , candidate , e )
46+ except Exception as e :
47+ logging .error ("Unexpected error when loading schema from %s: %s" , candidate , e )
48+ if not schema :
49+ raise Exception ("Cannot setup API tests: No valid schema found. Check your deployment and configuration." )
3950
40- except Exception as e :
41- raise Exception (
42- f"Cannot setup api tests: { openapi_uri } : { e } " ) from e
4351
4452 if "USERNAME" in os .environ and "PASSWORD" in os .environ :
4553 logging .info ("Setting token from username and password" )
46-
54+
4755 @st .auth .register ()
4856 class TokenAuth :
4957 def get (self , context ):
@@ -68,3 +76,24 @@ def set(self, case, data, context):
6876 case .headers = case .headers or {}
6977 case .headers ["Authorization" ] = f"Bearer { data } "
7078 case .headers ["Cookie" ] = f"kc-access={ data } "
79+
80+ UNSAFE_VALUES = ("%" )
81+
82+ @st .hook
83+ def before_generate_path_parameters (context : HookContext , strategy ):
84+ def valid_param (x ):
85+ # Extract the candidate value.
86+ param = x ["key" ] if isinstance (x , dict ) and "key" in x else x
87+
88+ if param is None or param == "" :
89+ return True
90+
91+ param_str = str (param )
92+
93+ # Reject if any unsafe substring is present.
94+ if any (unsafe in param_str for unsafe in UNSAFE_VALUES ):
95+ return False
96+
97+ return True
98+
99+ return strategy .filter (valid_param )
0 commit comments