Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
0
01SaaS-test
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
吴珊婧
01SaaS-test
Commits
f825d854
Commit
f825d854
authored
Jul 08, 2026
by
lujuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增智能接单配置准入用例
parent
2f4c7735
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
564 additions
and
7 deletions
+564
-7
wanzhanggui_order_page.py
e2e/pages/wanzhanggui_order_page.py
+406
-7
test_e2e_auto_acceptance_config_rules.py
e2e/tests/智能接单/test_e2e_auto_acceptance_config_rules.py
+158
-0
智能接单测试用例_配置准入补充_20260708.xlsx
e2e/tests/智能接单/智能接单测试用例_配置准入补充_20260708.xlsx
+0
-0
No files found.
e2e/pages/wanzhanggui_order_page.py
View file @
f825d854
...
...
@@ -58,6 +58,10 @@ class ManualOrderData:
service_hours
:
str
=
"14"
boss_phone
:
str
=
"13800138000"
contact_phone
:
str
=
"13800138000"
game_name
:
str
=
"王者"
game_region
:
str
=
"WeGame"
game_server
:
str
=
"微信2区-国士无双"
service_project
:
str
=
"排位"
game_account
:
str
=
"41275199"
game_password
:
str
=
"test123456"
role_name
:
str
=
"E2E测试角色"
...
...
@@ -69,9 +73,9 @@ class ManualOrderData:
return
"
\n
"
.
join
(
[
"订单来源:拼多多"
,
"游戏:王者荣耀
"
,
"区服:安卓QQ 国服
"
,
"服务项目:排位陪-陪玩
"
,
f
"游戏:{self.game_name}
"
,
f
"区服:{self.game_region} {self.game_server}
"
,
f
"服务项目:{self.service_project}
"
,
f
"来源单号:{self.source_order_no}"
,
f
"订单标题:{self.order_title}"
,
f
"角色名:{self.role_name}"
,
...
...
@@ -4278,10 +4282,7 @@ class WanzhangguiOrderPage(TenantAuthPage):
self
.
fill_number_by_placeholder
(
frame
,
"请输入价格"
,
order
.
receive_price
)
self
.
select_first_available_if_placeholder
(
frame
,
"请选择订单来源"
,
field_name
=
"订单来源"
)
self
.
select_first_available_if_placeholder
(
frame
,
"游戏"
)
self
.
select_first_available_if_placeholder
(
frame
,
"区"
)
self
.
select_first_available_if_placeholder
(
frame
,
"服"
)
self
.
select_service_project
(
frame
)
self
.
select_manual_order_game_region_service_values
(
frame
,
order
)
self
.
ensure_game_region_service_selected
(
frame
)
self
.
align_order_type_with_service_project
(
frame
)
self
.
select_sales_customer
(
frame
)
...
...
@@ -4298,6 +4299,7 @@ class WanzhangguiOrderPage(TenantAuthPage):
self
.
fill_input_by_placeholder
(
frame
,
"小时"
,
order
.
service_hours
)
self
.
fill_input_by_placeholder
(
frame
,
"请输入订单内容"
,
order
.
order_title
)
self
.
fill_number_by_placeholder
(
frame
,
"请输入价格"
,
order
.
receive_price
)
self
.
select_manual_order_game_region_service_values
(
frame
,
order
)
self
.
ensure_game_region_service_selected
(
frame
)
self
.
fill_sub_order_row
(
frame
,
order
)
...
...
@@ -4307,6 +4309,7 @@ class WanzhangguiOrderPage(TenantAuthPage):
self
.
fill_input_by_placeholder
(
frame
,
"小时"
,
order
.
service_hours
)
self
.
fill_input_by_placeholder
(
frame
,
"请输入订单内容"
,
order
.
order_title
)
self
.
fill_number_by_placeholder
(
frame
,
"请输入价格"
,
order
.
receive_price
)
self
.
select_manual_order_game_region_service_values
(
frame
,
order
)
self
.
ensure_game_region_service_selected
(
frame
)
def
assert_order_in_pending_accept_status
(
self
,
frame
:
Frame
,
order
:
ManualOrderData
)
->
None
:
...
...
@@ -5151,6 +5154,132 @@ class WanzhangguiOrderPage(TenantAuthPage):
f
"validation_messages={self.modal_validation_messages(frame)}"
)
def
select_manual_order_game_region_service_values
(
self
,
frame
:
Frame
,
order
:
ManualOrderData
)
->
None
:
target_values
=
{
"游戏"
:
order
.
game_name
,
"区"
:
order
.
game_region
,
"服"
:
order
.
game_server
,
"服务项目"
:
order
.
service_project
,
}
for
field
,
value
in
target_values
.
items
():
if
not
value
:
continue
selected
=
self
.
select_manual_order_game_region_field_value
(
frame
,
field
,
value
)
assert
selected
,
(
f
"手工录单未能选择{field}={value};status={self.manual_order_game_region_service_status(frame)}; "
f
"options={self.visible_dropdown_options(frame)}; validation_messages={self.modal_validation_messages(frame)}"
)
self
.
page
.
wait_for_timeout
(
900
)
def
select_manual_order_game_region_field_value
(
self
,
frame
:
Frame
,
field
:
str
,
value
:
str
)
->
bool
:
if
self
.
select_manual_order_game_region_field_value_by_id
(
frame
,
field
,
value
):
return
True
opened
=
frame
.
evaluate
(
"""({ field }) => {
const modal = Array.from(document.querySelectorAll('.ant-modal'))
.filter(el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
}).pop();
if (!modal) return { ok: false, reason: 'no visible modal' };
const selectors = Array.from(modal.querySelectorAll('.ant-select-selector'))
.map((el, index) => ({
el,
index,
text: (el.innerText || el.textContent || '').trim(),
r: el.getBoundingClientRect(),
}))
.filter(item => item.r.width > 0 && item.r.height > 0)
.sort((a, b) => a.r.y - b.r.y || a.r.x - b.r.x);
const byY = new Map();
for (const item of selectors) {
const key = Math.round(item.r.y / 8) * 8;
byY.set(key, [...(byY.get(key) || []), item]);
}
const rows = Array.from(byY.values()).map(items => items.sort((a, b) => a.r.x - b.r.x));
const row = rows.find(items => {
if (items.length < 4) return false;
const text = items.map(item => item.text).join('|');
return /王者|WeGame|默认服|游戏|服务项目|区|服/.test(text);
});
if (!row) return { ok: false, reason: 'game row not found', selectors: selectors.map(item => `${item.index}:${item.text}`) };
const index = { '游戏': 0, '区': 1, '服': 2, '服务项目': 3 }[field];
const selector = row[index];
if (!selector) return { ok: false, reason: `selector not found: ${field}`, row: row.map(item => item.text) };
selector.el.click();
return { ok: true, before: selector.text, row: row.map(item => item.text) };
}"""
,
{
"field"
:
field
},
)
if
not
opened
.
get
(
"ok"
):
return
False
self
.
page
.
wait_for_timeout
(
700
)
clicked
=
self
.
click_dropdown_option_by_text
(
frame
,
value
)
self
.
page
.
wait_for_timeout
(
700
)
return
clicked
def
select_manual_order_game_region_field_value_by_id
(
self
,
frame
:
Frame
,
field
:
str
,
value
:
str
)
->
bool
:
selector_by_field
=
{
"游戏"
:
"#gameId"
,
"区"
:
"#gameRegion"
,
"服"
:
"#gameServer"
,
"服务项目"
:
"#gameBisServeId"
,
}
selector
=
selector_by_field
.
get
(
field
,
""
)
if
not
selector
:
return
False
locator
=
frame
.
locator
(
selector
)
if
locator
.
count
()
==
0
:
return
False
try
:
locator
.
first
.
click
(
force
=
True
,
timeout
=
3000
)
self
.
page
.
wait_for_timeout
(
500
)
if
field
in
{
"游戏"
,
"服务项目"
}:
try
:
locator
.
first
.
fill
(
value
,
timeout
=
3000
)
self
.
page
.
wait_for_timeout
(
500
)
except
Exception
:
pass
clicked
=
self
.
click_dropdown_option_by_text
(
frame
,
value
)
if
clicked
:
self
.
page
.
wait_for_timeout
(
700
)
return
True
except
Exception
:
return
False
return
False
def
click_dropdown_option_by_text
(
self
,
frame
:
Frame
,
option_text
:
str
)
->
bool
:
clicked
=
frame
.
evaluate
(
"""optionText => {
const normalized = text => String(text || '').replace(/
\\
s+/g, '');
const targetText = normalized(optionText);
const options = Array.from(document.querySelectorAll(
'.ant-select-dropdown:not(.ant-select-dropdown-hidden) ' +
'.ant-select-item-option:not(.ant-select-item-option-disabled), ' +
'.ant-cascader-menu-item, [role="option"]'
)).map(el => {
const textEl = el.querySelector('.ant-select-item-option-content') || el;
const text = (textEl.innerText || textEl.textContent || '').trim();
const r = el.getBoundingClientRect();
return { el, text, normalizedText: normalized(text), r };
}).filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text && item.text !== 'No data' && !item.text.includes('请选择'));
const exact = options.find(item => item.normalizedText === targetText);
const fuzzy = options.find(item =>
item.normalizedText.includes(targetText) || targetText.includes(item.normalizedText)
);
const target = exact || fuzzy;
if (!target) return false;
target.el.click();
return true;
}"""
,
option_text
,
)
if
not
clicked
:
self
.
page
.
keyboard
.
press
(
"Escape"
)
self
.
page
.
wait_for_timeout
(
300
)
return
bool
(
clicked
)
def
manual_order_game_region_service_status
(
self
,
frame
:
Frame
)
->
dict
:
return
dict
(
frame
.
evaluate
(
...
...
@@ -10108,6 +10237,276 @@ class WanyoujiFulfillmentPage(TenantAuthPage):
self
.
page
.
wait_for_timeout
(
1000
)
return
bool
(
clicked
)
def
ensure_auto_acceptance_private_order_rules
(
self
,
*
,
merchant_name
:
str
,
game_name
:
str
,
service_project
:
str
,
max_private_order_count
:
str
=
"800"
,
)
->
str
:
self
.
ensure_auto_accept_assignment
(
merchant_name
,
enabled
=
True
)
frame
=
self
.
open_auto_accept_assignment_config
()
self
.
search_auto_accept_assignment
(
frame
,
merchant_name
)
row_text
=
self
.
auto_accept_assignment_row_text
(
frame
,
merchant_name
)
assert
self
.
auto_accept_assignment_enabled
(
frame
,
merchant_name
),
(
f
"智能接单配置商家自动接指派单未开启;merchant={merchant_name}; row_text={row_text}"
)
clicked
=
self
.
click_workshop_acceptance_profile_edit
(
frame
)
assert
clicked
,
(
f
"智能接单配置页未找到上方【编辑画像】入口;merchant={merchant_name}; row_text={row_text}; "
f
"text={frame.locator('body').inner_text(timeout=5000)[:1500]}"
)
self
.
page
.
wait_for_timeout
(
1500
)
editor_text
=
self
.
visible_acceptance_profile_editor_text
(
frame
)
assert
editor_text
,
(
f
"点击【编辑画像】后未打开画像编辑弹窗/抽屉;merchant={merchant_name}; "
f
"text={frame.locator('body').inner_text(timeout=5000)[:1500]}"
)
self
.
ensure_auto_acceptance_combo_value
(
frame
,
[
"接单游戏"
,
"游戏"
],
game_name
)
self
.
ensure_auto_acceptance_combo_value
(
frame
,
[
"服务项目"
,
"接单服务项目"
],
service_project
)
private_count_filled
=
self
.
fill_auto_acceptance_config_input
(
frame
,
[
"工作室每日私单最大接单量"
,
"每日私单最大接单量"
,
"私单最大接单量"
,
"最大接单量"
],
max_private_order_count
,
)
assert
private_count_filled
,
(
f
"智能接单配置弹窗未找到每日私单最大接单量输入框;merchant={merchant_name}; "
f
"modal={self.visible_modal_text(frame)[:1500]}"
)
saved
=
self
.
click_acceptance_profile_editor_button
(
frame
,
[
"保 存"
,
"保存"
,
"确 定"
,
"确定"
,
"提交"
])
assert
saved
,
f
"智能接单画像编辑弹窗/抽屉未找到保存/确定按钮;panel={self.visible_acceptance_profile_editor_text(frame)[:1500]}"
self
.
page
.
wait_for_timeout
(
2500
)
self
.
search_auto_accept_assignment
(
frame
,
merchant_name
)
final_row_text
=
self
.
auto_accept_assignment_row_text
(
frame
,
merchant_name
)
assert
self
.
auto_accept_assignment_enabled
(
frame
,
merchant_name
),
(
f
"智能接单配置保存后自动接指派单未保持开启;merchant={merchant_name}; row_text={final_row_text}"
)
return
final_row_text
def
click_workshop_acceptance_profile_edit
(
self
,
frame
:
Frame
)
->
bool
:
clicked
=
frame
.
evaluate
(
"""() => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const nodes = Array.from(document.querySelectorAll('button, a, [role="button"], span, div'))
.map(el => ({
el,
clickable: el.closest('button, a, [role="button"]') || el,
text: (el.innerText || el.textContent || '').trim(),
r: el.getBoundingClientRect(),
}))
.filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text === '编辑画像' || item.text.includes('编辑画像'));
const target = nodes.sort((a, b) => (a.r.width * a.r.height) - (b.r.width * b.r.height))[0];
if (!target) return false;
target.clickable.click();
return true;
}"""
)
if
clicked
:
self
.
page
.
wait_for_timeout
(
1000
)
return
bool
(
clicked
)
def
visible_acceptance_profile_editor_text
(
self
,
frame
:
Frame
)
->
str
:
script
=
"""() => {
const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer'))
.filter(el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
});
const root = roots.pop();
return root ? (root.innerText || root.textContent || '') : '';
}"""
text
=
str
(
frame
.
evaluate
(
script
))
if
text
:
return
text
return
str
(
self
.
page
.
evaluate
(
script
))
def
click_acceptance_profile_editor_button
(
self
,
frame
:
Frame
,
texts
:
list
[
str
])
->
bool
:
script
=
"""texts => {
const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer, .ant-popover, .ant-popconfirm'))
.filter(el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
});
const root = roots.pop();
if (!root) return false;
const buttons = Array.from(root.querySelectorAll('button, a, [role="button"]'))
.map(el => ({ el, text: (el.innerText || el.textContent || '').trim(), disabled: el.disabled, r: el.getBoundingClientRect() }))
.filter(item => item.r.width > 0 && item.r.height > 0 && !item.disabled);
for (const text of texts) {
const normalized = String(text || '').replace(/
\\
s+/g, '');
const target = buttons.find(item => item.text === text) ||
buttons.find(item => item.text.replace(/
\\
s+/g, '') === normalized) ||
buttons.find(item => item.text.includes(text) || item.text.replace(/
\\
s+/g, '').includes(normalized));
if (target) {
target.el.click();
return true;
}
}
return false;
}"""
clicked
=
frame
.
evaluate
(
script
,
texts
)
if
not
clicked
:
clicked
=
self
.
page
.
evaluate
(
script
,
texts
)
if
clicked
:
self
.
page
.
wait_for_timeout
(
1000
)
return
bool
(
clicked
)
def
click_auto_accept_assignment_switch_detail
(
self
,
frame
:
Frame
,
merchant_name
:
str
)
->
bool
:
clicked
=
frame
.
evaluate
(
"""merchantName => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const rows = Array.from(document.querySelectorAll('tbody tr, .ant-table-row, [class*="table"] [class*="row"]'))
.map(row => ({ row, text: (row.innerText || row.textContent || '').trim(), r: row.getBoundingClientRect() }))
.filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text.includes(merchantName));
const row = rows[0]?.row;
if (!row) return false;
const actionNodes = Array.from(row.querySelectorAll('button, a, [role="button"], span, div'))
.map(el => ({
el,
clickable: el.closest('button, a, [role="button"]') || el,
text: (el.innerText || el.textContent || '').trim(),
r: el.getBoundingClientRect(),
}))
.filter(item => item.r.width > 0 && item.r.height > 0);
const target = actionNodes.find(item => /编辑|配置|调整|设置|修改|详情/.test(item.text));
if (!target) return false;
target.clickable.click();
return true;
}"""
,
merchant_name
,
)
self
.
page
.
wait_for_timeout
(
1000
)
return
bool
(
clicked
)
def
ensure_auto_acceptance_combo_value
(
self
,
frame
:
Frame
,
label_texts
:
list
[
str
],
option_text
:
str
)
->
None
:
if
not
option_text
:
return
if
self
.
auto_acceptance_modal_contains
(
frame
,
option_text
):
return
selected
=
False
for
label_text
in
label_texts
:
if
self
.
select_auto_acceptance_config_option
(
frame
,
label_text
,
option_text
):
selected
=
True
break
assert
selected
or
self
.
auto_acceptance_modal_contains
(
frame
,
option_text
),
(
f
"智能接单配置弹窗未能选择配置项;labels={label_texts}; option={option_text}; "
f
"panel={(self.visible_modal_text(frame) or self.visible_acceptance_profile_editor_text(frame))[:1500]}"
)
def
auto_acceptance_modal_contains
(
self
,
frame
:
Frame
,
text
:
str
)
->
bool
:
modal_text
=
self
.
visible_modal_text
(
frame
)
or
self
.
visible_acceptance_profile_editor_text
(
frame
)
return
bool
(
text
and
text
in
modal_text
)
def
fill_auto_acceptance_config_input
(
self
,
frame
:
Frame
,
label_texts
:
list
[
str
],
value
:
str
)
->
bool
:
filled
=
frame
.
evaluate
(
"""({ labelTexts, value }) => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer, body')).filter(visible);
const root = roots[0] || document;
const setValue = input => {
input.focus();
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
setter.call(input, value);
input.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: value }));
input.dispatchEvent(new Event('change', { bubbles: true }));
input.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
return true;
};
const normalizedLabels = labelTexts.map(item => String(item || '').replace(/
\\
s+/g, ''));
const controls = Array.from(root.querySelectorAll('input'))
.filter(input => visible(input) && !input.disabled && input.getAttribute('type') !== 'hidden')
.map(input => ({
input,
placeholder: (input.getAttribute('placeholder') || '').replace(/
\\
s+/g, ''),
text: ((input.closest('.ant-form-item, [class*="form-item"], .ant-row, tr, [class*="field"]') || root).innerText || '').replace(/
\\
s+/g, ''),
}));
const exact = controls.find(item =>
normalizedLabels.some(label => item.placeholder.includes(label) || item.text.includes(label))
);
if (exact) return setValue(exact.input);
const numberInput = controls.find(item => item.input.getAttribute('type') === 'number');
if (numberInput) return setValue(numberInput.input);
return false;
}"""
,
{
"labelTexts"
:
label_texts
,
"value"
:
value
},
)
self
.
page
.
wait_for_timeout
(
500
)
return
bool
(
filled
)
def
select_auto_acceptance_config_option
(
self
,
frame
:
Frame
,
label_text
:
str
,
option_text
:
str
)
->
bool
:
opened
=
frame
.
evaluate
(
"""({ labelText }) => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer, body')).filter(visible);
const root = roots[0] || document;
const normalizedLabel = String(labelText || '').replace(/
\\
s+/g, '');
const fields = Array.from(root.querySelectorAll('.ant-form-item, [class*="form-item"], .ant-row, tr, [class*="field"], div'))
.map(el => ({ el, text: (el.innerText || el.textContent || '').replace(/
\\
s+/g, ''), r: el.getBoundingClientRect() }))
.filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text.includes(normalizedLabel))
.sort((a, b) => (a.r.width * a.r.height) - (b.r.width * b.r.height));
const field = fields[0]?.el;
if (!field) return false;
const selector = Array.from(field.querySelectorAll('.ant-select-selector, [class*="select-selector"], input'))
.find(visible);
if (!selector) return false;
const clickable = selector.closest('.ant-select, [class*="select"]') || selector;
clickable.click();
return true;
}"""
,
{
"labelText"
:
label_text
},
)
if
not
opened
:
return
False
self
.
page
.
wait_for_timeout
(
800
)
clicked
=
frame
.
evaluate
(
"""optionText => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const normalizedOption = String(optionText || '').replace(/
\\
s+/g, '');
const options = Array.from(document.querySelectorAll(
'.ant-select-dropdown:not(.ant-select-dropdown-hidden) .ant-select-item-option, .ant-cascader-menu-item, [role="option"], li, div, span'
))
.map(el => ({
el,
clickable: el.closest('.ant-select-item-option, .ant-cascader-menu-item, [role="option"], li') || el,
text: (el.innerText || el.textContent || '').replace(/
\\
s+/g, ''),
r: el.getBoundingClientRect(),
}))
.filter(item => item.r.width > 0 && item.r.height > 0);
const target = options.find(item => item.text === normalizedOption) ||
options.find(item => item.text.includes(normalizedOption) || normalizedOption.includes(item.text));
if (!target) return false;
target.clickable.click();
return true;
}"""
,
option_text
,
)
self
.
page
.
wait_for_timeout
(
800
)
return
bool
(
clicked
)
def
open_workshop_appeal_work_order
(
self
)
->
Frame
:
self
.
goto
(
WANYOUJI_CONSOLE_URL
)
self
.
wait_for_enterprise_console_shell
()
...
...
e2e/tests/智能接单/test_e2e_auto_acceptance_config_rules.py
0 → 100644
View file @
f825d854
from
__future__
import
annotations
import
os
from
dataclasses
import
dataclass
from
datetime
import
datetime
import
pytest
from
playwright.sync_api
import
Page
from
e2e.pages.wanzhanggui_order_page
import
ManualOrderData
,
WanyoujiFulfillmentPage
,
WanzhangguiOrderPage
from
e2e.utils.account_store
import
account_store
@
dataclass
(
frozen
=
True
)
class
AutoAcceptanceConfigCase
:
case_id
:
str
wanzhanggui_phone
:
str
wanyouji_phone
:
str
merchant_name
:
str
workshop_name
:
str
strategy_name
:
str
strategy_type
:
str
game_name
:
str
game_region
:
str
game_server
:
str
service_project
:
str
max_private_order_count
:
str
def
first_config_case
(
settings
)
->
AutoAcceptanceConfigCase
:
return
AutoAcceptanceConfigCase
(
case_id
=
"AUTO-ACCEPT-CONFIG-001"
,
wanzhanggui_phone
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_WANZHANGGUI_PHONE"
,
"17788888888"
)
.
strip
(),
wanyouji_phone
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_WANYOUJI_PHONE"
,
"18800000001"
)
.
strip
(),
merchant_name
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_MERCHANT"
,
"测试001"
)
.
strip
(),
workshop_name
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_WORKSHOP"
,
"旺仔工作室"
)
.
strip
(),
strategy_name
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_STRATEGY"
,
"指定-旺仔"
)
.
strip
(),
strategy_type
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_STRATEGY_TYPE"
,
"单平台指定"
)
.
strip
(),
game_name
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_GAME"
,
"王者"
)
.
strip
(),
game_region
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_GAME_REGION"
,
"WeGame"
)
.
strip
(),
game_server
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_GAME_SERVER"
,
"微信2区-国士无双"
)
.
strip
(),
service_project
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_SERVICE_PROJECT"
,
"排位"
)
.
strip
(),
max_private_order_count
=
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_MAX_PRIVATE_ORDER_COUNT"
,
"800"
)
.
strip
(),
)
@
pytest
.
mark
.
e2e_auto_acceptance
@
pytest
.
mark
.
e2e_ledger
@
pytest
.
mark
.
e2e_chain
def
test_auto_acceptance_config_001_private_order_rules_positive
(
page
:
Page
,
settings
,
bug_reporter
,
dual_account_pages
,
)
->
None
:
case
=
first_config_case
(
settings
)
store
=
account_store
()
wanzhanggui_account
=
store
.
find
(
phone
=
case
.
wanzhanggui_phone
)
wanyouji_account
=
store
.
find
(
phone
=
case
.
wanyouji_phone
)
assert
wanzhanggui_account
is
not
None
,
f
"台账中未找到丸掌柜账号:{case.wanzhanggui_phone}"
assert
wanyouji_account
is
not
None
,
f
"台账中未找到丸友集账号:{case.wanyouji_phone}"
assert
wanzhanggui_account
.
wanzhanggui_status
==
"opened"
,
(
f
"丸掌柜账号未开通;phone={case.wanzhanggui_phone}; status={wanzhanggui_account.wanzhanggui_status}"
)
assert
wanyouji_account
.
wanyouji_status
==
"opened"
,
(
f
"丸友集账号未开通;phone={case.wanyouji_phone}; status={wanyouji_account.wanyouji_status}"
)
wanzhanggui_page
,
wanyouji_page
=
dual_account_pages
.
pair
(
case
.
wanzhanggui_phone
,
case
.
wanyouji_phone
)
order_page
=
WanzhangguiOrderPage
(
wanzhanggui_page
,
settings
.
tenant_home_url
,
bug_reporter
)
fulfillment_page
=
WanyoujiFulfillmentPage
(
wanyouji_page
,
settings
.
tenant_home_url
,
bug_reporter
)
order_page
.
login_main_account
(
case
.
wanzhanggui_phone
,
wanzhanggui_account
.
password
)
order_page
.
ensure_workshop_guarantee
(
case
.
workshop_name
,
enabled
=
False
)
bug_reporter
.
record_if_errors
(
account
=
case
.
wanzhanggui_phone
,
location
=
f
"{case.case_id} 发单前关闭工作室担保 {case.workshop_name}"
,
)
fulfillment_page
.
login_main_account
(
case
.
wanyouji_phone
,
wanyouji_account
.
password
)
fulfillment_page
.
ensure_auto_acceptance_private_order_rules
(
merchant_name
=
case
.
merchant_name
,
game_name
=
case
.
game_name
,
service_project
=
case
.
service_project
,
max_private_order_count
=
case
.
max_private_order_count
,
)
bug_reporter
.
record_if_errors
(
account
=
case
.
wanyouji_phone
,
location
=
(
f
"{case.case_id} 通过编辑画像配置智能接单:商家开关开启,游戏+服务项目同组合命中,"
f
"每日私单最大接单量={case.max_private_order_count}"
),
)
timestamp
=
datetime
.
now
()
.
strftime
(
"
%
m
%
d
%
H
%
M
%
S"
)
source_order_no
=
(
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_SOURCE_ORDER_NO"
,
""
)
.
strip
()
or
f
"AACFG{timestamp}"
)
order_title
=
(
os
.
getenv
(
"E2E_AUTO_ACCEPT_CONFIG_ORDER_TITLE"
,
""
)
.
strip
()
or
f
"E2E智能接单配置{timestamp}"
)
order
=
ManualOrderData
(
source_order_no
=
source_order_no
,
order_title
=
order_title
,
sub_order_title
=
f
"{order_title}私单配置准入"
,
strategy_name
=
case
.
strategy_name
,
strategy_type
=
case
.
strategy_type
,
game_name
=
case
.
game_name
,
game_region
=
case
.
game_region
,
game_server
=
case
.
game_server
,
service_project
=
case
.
service_project
,
role_name
=
f
"AACFG角色{timestamp[-4:]}"
,
)
order_page
.
login_main_account
(
case
.
wanzhanggui_phone
,
wanzhanggui_account
.
password
)
order_page
.
create_manual_order
(
order
)
bug_reporter
.
record_if_errors
(
account
=
case
.
wanzhanggui_phone
,
location
=
(
f
"{case.case_id} 丸掌柜创建匹配游戏+服务项目的私单并推送目标工作室:"
f
"{source_order_no}/{order_title}"
),
)
row_text
=
order_page
.
refresh_order_list_and_get_row_text
(
source_order_no
,
order_title
)
assert
"代练中"
in
row_text
,
(
"满足商家自动接指派单开启、游戏+服务项目同组合命中、最大接单量800后,"
f
"丸掌柜订单未自动进入代练中;source_order_no={source_order_no}; row_text={row_text[:1500]}"
)
fulfillment_page
.
login_main_account
(
case
.
wanyouji_phone
,
wanyouji_account
.
password
)
accepted_row_text
=
fulfillment_page
.
verify_workshop_order_list_status
(
source_order_no
,
order_title
,
[
"已接单"
,
"接单"
],
)
bug_reporter
.
record_if_errors
(
account
=
case
.
wanyouji_phone
,
location
=
f
"{case.case_id} 丸友集订单列表校验自动接单成功:{source_order_no}/{order_title}"
,
)
store
.
mark_order_dispatched
(
wanzhanggui_phone
=
case
.
wanzhanggui_phone
,
source_order_no
=
source_order_no
,
order_title
=
order_title
,
strategy_name
=
case
.
strategy_name
,
strategy_type
=
case
.
strategy_type
,
wanyouji_phones
=
[
case
.
wanyouji_phone
],
)
store
.
mark_task_order_status
(
source_order_no
=
source_order_no
,
status
=
"task_accepted"
,
task_accept_scope
=
"已接单"
,
task_wanyouji_phone
=
case
.
wanyouji_phone
,
)
assert
source_order_no
in
accepted_row_text
or
order_title
in
accepted_row_text
e2e/tests/智能接单/智能接单测试用例_配置准入补充_20260708.xlsx
0 → 100644
View file @
f825d854
File added
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment