11package cc.unitmesh.server.cli
22
3- import cc.unitmesh.agent.e2etest.planner.PlannerConfig
4- import cc.unitmesh.agent.e2etest.planner.TestActionPlanner
3+ import cc.unitmesh.e2e.dsl.E2EDslGenerator
4+ import cc.unitmesh.e2e.dsl.E2EDslIntegration
55import cc.unitmesh.llm.LLMProviderType
66import cc.unitmesh.llm.LLMService
77import cc.unitmesh.llm.ModelConfig
@@ -66,18 +66,16 @@ object E2ECli {
6666 println ()
6767
6868 val llmService = LLMService .create(modelConfig)
69- val planner = TestActionPlanner (llmService, PlannerConfig (useDslFormat = true ))
69+ val dslIntegration = E2EDslIntegration (llmService)
70+ val dslGenerator = E2EDslGenerator ()
7071
71- println (" 🧠 Generating E2E test scenario..." )
72+ println (" 🧠 Generating E2E test scenario from description ..." )
7273 println ()
7374
74- // Create a mock page state for scenario generation
75- val mockPageState = createMockPageState(targetUrl)
76-
77- val scenario = planner.generateScenario(
75+ // Generate scenario directly from description - no page state needed
76+ val scenario = dslIntegration.generateScenarioFromDescription(
7877 description = testGoal,
79- startUrl = targetUrl,
80- pageState = mockPageState
78+ startUrl = targetUrl
8179 )
8280
8381 val totalTime = System .currentTimeMillis() - startTime
@@ -90,12 +88,12 @@ object E2ECli {
9088 println (" =" .repeat(80 ))
9189 println ()
9290
93- val dsl = generateDsl (scenario)
91+ val dsl = dslGenerator.generate (scenario)
9492 println (dsl)
9593
9694 // Save to file if specified
9795 if (outputFile != null ) {
98- java.io. File (outputFile).writeText(dsl)
96+ File (outputFile).writeText(dsl)
9997 println ()
10098 println (" 💾 Saved to: $outputFile " )
10199 }
@@ -184,157 +182,5 @@ object E2ECli {
184182 maxTokens = 4096
185183 )
186184 }
187-
188- /* *
189- * Create a mock page state for scenario generation.
190- * In a real implementation, this would use Playwright to extract actual page state.
191- */
192- private fun createMockPageState (url : String ): cc.unitmesh.agent.e2etest.model.PageState {
193- val defaultBoundingBox = cc.unitmesh.agent.e2etest.model.BoundingBox (0.0 , 0.0 , 100.0 , 30.0 )
194-
195- fun createFingerprint (selector : String , tagName : String , name : String , role : String ) =
196- cc.unitmesh.agent.e2etest.model.ElementFingerprint (
197- selector = selector,
198- tagName = tagName,
199- textContent = name,
200- role = role
201- )
202-
203- return cc.unitmesh.agent.e2etest.model.PageState (
204- url = url,
205- title = " Page at $url " ,
206- viewport = cc.unitmesh.agent.e2etest.model.Viewport (1280 , 720 ),
207- actionableElements = listOf (
208- // Common elements that might be on a page
209- cc.unitmesh.agent.e2etest.model.ActionableElement (
210- tagId = 1 ,
211- tagName = " input" ,
212- role = " textbox" ,
213- name = " username" ,
214- selector = " input[name='username']" ,
215- isVisible = true ,
216- isEnabled = true ,
217- boundingBox = defaultBoundingBox,
218- fingerprint = createFingerprint(" input[name='username']" , " input" , " username" , " textbox" )
219- ),
220- cc.unitmesh.agent.e2etest.model.ActionableElement (
221- tagId = 2 ,
222- tagName = " input" ,
223- role = " textbox" ,
224- name = " password" ,
225- selector = " input[name='password']" ,
226- isVisible = true ,
227- isEnabled = true ,
228- boundingBox = defaultBoundingBox,
229- fingerprint = createFingerprint(" input[name='password']" , " input" , " password" , " textbox" )
230- ),
231- cc.unitmesh.agent.e2etest.model.ActionableElement (
232- tagId = 3 ,
233- tagName = " button" ,
234- role = " button" ,
235- name = " Login" ,
236- selector = " button[type='submit']" ,
237- isVisible = true ,
238- isEnabled = true ,
239- boundingBox = defaultBoundingBox,
240- fingerprint = createFingerprint(" button[type='submit']" , " button" , " Login" , " button" )
241- ),
242- cc.unitmesh.agent.e2etest.model.ActionableElement (
243- tagId = 4 ,
244- tagName = " input" ,
245- role = " searchbox" ,
246- name = " search" ,
247- selector = " input[type='search']" ,
248- isVisible = true ,
249- isEnabled = true ,
250- boundingBox = defaultBoundingBox,
251- fingerprint = createFingerprint(" input[type='search']" , " input" , " search" , " searchbox" )
252- ),
253- cc.unitmesh.agent.e2etest.model.ActionableElement (
254- tagId = 5 ,
255- tagName = " button" ,
256- role = " button" ,
257- name = " Search" ,
258- selector = " button.search-btn" ,
259- isVisible = true ,
260- isEnabled = true ,
261- boundingBox = defaultBoundingBox,
262- fingerprint = createFingerprint(" button.search-btn" , " button" , " Search" , " button" )
263- )
264- ),
265- capturedAt = System .currentTimeMillis()
266- )
267- }
268-
269- /* *
270- * Generate DSL from a TestScenario
271- */
272- private fun generateDsl (scenario : cc.unitmesh.agent.e2etest.model.TestScenario ): String {
273- return buildString {
274- appendLine(" scenario \" ${scenario.name} \" {" )
275- appendLine(" description \" ${scenario.description} \" " )
276- appendLine(" url \" ${scenario.startUrl} \" " )
277- appendLine()
278-
279- scenario.steps.forEach { step ->
280- appendLine(" step \" ${step.description} \" {" )
281- appendLine(" ${formatAction(step.action)} " )
282- step.expectedOutcome?.let {
283- appendLine(" expect \" $it \" " )
284- }
285- appendLine(" }" )
286- appendLine()
287- }
288-
289- appendLine(" }" )
290- }
291- }
292-
293- private fun formatAction (action : cc.unitmesh.agent.e2etest.model.TestAction ): String {
294- return when (action) {
295- is cc.unitmesh.agent.e2etest.model.TestAction .Click -> " click #${action.targetId} "
296- is cc.unitmesh.agent.e2etest.model.TestAction .Type -> " type #${action.targetId} \" ${action.text} \" "
297- is cc.unitmesh.agent.e2etest.model.TestAction .Hover -> " hover #${action.targetId} "
298- is cc.unitmesh.agent.e2etest.model.TestAction .Scroll -> " scroll ${action.direction.name.lowercase()} "
299- is cc.unitmesh.agent.e2etest.model.TestAction .Wait -> formatWaitAction(action)
300- is cc.unitmesh.agent.e2etest.model.TestAction .PressKey -> " pressKey \" ${action.key} \" "
301- is cc.unitmesh.agent.e2etest.model.TestAction .Navigate -> " navigate \" ${action.url} \" "
302- is cc.unitmesh.agent.e2etest.model.TestAction .GoBack -> " goBack"
303- is cc.unitmesh.agent.e2etest.model.TestAction .GoForward -> " goForward"
304- is cc.unitmesh.agent.e2etest.model.TestAction .Refresh -> " refresh"
305- is cc.unitmesh.agent.e2etest.model.TestAction .Assert -> " assert #${action.targetId} ${formatAssertion(action.assertion)} "
306- is cc.unitmesh.agent.e2etest.model.TestAction .Select -> " select #${action.targetId} "
307- is cc.unitmesh.agent.e2etest.model.TestAction .UploadFile -> " uploadFile #${action.targetId} \" ${action.filePath} \" "
308- is cc.unitmesh.agent.e2etest.model.TestAction .Screenshot -> " screenshot \" ${action.name} \" "
309- }
310- }
311-
312- private fun formatWaitAction (action : cc.unitmesh.agent.e2etest.model.TestAction .Wait ): String {
313- return when (val condition = action.condition) {
314- is cc.unitmesh.agent.e2etest.model.WaitCondition .Duration -> " wait duration ${condition.ms} "
315- is cc.unitmesh.agent.e2etest.model.WaitCondition .ElementVisible -> " wait visible #${condition.targetId} "
316- is cc.unitmesh.agent.e2etest.model.WaitCondition .ElementHidden -> " wait hidden #${condition.targetId} "
317- is cc.unitmesh.agent.e2etest.model.WaitCondition .ElementEnabled -> " wait enabled #${condition.targetId} "
318- is cc.unitmesh.agent.e2etest.model.WaitCondition .TextPresent -> " wait textPresent \" ${condition.text} \" "
319- is cc.unitmesh.agent.e2etest.model.WaitCondition .UrlContains -> " wait urlContains \" ${condition.substring} \" "
320- is cc.unitmesh.agent.e2etest.model.WaitCondition .PageLoaded -> " wait pageLoaded"
321- is cc.unitmesh.agent.e2etest.model.WaitCondition .NetworkIdle -> " wait networkIdle"
322- }
323- }
324-
325- private fun formatAssertion (assertion : cc.unitmesh.agent.e2etest.model.AssertionType ): String {
326- return when (assertion) {
327- is cc.unitmesh.agent.e2etest.model.AssertionType .Visible -> " visible"
328- is cc.unitmesh.agent.e2etest.model.AssertionType .Hidden -> " hidden"
329- is cc.unitmesh.agent.e2etest.model.AssertionType .Enabled -> " enabled"
330- is cc.unitmesh.agent.e2etest.model.AssertionType .Disabled -> " disabled"
331- is cc.unitmesh.agent.e2etest.model.AssertionType .Checked -> " checked"
332- is cc.unitmesh.agent.e2etest.model.AssertionType .Unchecked -> " unchecked"
333- is cc.unitmesh.agent.e2etest.model.AssertionType .TextEquals -> " textEquals \" ${assertion.text} \" "
334- is cc.unitmesh.agent.e2etest.model.AssertionType .TextContains -> " textContains \" ${assertion.text} \" "
335- is cc.unitmesh.agent.e2etest.model.AssertionType .AttributeEquals -> " attributeEquals \" ${assertion.attribute} \" \" ${assertion.value} \" "
336- is cc.unitmesh.agent.e2etest.model.AssertionType .HasClass -> " hasClass \" ${assertion.className} \" "
337- }
338- }
339185}
340186
0 commit comments