8#include "absl/strings/ascii.h"
9#include "absl/strings/match.h"
10#include "absl/strings/str_cat.h"
11#include "absl/strings/str_format.h"
12#include "absl/strings/str_replace.h"
20 return absl::StrFormat(
"Click(%s)",
target);
22 return absl::StrFormat(
"Type(%s, \"%s\"%s)",
target,
text,
27 return absl::StrFormat(
"Assert(%s)",
condition);
29 return "Screenshot()";
35 std::string result = absl::StrCat(
"Workflow: ",
description,
"\n");
36 for (
size_t i = 0; i <
steps.size(); ++i) {
37 absl::StrAppend(&result,
" ", i + 1,
". ",
steps[i].
ToString(),
"\n");
43 const std::string& prompt) {
44 std::string normalized_prompt = absl::AsciiStrToLower(prompt);
47 std::string editor_name, input_name, text, button_name;
70 return absl::InvalidArgumentError(
71 absl::StrFormat(
"Unable to parse prompt: \"%s\"\n\n"
72 "Supported patterns:\n"
73 " - Open <Editor> editor\n"
74 " - Open <Editor> and verify it loads\n"
75 " - Type '<text>' in <input>\n"
76 " - Click <button>\n\n"
78 " - Open Overworld editor\n"
79 " - Open Dungeon editor and verify it loads\n"
80 " - Type 'zelda3.sfc' in filename input\n"
81 " - Click Open ROM button",
86 std::string* editor_name) {
88 std::regex pattern(R
"(open\s+(\w+)(?:\s+editor)?)");
90 if (std::regex_search(prompt, match, pattern) && match.size() > 1) {
91 *editor_name = match[1].str();
98 std::string* editor_name) {
100 std::regex pattern(R
"(open\s+(\w+)(?:\s+editor)?\s+and\s+verify)");
102 if (std::regex_search(prompt, match, pattern) && match.size() > 1) {
103 *editor_name = match[1].str();
110 std::string* input_name,
113 std::regex pattern(R
"(type\s+['"]([^'"]+)['"]\s+in(?:to)?\s+(\w+))");
115 if (std::regex_search(prompt, match, pattern) && match.size() > 2) {
116 *text = match[1].str();
117 *input_name = match[2].str();
124 std::string* button_name) {
126 std::regex pattern(R
"(click\s+([\w\s]+?)(?:\s+button)?\s*$)");
128 if (std::regex_search(prompt, match, pattern) && match.size() > 1) {
129 *button_name = match[1].str();
136 const std::string& name) {
137 std::string normalized =
name;
139 if (!normalized.empty()) {
140 normalized[0] = std::toupper(normalized[0]);
143 if (!absl::StrContains(absl::AsciiStrToLower(normalized),
"editor")) {
144 absl::StrAppend(&normalized,
" Editor");
150 const std::string& editor_name) {
153 TestWorkflow workflow;
154 workflow.description = absl::StrFormat(
"Open %s", normalized_name);
159 click_step.target = absl::StrFormat(
160 "button:%s", absl::StrReplaceAll(normalized_name, {{
" Editor",
""}}));
161 workflow.steps.push_back(click_step);
166 wait_step.condition = absl::StrFormat(
"window_visible:%s", normalized_name);
167 wait_step.timeout_ms = 5000;
168 workflow.steps.push_back(wait_step);
174 const std::string& editor_name) {
177 workflow.description =
181 TestStep assert_step;
183 assert_step.condition =
185 workflow.steps.push_back(assert_step);
191 const std::string& input_name,
const std::string& text) {
192 TestWorkflow workflow;
193 workflow.
description = absl::StrFormat(
"Type '%s' into %s", text, input_name);
198 click_step.target = absl::StrFormat(
"input:%s", input_name);
199 workflow.steps.push_back(click_step);
204 type_step.target = absl::StrFormat(
"input:%s", input_name);
205 type_step.text = text;
206 type_step.clear_first =
true;
207 workflow.steps.push_back(type_step);
213 const std::string& button_name) {
214 TestWorkflow workflow;
215 workflow.
description = absl::StrFormat(
"Click '%s' button", button_name);
219 click_step.target = absl::StrFormat(
"button:%s", button_name);
220 workflow.steps.push_back(click_step);
bool MatchesClickButton(const std::string &prompt, std::string *button_name)
bool MatchesTypeInput(const std::string &prompt, std::string *input_name, std::string *text)
bool MatchesOpenEditor(const std::string &prompt, std::string *editor_name)
TestWorkflow BuildOpenEditorWorkflow(const std::string &editor_name)
TestWorkflow BuildTypeInputWorkflow(const std::string &input_name, const std::string &text)
TestWorkflow BuildClickButtonWorkflow(const std::string &button_name)
bool MatchesOpenAndVerify(const std::string &prompt, std::string *editor_name)
std::string NormalizeEditorName(const std::string &name)
TestWorkflow BuildOpenAndVerifyWorkflow(const std::string &editor_name)
absl::StatusOr< TestWorkflow > GenerateWorkflow(const std::string &prompt)
Generate a test workflow from a natural language prompt.
std::string ToString() const
std::vector< TestStep > steps
std::string ToString() const