tests: cover nested zhihu creator write entry
This commit is contained in:
@@ -25,36 +25,107 @@ def run_open_creator_entry(*, body_text: str, selectors: dict[str, list[dict]])
|
|||||||
|
|
||||||
function createNode(spec) {{
|
function createNode(spec) {{
|
||||||
const node = {{
|
const node = {{
|
||||||
|
id: String(spec?.id ?? ''),
|
||||||
tagName: String(spec?.tagName || 'DIV').toUpperCase(),
|
tagName: String(spec?.tagName || 'DIV').toUpperCase(),
|
||||||
textContent: String(spec?.textContent ?? ''),
|
textContent: String(spec?.textContent ?? ''),
|
||||||
innerText: String(spec?.innerText ?? spec?.textContent ?? ''),
|
innerText: String(spec?.innerText ?? spec?.textContent ?? ''),
|
||||||
href: String(spec?.href ?? ''),
|
href: String(spec?.href ?? ''),
|
||||||
|
className: String(spec?.className ?? ''),
|
||||||
|
role: String(spec?.role ?? ''),
|
||||||
|
tabIndex: Number.isFinite(spec?.tabIndex) ? Number(spec.tabIndex) : -1,
|
||||||
clicked: false,
|
clicked: false,
|
||||||
click() {{
|
click() {{
|
||||||
this.clicked = true;
|
this.clicked = true;
|
||||||
}},
|
}},
|
||||||
|
getAttribute(name) {{
|
||||||
|
if (name === 'class') {{
|
||||||
|
return this.className;
|
||||||
|
}}
|
||||||
|
if (name === 'role') {{
|
||||||
|
return this.role;
|
||||||
|
}}
|
||||||
|
if (name === 'href') {{
|
||||||
|
return this.href;
|
||||||
|
}}
|
||||||
|
if (name === 'tabindex' && this.tabIndex >= 0) {{
|
||||||
|
return String(this.tabIndex);
|
||||||
|
}}
|
||||||
|
return '';
|
||||||
|
}},
|
||||||
getBoundingClientRect() {{
|
getBoundingClientRect() {{
|
||||||
return {{
|
return {{
|
||||||
width: spec?.visible === false ? 0 : 120,
|
width: spec?.visible === false ? 0 : 120,
|
||||||
height: spec?.visible === false ? 0 : 32,
|
height: spec?.visible === false ? 0 : 32,
|
||||||
}};
|
}};
|
||||||
}},
|
}},
|
||||||
|
parentElement: null,
|
||||||
|
closest(selector) {{
|
||||||
|
let current = this;
|
||||||
|
while (current) {{
|
||||||
|
if (matchesSelector(current, selector)) {{
|
||||||
|
return current;
|
||||||
|
}}
|
||||||
|
current = current.parentElement;
|
||||||
|
}}
|
||||||
|
return null;
|
||||||
|
}},
|
||||||
}};
|
}};
|
||||||
return node;
|
return node;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
const created = new Map();
|
const created = new Map();
|
||||||
|
const nodesById = new Map();
|
||||||
|
function matchesSelector(node, selector) {{
|
||||||
|
const parts = selector.split(',').map((part) => part.trim()).filter(Boolean);
|
||||||
|
return parts.some((part) => {{
|
||||||
|
if (part === 'a[href]') {{
|
||||||
|
return node.tagName === 'A' && Boolean(node.href);
|
||||||
|
}}
|
||||||
|
if (part === 'button') {{
|
||||||
|
return node.tagName === 'BUTTON';
|
||||||
|
}}
|
||||||
|
if (part === '[role=\"button\"]' || part === "[role='button']") {{
|
||||||
|
return node.role === 'button';
|
||||||
|
}}
|
||||||
|
if (part === '[tabindex]') {{
|
||||||
|
return node.tabIndex >= 0;
|
||||||
|
}}
|
||||||
|
if (part === 'div') {{
|
||||||
|
return node.tagName === 'DIV';
|
||||||
|
}}
|
||||||
|
if (part === 'span') {{
|
||||||
|
return node.tagName === 'SPAN';
|
||||||
|
}}
|
||||||
|
return false;
|
||||||
|
}});
|
||||||
|
}}
|
||||||
function createNodeList(selector) {{
|
function createNodeList(selector) {{
|
||||||
const specs = selectorMap[selector] || [];
|
const specs = selectorMap[selector] || [];
|
||||||
return specs.map((spec, index) => {{
|
return specs.map((spec, index) => {{
|
||||||
const key = `${{selector}}#${{index}}`;
|
const key = `${{selector}}#${{index}}`;
|
||||||
if (!created.has(key)) {{
|
if (!created.has(key)) {{
|
||||||
created.set(key, createNode(spec));
|
const node = createNode(spec);
|
||||||
|
created.set(key, node);
|
||||||
|
if (node.id) {{
|
||||||
|
nodesById.set(node.id, node);
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
return created.get(key);
|
return created.get(key);
|
||||||
}});
|
}});
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
for (const selector of Object.keys(selectorMap)) {{
|
||||||
|
createNodeList(selector);
|
||||||
|
}}
|
||||||
|
for (const node of created.values()) {{
|
||||||
|
const parentId = selectorMap && Object.values(selectorMap)
|
||||||
|
.flat()
|
||||||
|
.find((spec) => String(spec?.id ?? '') === node.id)?.parentId;
|
||||||
|
if (parentId && nodesById.has(parentId)) {{
|
||||||
|
node.parentElement = nodesById.get(parentId);
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
const bodyNode = createNode({{ tagName: 'BODY', textContent: bodyText, innerText: bodyText }});
|
const bodyNode = createNode({{ tagName: 'BODY', textContent: bodyText, innerText: bodyText }});
|
||||||
const context = {{
|
const context = {{
|
||||||
args: {{ desired_target: 'article_editor' }},
|
args: {{ desired_target: 'article_editor' }},
|
||||||
@@ -141,6 +212,32 @@ class SkillScriptZhihuNavigateTest(unittest.TestCase):
|
|||||||
self.assertEqual(payload["result"]["status"], "creator_entry_clicked")
|
self.assertEqual(payload["result"]["status"], "creator_entry_clicked")
|
||||||
self.assertTrue(payload["created"]["a[href], button, [role='button']#0"]["clicked"])
|
self.assertTrue(payload["created"]["a[href], button, [role='button']#0"]["clicked"])
|
||||||
|
|
||||||
|
def test_open_creator_entry_clicks_clickable_ancestor_for_nested_write_text(self):
|
||||||
|
payload = run_open_creator_entry(
|
||||||
|
body_text="创作者中心 写文章",
|
||||||
|
selectors={
|
||||||
|
"a[href], button, [role='button']": [],
|
||||||
|
"div, span, [tabindex]": [
|
||||||
|
{
|
||||||
|
"id": "ancestor",
|
||||||
|
"tagName": "div",
|
||||||
|
"className": "creator-entry",
|
||||||
|
"tabIndex": 0,
|
||||||
|
"textContent": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "label",
|
||||||
|
"parentId": "ancestor",
|
||||||
|
"tagName": "span",
|
||||||
|
"textContent": "写文章",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(payload["result"]["status"], "creator_entry_clicked")
|
||||||
|
self.assertTrue(payload["created"]["div, span, [tabindex]#0"]["clicked"])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user