Skip to content

Commit

Permalink
Merge pull request #180 from ctripcorp/main_web_mock_new
Browse files Browse the repository at this point in the history
add web mock
  • Loading branch information
clgwlg authored Jun 20, 2023
2 parents fa1b548 + 2a9faf0 commit af2e8b1
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 6 deletions.
4 changes: 3 additions & 1 deletion flybirds/core/dsl/globalization/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@
"compare target element[{target_ele}] with compared text path of [{compared_text_path}]": [
"对比文本元素[{target_ele}]和基准文本路径[{compared_text_path}]"],
"call external party api of method[{method}] and url[{url}] and data[{data}] and headers[{headers}]": [
"调外部接口并传参请求方式[{method}]与请求链接[{url}]与请求内容[{data}]与请求标头[{headers}]"]
"调外部接口并传参请求方式[{method}]与请求链接[{url}]与请求内容[{data}]与请求标头[{headers}]"],
"open service [{service}] bind mockCase[{mock_case_id}]": [
"开启服务[{service}]绑定MockCase[{mock_case_id}]"],
},
}
6 changes: 6 additions & 0 deletions flybirds/core/dsl/step/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,9 @@ def request_compare_value(context, service=None, target_json_path=None,
"""
g_Context.step.request_compare_value(context, service, target_json_path,
expect_value)


@step("open service [{service}] bind mockCase[{mock_case_id}]")
@ele_wrap
def open_request_mock(context, service, mock_case_id):
g_Context.step.open_web_mock(context, service, mock_case_id)
2 changes: 2 additions & 0 deletions flybirds/core/plugin/event/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def scenario_fail(context, scenario):
try:
GlobalContext.step.clear_all_request_body(context)
GlobalContext.step.clear_all_request_mock(context)
GlobalContext.step.remove_web_mock(context)
except:
log.info("failed to remove mock and cache")

Expand Down Expand Up @@ -149,6 +150,7 @@ def scenario_success(context, scenario):
try:
GlobalContext.step.clear_all_request_body(context)
GlobalContext.step.clear_all_request_mock(context)
GlobalContext.step.remove_web_mock(context)
except:
log.info("failed to remove mock and cache")
launch_helper.app_start("scenario_success_page")
Expand Down
53 changes: 50 additions & 3 deletions flybirds/core/plugin/plugins/default/web/interception.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,53 @@ def add_some_interception_mock(service_str, mock_case_id_str):

gr.set_value('interceptionValues', interception_values)

@staticmethod
def open_web_mock(service_str, mock_case_id_str, request_mock_key_value: list):
if service_str is None or mock_case_id_str is None:
log.error('[addSomeInterceptionMock] param can not be none. ')
return

service_list = service_str.strip().split(',')
mock_case_id_list = mock_case_id_str.strip().split(',')
if len(service_list) != len(mock_case_id_list):
message = f"serviceCount[{service_str}] not equal " \
f"mockCaseCount[{mock_case_id_str}]"
raise FlybirdsException(message)

interception_values = request_mock_key_value
for i, service in enumerate(service_list):
if service is not None and len(service.strip()) > 0:
if ":" in service:
split_service = service.split(":")
if split_service[0].strip() == "reg":
interception_values.append({
"max": 1,
"key": split_service[1].strip(),
"value": mock_case_id_list[i].strip(),
"method": "reg"
})
elif split_service[0].strip() == "equ":
interception_values.append({
"max": 1,
"key": split_service[1].strip(),
"value": mock_case_id_list[i].strip(),
"method": "equ"
})
else:
interception_values.append({
"max": 1,
"key": service.strip(),
"value": mock_case_id_list[i].strip(),
"method": "contains"
})
else:
interception_values.append({
"max": 1,
"key": service.strip(),
"value": mock_case_id_list[i].strip(),
"method": "contains"
})

@staticmethod
def remove_some_interception_mock(service_str):
service_list = service_str.strip().split(',')
Expand Down Expand Up @@ -352,7 +399,7 @@ def request_compare_value(operation, target_path, expect_value):
raise FlybirdsException(message)

@staticmethod
def compare_images(context,target_picture_path, compared_picture_path, threshold=None):
def compare_images(context, target_picture_path, compared_picture_path, threshold=None):

if threshold is None:
threshold = 0.95
Expand Down Expand Up @@ -426,7 +473,7 @@ def compare_images(context,target_picture_path, compared_picture_path, threshold
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(image2, (x, y), (x + w, y + h), (0, 0, 255), 2)

cv2.imencode('.png',image2)[1].tofile(diff_file_path)
cv2.imencode('.png', image2)[1].tofile(diff_file_path)
message = f'Diff percentage of image [{threshold}] ' \
f'has been saved in path [{diff_file_path}]'

Expand Down Expand Up @@ -464,7 +511,7 @@ def compare_dom_element_text(target_text, compared_text_path):
# Compare the text content of the two DOM elements
if text1 == text2:
same = True
message = f'The text of the two UI elements are the same'\
message = f'The text of the two UI elements are the same' \
f' [{text1}]:' \
f' [{compared_text_path}] - [{text2}]:'
log.info(message)
Expand Down
71 changes: 71 additions & 0 deletions flybirds/core/plugin/plugins/default/web/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@
from flybirds.utils.dsl_helper import is_number
from flybirds.utils import file_helper
from flybirds.core.exceptions import FlybirdsException
import urllib.parse
import threading
from urllib.parse import urlsplit, urlunsplit

__open__ = ["Page"]

mock_lock: threading.Lock = threading.Lock()


class Page:
"""Web Page Class"""
Expand Down Expand Up @@ -346,6 +351,46 @@ def handle_request(request):
gr.set_value("interceptionRequest", interception_request)


def mock_rules(url: str, request_mock_key_value: list):
if url is None or len(url.strip()) <= 0:
return None
scheme, netloc, path, query, fragment = urlsplit(url)
temp_path = urlunsplit(("", "", path, query, fragment))
if temp_path is None or len(temp_path.strip()) <= 0:
return None
if path is None or len(path.strip()) <= 0:
return None
match_mock_key = None
with mock_lock:
for mock_rule in request_mock_key_value:
mock_find = False
if mock_rule is not None and mock_rule.get("key") and mock_rule.get("value") and mock_rule.get("max"):
if mock_rule.get("key") is not None and len(mock_rule.get("key").strip()) > 0 and len(
mock_rule.get("value").strip()) > 0:
if mock_rule.get("max") <= 0:
continue
method = mock_rule.get("method", None)
if method is None or method == "contains":
if mock_rule.get("key").strip() in temp_path:
mock_find = True
elif method == "equ":
if mock_rule.get("key").strip().strip("/").strip("\\") == path.lower().strip().strip("/").strip(
"\\"):
mock_find = True
elif method == "reg":
match = re.search(mock_rule.get("key").strip(), temp_path)
if match:
mock_find = True
else:
if mock_rule.get("key").strip() in temp_path:
mock_find = True
if mock_find:
match_mock_key = mock_rule
mock_rule["max"] = mock_rule.get("max") - 1
break
return match_mock_key


def handle_route(route):
abort_domain_list = gr.get_web_info_value("abort_domain_list", [])
parsed_uri = urlparse(route.request.url)
Expand All @@ -361,6 +406,32 @@ def handle_route(route):
if result:
return
resource_type = route.request.resource_type
# pass options
if route.request.method.lower() == "options":
route.continue_()
return
# mock response
request_mock_key_value = GlobalContext.get_global_cache("request_mock_key_value")
if request_mock_key_value is not None and len(request_mock_key_value) > 0:
try:
mock_rule = mock_rules(route.request.url, request_mock_key_value)
if mock_rule is not None:
log.info(
f"url:{route.request.url}===== match mock key:{mock_rule.get('key')} mock case "
f":{mock_rule.get('value')}===================")
mock_body = get_case_response_body(mock_rule.get("value"))
if mock_body:
if not isinstance(mock_body, str):
mock_body = json.dumps(mock_body)
route.fulfill(status=200,
content_type="application/json;charset=utf-8",
body=mock_body)
return

except Exception as mock_error:
log.info("find mock info error", mock_error)
finally:
pass
if resource_type != 'fetch' and resource_type != 'xhr':
route.continue_()
return
Expand Down
19 changes: 17 additions & 2 deletions flybirds/core/plugin/plugins/default/web/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
Interception as request_op
from flybirds.core.exceptions import FlybirdsException
from flybirds.utils import dsl_helper, uuid_helper
from flybirds.core.global_context import GlobalContext

__open__ = ["Step"]

Expand Down Expand Up @@ -355,8 +356,7 @@ def picture_compare_from_path(context, target_element, compared_picture_path):
old_filename = f"{os.path.splitext(filename)[0]}_{uuid}_old.png"
target_image_path = os.path.join(directory, old_filename)
target_image_io.save(target_image_path)
request_op.compare_images(context,target_image_path, compared_picture_path, threshold)

request_op.compare_images(context, target_image_path, compared_picture_path, threshold)

@staticmethod
def dom_ele_compare_from_path(context, target_ele, compared_text_path):
Expand All @@ -375,3 +375,18 @@ def dom_ele_compare_from_path(context, target_ele, compared_text_path):
@staticmethod
def call_external_party_api(context, method, url, data, headers):
request_op.call_external_party_api(method, url, data, headers)

@staticmethod
def open_web_mock(context, service_str, mock_case_id_str):
request_mock_key_value = GlobalContext.get_global_cache("request_mock_key_value")
if request_mock_key_value is None:
request_mock_key_value = []
GlobalContext.set_global_cache("request_mock_key_value", request_mock_key_value)
request_op.open_web_mock(service_str, mock_case_id_str, request_mock_key_value)

@staticmethod
def remove_web_mock(context):
request_mock_key_value = GlobalContext.get_global_cache("request_mock_key_value")
if request_mock_key_value is not None:
del request_mock_key_value
GlobalContext.set_global_cache("request_mock_key_value", None)

0 comments on commit af2e8b1

Please sign in to comment.