From 06cde6c6a696126d492cfb458b34f0fbd130ac2b Mon Sep 17 00:00:00 2001 From: Zhou xiao Date: Thu, 1 Aug 2024 21:29:27 +0800 Subject: [PATCH] fix(web-report): fixed the report folder issue (#22) * fix(web-report): fix report dir * chore: fix langsmith wrapper * chore: fix langsmith wrapper * chore: fix langsmith wrapper --- packages/playwright-demo/tsconfig.json | 8 +- .../ai-auto-todo.spec.ts:8(ai todo).json | 76 ++-- ...ine-order.spec.ts:10(ai online order).json | 348 ++---------------- .../src/playwright/reporter/index.ts | 2 +- .../src/playwright/reporter/util.ts | 79 ++-- 5 files changed, 106 insertions(+), 407 deletions(-) diff --git a/packages/playwright-demo/tsconfig.json b/packages/playwright-demo/tsconfig.json index f23bf8a98..45049427d 100644 --- a/packages/playwright-demo/tsconfig.json +++ b/packages/playwright-demo/tsconfig.json @@ -1,25 +1,23 @@ { "compilerOptions": { "baseUrl": ".", - "module": "NodeNext", - "types": ["node"], "declaration": true, "emitDeclarationOnly": true, "esModuleInterop": true, - "preserveSymlinks": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "jsx": "preserve", "lib": ["DOM", "ESNext"], - "moduleResolution": "NodeNext", + "moduleResolution": "node", "paths": { "@/*": ["./src/*"] }, + "target": "ES2017", "resolveJsonModule": true, "rootDir": "./", "skipLibCheck": true, "strict": true }, - "exclude": ["**/node_modules"], + "exclude": [ "node_modules"], "include": ["src", "e2e", "./playwright.config.ts", "./modern.config.ts"] } diff --git a/packages/web-integration/midscene_run/cache/ai-auto-todo.spec.ts:8(ai todo).json b/packages/web-integration/midscene_run/cache/ai-auto-todo.spec.ts:8(ai todo).json index b87c574c1..d7b7d985d 100644 --- a/packages/web-integration/midscene_run/cache/ai-auto-todo.spec.ts:8(ai todo).json +++ b/packages/web-integration/midscene_run/cache/ai-auto-todo.spec.ts:8(ai todo).json @@ -1,6 +1,6 @@ { "pkgName": "@midscene/web", - "pkgVersion": "0.1.1", + "pkgVersion": "0.1.2", "taskFile": "ai-auto-todo.spec.ts:8", "taskTitle": "ai todo", "aiTasks": [ @@ -17,21 +17,21 @@ "response": { "plans": [ { - "thought": "To create a new task, we need to locate the input box where tasks are entered.", + "thought": "The user wants to input a new task in the todo list input box and then press enter to create it. The input field is identified by its placeholder text 'What needs to be done?'.", "type": "Locate", "param": { - "prompt": "The input box with placeholder text 'What needs to be done?' located in the center of the page." + "prompt": "The input box with the placeholder text 'What needs to be done?'." } }, { - "thought": "Enter the task 'Learn JS today' in the located input box.", + "thought": "Once the input box is located, we need to enter the task description.", "type": "Input", "param": { "value": "Learn JS today" } }, { - "thought": "Press Enter to create the new task.", + "thought": "After entering the task, we need to commit it by pressing 'Enter'.", "type": "KeyboardPress", "param": { "value": "Enter" @@ -49,11 +49,11 @@ "height": 720 } }, - "prompt": "The input box with placeholder text 'What needs to be done?' located in the center of the page.", + "prompt": "The input box with the placeholder text 'What needs to be done?'.", "response": { "elements": [ { - "reason": "The input box with the placeholder text 'What needs to be done?' located in the center of the page matches the description.", + "reason": "The element with ID '3530a9c1eb' is an INPUT Node. Its placeholder text is 'What needs to be done?', which matches the user's description.", "text": "What needs to be done?", "id": "3530a9c1eb" } @@ -74,14 +74,14 @@ "response": { "plans": [ { - "thought": "First, we locate the task input box to add a new task.", + "thought": "The user wants to input a new task and hit enter for creation. First, we need to locate the task input box.", "type": "Locate", "param": { - "prompt": "The input box with the placeholder 'What needs to be done?' positioned near the top center of the page." + "prompt": "The input box with placeholder text 'What needs to be done?'" } }, { - "thought": "Entering the task details 'Learn Rust tomorrow' into the input box.", + "thought": "Typing 'Learn Rust tomorrow' into the task input box.", "type": "Input", "param": { "value": "Learn Rust tomorrow" @@ -106,11 +106,11 @@ "height": 720 } }, - "prompt": "The input box with the placeholder 'What needs to be done?' positioned near the top center of the page.", + "prompt": "The input box with placeholder text 'What needs to be done?'", "response": { "elements": [ { - "reason": "The input box with the placeholder 'What needs to be done?' positioned near the top center of the page matches the element with ID '3530a9c1eb'. This element is an INPUT Node with the specified placeholder.", + "reason": "The element is an input node with the placeholder text 'What needs to be done?' located at 366px from the left and 130px from the top.", "text": "What needs to be done?", "id": "3530a9c1eb" } @@ -131,21 +131,21 @@ "response": { "plans": [ { - "thought": "进入新任务的输入框,键入\"Learning AI the day after tomorrow\",然后按回车键。", + "thought": "Focusing on the input task box based on its placeholder text.", "type": "Locate", "param": { - "prompt": "The text input box with placeholder 'What needs to be done?'" + "prompt": "The input box with placeholder text 'What needs to be done?' near the top center of the page." } }, { - "thought": "找到输入框后,可以输入内容。", + "thought": "Entering the desired task text into the located input box.", "type": "Input", "param": { "value": "Learning AI the day after tomorrow" } }, { - "thought": "输入完成后,点击回车键以创建新任务。", + "thought": "Pressing the Enter key to add the new task to the list.", "type": "KeyboardPress", "param": { "value": "Enter" @@ -163,11 +163,11 @@ "height": 720 } }, - "prompt": "The text input box with placeholder 'What needs to be done?'", + "prompt": "The input box with placeholder text 'What needs to be done?' near the top center of the page.", "response": { "elements": [ { - "reason": "This input element matches the description 'text input box with placeholder What needs to be done?', it has the attribute 'placeholder' with the value 'What needs to be done?'", + "reason": "The element matches the description as it is an input box with the placeholder text 'What needs to be done?' near the top center of the page.", "text": "What needs to be done?", "id": "3530a9c1eb" } @@ -188,26 +188,26 @@ "response": { "plans": [ { - "thought": "The task involves interacting with the second item on the task list, specifically hovering over and clicking the Delete button.", + "thought": "First, I need to locate the second task, which is 'Learn Rust tomorrow'.", "type": "Locate", "param": { - "prompt": "The second task item with content 'Learn Rust tomorrow'" + "prompt": "The task with the text 'Learn Rust tomorrow'" } }, { - "thought": "Hover over the located element to make the Delete button visible.", + "thought": "Hover over the second task to reveal the Delete button.", "type": "Hover", "param": null }, { - "thought": "Locate the Delete button next to the second task item.", + "thought": "Now, I need to locate the Delete button for the second task.", "type": "Locate", "param": { - "prompt": "A delete button to the far right of the second task item 'Learn Rust tomorrow'" + "prompt": "The Delete button to the right of the task 'Learn Rust tomorrow'" } }, { - "thought": "Click the Delete button to remove the second task item.", + "thought": "I will now click the located Delete button.", "type": "Tap", "param": null } @@ -223,11 +223,11 @@ "height": 720 } }, - "prompt": "The second task item with content 'Learn Rust tomorrow'", + "prompt": "The task with the text 'Learn Rust tomorrow'", "response": { "elements": [ { - "reason": "The element with the content 'Learn Rust tomorrow' exactly matches the user's description to identify the 'Learn Rust tomorrow' task item.", + "reason": "The element has the content 'Learn Rust tomorrow', matching the description provided.", "text": "Learn Rust tomorrow", "id": "10bc260820" } @@ -244,11 +244,11 @@ "height": 720 } }, - "prompt": "A delete button to the far right of the second task item 'Learn Rust tomorrow'", + "prompt": "The Delete button to the right of the task 'Learn Rust tomorrow'", "response": { "elements": [ { - "reason": "The element is a button type located to the far right of the second task item 'Learn Rust tomorrow'. It matches the description of a delete button for that task.", + "reason": "The element is a 'BUTTON Node' (an 'X' button) situated to the right of the text node labeled 'Learn Rust tomorrow’", "text": "×", "id": "7ccd467339" } @@ -269,14 +269,14 @@ "response": { "plans": [ { - "thought": "The user wants to click the checkbox to the left of the second task. Based on the screenshot and the given context, the second task is 'Learning AI the day after tomorrow'. We should locate the checkbox next to this task.", + "thought": "The user asked to click the check button to the left of the second task labeled 'Learning AI the day after tomorrow', so I need to locate that checkbox first.", "type": "Locate", "param": { - "prompt": "The checkbox to the left of the task 'Learning AI the day after tomorrow'." + "prompt": "Checkbox on the left of 'Learning AI the day after tomorrow'" } }, { - "thought": "The checkbox for the second task 'Learning AI the day after tomorrow' is located, and needs to be clicked.", + "thought": "Now that the checkbox is located, it should be tapped to mark the task as done.", "type": "Tap", "param": null } @@ -292,11 +292,11 @@ "height": 720 } }, - "prompt": "The checkbox to the left of the task 'Learning AI the day after tomorrow'.", + "prompt": "Checkbox on the left of 'Learning AI the day after tomorrow'", "response": { "elements": [ { - "reason": "The element is a checkbox (INPUT Node) located to the left of the task text 'Learning AI the day after tomorrow'. It matches the description precisely.", + "reason": "This element is a checkbox located to the left of the 'Learning AI the day after tomorrow' text, matching the user's description.", "text": "", "id": "c0751f3b26" } @@ -317,14 +317,14 @@ "response": { "plans": [ { - "thought": "The user wants to click on the Completed Status button in the task list. Locate the element with the label Completed below the task list.", + "thought": "The user wants to click the 'Completed' status button below the task list to filter the tasks and see only the completed ones. This element is identifiable by its text content 'Completed'.", "type": "Locate", "param": { - "prompt": "The button labeled 'Completed' below the task list." + "prompt": "The 'Completed' status button below the task list with the text 'Completed'." } }, { - "thought": "Click on the located Completed Status button.", + "thought": "Click the located 'Completed' status button to filter the task list.", "type": "Tap", "param": null } @@ -340,11 +340,11 @@ "height": 720 } }, - "prompt": "The button labeled 'Completed' below the task list.", + "prompt": "The 'Completed' status button below the task list with the text 'Completed'.", "response": { "elements": [ { - "reason": "The element labeled 'Completed' below the task list corresponds to the text node with the content 'Completed'.", + "reason": "The 'Completed' status button below the task list and next to 'Active' with the text 'Completed'. In the provided JSON, the text 'Completed' is found in element with id 663a34de3b.", "text": "Completed", "id": "663a34de3b" } diff --git a/packages/web-integration/midscene_run/cache/ai-online-order.spec.ts:10(ai online order).json b/packages/web-integration/midscene_run/cache/ai-online-order.spec.ts:10(ai online order).json index a06515a88..b78efdb7d 100644 --- a/packages/web-integration/midscene_run/cache/ai-online-order.spec.ts:10(ai online order).json +++ b/packages/web-integration/midscene_run/cache/ai-online-order.spec.ts:10(ai online order).json @@ -1,6 +1,6 @@ { "pkgName": "@midscene/web", - "pkgVersion": "0.1.1", + "pkgVersion": "0.1.2", "taskFile": "ai-online-order.spec.ts:10", "taskTitle": "ai online order", "aiTasks": [ @@ -17,26 +17,26 @@ "response": { "plans": [ { - "thought": "用户希望切换语言到中文", + "thought": "需要找到左上角的语言切换按钮", "type": "Locate", "param": { - "prompt": "顶部导航栏中当前文本为‘English’的语言切换按钮" + "prompt": "左上角标有 \"English\" 的按钮" } }, { - "thought": "点击语言切换按钮", + "thought": "点击语言切换按钮以展开下拉菜单", "type": "Tap", "param": null }, { - "thought": "用户希望点击下拉列表中的中文选项", + "thought": "在弹出的下拉列表中找出 \"中文\" 并点击", "type": "Locate", "param": { - "prompt": "弹出下拉列表中含有‘中文’文本的选项" + "prompt": "下拉列表中的 \"中文\" 选项" } }, { - "thought": "选择语言为中文", + "thought": "选择中文选项", "type": "Tap", "param": null } @@ -52,11 +52,11 @@ "height": 905 } }, - "prompt": "顶部导航栏中当前文本为‘English’的语言切换按钮", + "prompt": "左上角标有 \"English\" 的按钮", "response": { "elements": [ { - "reason": "The element that matches the description is located in the top navigation bar with a text content of 'English', indicating that it is the language switch button.", + "reason": "The element with the text 'English' is located in the upper left corner and matches the description.", "text": "English", "id": "57c026f0b8" } @@ -73,11 +73,11 @@ "height": 905 } }, - "prompt": "弹出下拉列表中含有‘中文’文本的选项", + "prompt": "下拉列表中的 \"中文\" 选项", "response": { "elements": [ { - "reason": "The option labeled '中文' is identified in the dropdown, indicating it is a text node with the value '中文'.", + "reason": "The element with the id 'efc0b2ff38' is the 'TEXT Node' that matches the description “下拉列表中的 '中文' 选项”. It contains the text '中文' and is part of the dropdown menu.", "text": "中文", "id": "efc0b2ff38" } @@ -98,7 +98,7 @@ "response": { "plans": [ { - "thought": "用户需要向下滚动页面一屏,通过页面显示的元素,可以找到相关内容", + "thought": "执行用户想要向下滚动一屏的动作。", "type": "Scroll", "param": { "scrollType": "ScrollDown" @@ -120,14 +120,14 @@ "response": { "plans": [ { - "thought": "用户希望选择多肉葡萄的规格按钮,这可以通过点击相应的'选规格'按钮来完成。", + "thought": "用户需要点击多肉葡萄的规格按钮,这个按钮在列表中的一项,需要先找到对应商品,再点击按钮。", "type": "Locate", "param": { - "prompt": "多肉葡萄(首创)旁的黄色'选规格'按钮" + "prompt": "在页面中部,内容为'多肉葡萄(首创)'所在项的'选规格'按钮" } }, { - "thought": "点击找到的'选规格'按钮以选择规格", + "thought": "找到按钮后,点击它。", "type": "Tap", "param": null } @@ -143,11 +143,11 @@ "height": 905 } }, - "prompt": "多肉葡萄(首创)旁的黄色'选规格'按钮", + "prompt": "在页面中部,内容为'多肉葡萄(首创)'所在项的'选规格'按钮", "response": { "elements": [ { - "reason": "The button next to '多肉葡萄(首创)' is identified as the yellow '选规格' button with ID '427d3179c2'.", + "reason": "I identified the '选规格' button corresponding to the item '多肉葡萄(首创)' by locating the text '多肉葡萄(首创)' with ID '65b6fcae72' in the JSON description, and then finding the corresponding '选规格' button, which is situated close to this text item. The description and the screenshot match the required item.", "text": "选规格", "id": "427d3179c2" } @@ -168,334 +168,38 @@ "response": { "plans": [ { - "thought": "用户要选择 '不使用吸管',在页面中定位到该位置。", + "thought": "任务是点击'不使用吸管','冰沙推荐','正常冰推荐'。可以在页面上找到这些选项并点击。", "type": "Locate", "param": { - "prompt": "勾选框旁的文本为 '不使用吸管'" + "prompt": "勾选框旁边的文字内容为'不使用吸管'的复选框" } }, { - "thought": "点击 '不使用吸管' 选项。", + "thought": "用户需要选择'不使用吸管'选项。", "type": "Tap", "param": null }, { - "thought": "用户要选择含冰的冰沙推荐,先在页面中定位到该位置。", + "thought": "下一步是选择'冰沙(推荐)'。", "type": "Locate", "param": { - "prompt": "勾选框旁的文本为 '冰沙(推荐)'" + "prompt": "勾选框旁边的文字内容为'冰沙(推荐)'的复选框" } }, { - "thought": "点击 '冰沙(推荐)' 选项。", + "thought": "用户需要选择'冰沙推荐'选项。", "type": "Tap", "param": null }, { - "thought": "用户要选择正常冰推荐,先在页面中定位到该位置。", + "thought": "最后一步是选择'正常冰(推荐)'。", "type": "Locate", "param": { - "prompt": "勾选框旁的文本为 '正常冰(推荐)'" + "prompt": "勾选框旁边的文字内容为'正常冰(推荐)'的复选框" } }, { - "thought": "点击 '正常冰(推荐)' 选项。", - "type": "Tap", - "param": null - } - ] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "勾选框旁的文本为 '不使用吸管'", - "response": { - "elements": [ - { - "reason": "The text next to the checkbox saying '不使用吸管' matches the user's description of '勾选框旁的文本为 '不使用吸管'", - "text": "不使用吸管", - "id": "e83902c611" - } - ], - "errors": [] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "勾选框旁的文本为 '冰沙(推荐)'", - "response": { - "elements": [ - { - "reason": "The closest element to the description is the one that has the text '冰沙(推荐)', which is the exact text to the right of the desired checkbox.", - "text": "冰沙(推荐)", - "id": "e673260398" - } - ], - "errors": [] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "勾选框旁的文本为 '正常冰(推荐)'", - "response": { - "elements": [ - { - "reason": "The description '勾选框旁的文本为 正常冰(推荐)' refers to a checkbox next to the text '正常冰(推荐)'. The element '0b385ab4dc' matches this description as it has the class '.radio-text' and the content '正常冰(推荐)'.", - "text": "正常冰(推荐)", - "id": "0b385ab4dc" - } - ], - "errors": [] - } - }, - { - "type": "plan", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "向下滚动一屏", - "response": { - "plans": [ - { - "thought": "用户想要向下滚动一屏。", - "type": "Scroll", - "param": { - "scrollType": "ScrollDown" - } - } - ] - } - }, - { - "type": "plan", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "点击标准甜、点击绿妍(推荐)、点击标准口味", - "response": { - "plans": [ - { - "thought": "需要找到\"标准甜\"的复选框,然后点击它。", - "type": "Locate", - "param": { - "prompt": "包含文本'标准甜(推荐)'的复选框" - } - }, - { - "thought": "点击找到的\"标准甜\"复选框。", - "type": "Tap", - "param": null - }, - { - "thought": "需要找到\"绿妍(推荐)\"的复选框,然后点击它。", - "type": "Locate", - "param": { - "prompt": "包含文本'绿妍(推荐)'的复选框" - } - }, - { - "thought": "点击找到的\"绿妍(推荐)\"复选框。", - "type": "Tap", - "param": null - }, - { - "thought": "需要找到\"标准口味(推荐)\"的复选框,然后点击它。", - "type": "Locate", - "param": { - "prompt": "包含文本'标准口味(推荐)'的复选框" - } - }, - { - "thought": "点击找到的\"标准口味(推荐)\"复选框。", - "type": "Tap", - "param": null - } - ] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "包含文本'标准甜(推荐)'的复选框", - "response": { - "elements": [ - { - "reason": "The element is a checkbox associated with the text '标准甜(推荐)', which matches the description '包含文本'标准甜(推荐)'的复选框'", - "text": "", - "id": "5280c060a7" - } - ], - "errors": [] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "包含文本'绿妍(推荐)'的复选框", - "response": { - "elements": [ - { - "reason": "The description contains the text '绿妍(推荐)' and specifies that it should be a checkbox. The matching element has the ID '5570045013'.", - "text": "", - "id": "5570045013" - } - ], - "errors": [] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "包含文本'标准口味(推荐)'的复选框", - "response": { - "elements": [ - { - "reason": "The checkbox with the text '标准口味(推荐)' is identified based on its description. It is located in the section with other checkboxes and text labels. The element info confirms that the text '标准口味(推荐)' is associated with a checkbox.", - "text": "标准口味(推荐)", - "id": "7946eb054f" - } - ], - "errors": [] - } - }, - { - "type": "plan", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "滚动到最下面", - "response": { - "plans": [ - { - "thought": "根据用户的指示,需要将页面滚动到最底部,以便显示所有的可能选项。", - "type": "Scroll", - "param": { - "scrollType": "ScrollUntilBottom" - } - } - ] - } - }, - { - "type": "plan", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "点击选好了按钮", - "response": { - "plans": [ - { - "thought": "用户希望点击'选好了'按钮以完成选购", - "type": "Locate", - "param": { - "prompt": "位于屏幕底部,黄色背景带有“选好了”文字的按钮" - } - }, - { - "thought": "执行点击操作", - "type": "Tap", - "param": null - } - ] - } - }, - { - "type": "locate", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "位于屏幕底部,黄色背景带有“选好了”文字的按钮", - "response": { - "elements": [ - { - "reason": "The element with ID 'c9de916ef0' is identified as a button located at the bottom of the screen with the text '选好了' and a yellow background, matching the requested description.", - "text": "选好了", - "id": "c9de916ef0" - } - ], - "errors": [] - } - }, - { - "type": "plan", - "pageContext": { - "url": "https://heyteavivocity.meuu.online/home", - "size": { - "width": 400, - "height": 905 - } - }, - "prompt": "点击右上角商品图标按钮", - "response": { - "plans": [ - { - "thought": "右上角的商品图标按钮是一个看起来像购物车的图标,就在页面右上角。", - "type": "Locate", - "param": { - "prompt": "右上角的商品图标按钮,看起来像购物车的图标,接近右侧边缘。" - } - }, - { - "thought": "点击该商品图标按钮。", + "thought": "用户需要选择'正常冰推荐'选项。", "type": "Tap", "param": null } diff --git a/packages/web-integration/src/playwright/reporter/index.ts b/packages/web-integration/src/playwright/reporter/index.ts index e3b6c98e8..14ecb70c2 100644 --- a/packages/web-integration/src/playwright/reporter/index.ts +++ b/packages/web-integration/src/playwright/reporter/index.ts @@ -55,7 +55,7 @@ class MidSceneReporter implements Reporter { generateTestData(testDataList); console.log( '\x1b[32m%s\x1b[0m', - `MidScene report has been generated. Run "npx http-server -p 0 ./midscene_run/report -o --s" to view.`, + `MidScene report has been generated. Run "npx http-server ./midscene_run/report -p 0 -o -s" to view.`, ); } } diff --git a/packages/web-integration/src/playwright/reporter/util.ts b/packages/web-integration/src/playwright/reporter/util.ts index 0e1c80904..27c564907 100644 --- a/packages/web-integration/src/playwright/reporter/util.ts +++ b/packages/web-integration/src/playwright/reporter/util.ts @@ -1,9 +1,9 @@ import path from 'path'; -import fs from 'fs'; import assert from 'assert'; import os from 'os'; import fsExtra from 'fs-extra'; import { TestData } from './type'; +import { findNearestPackageJson } from '@/common/utils'; export function generateTestData(testDataList: Array) { const filterDataList = testDataList.reduce((res, testData) => { @@ -13,28 +13,25 @@ export function generateTestData(testDataList: Array) { return [...res, testData]; } }, [] as Array); - const projectDir = process.cwd(); - const reportDir = path.join(projectDir, 'midscene_run', 'report'); + const reportDir = findNearestPackageJson(__dirname); + assert(reportDir, `can't get reportDir from ${__dirname}`); - // Create a report folder - if (!fs.existsSync(reportDir)) { - fs.mkdirSync(reportDir); - } + const targetReportDir = path.join(process.cwd(), 'midscene_run', 'report'); // Copy the contents of the report html folder to the report folder - const reportHtmlDir = path.join(projectDir, `dist/visualizer-report`); + const reportHtmlDir = path.join(reportDir, `dist/visualizer-report`); const tempDir = path.join(os.tmpdir(), 'temp-folder'); try { // First copy to the temporary directory fsExtra.copySync(reportHtmlDir, tempDir); // Then move the contents of the temporary directory to the destination directory - fsExtra.moveSync(tempDir, reportDir, { overwrite: true }); + fsExtra.moveSync(tempDir, targetReportDir, { overwrite: true }); } catch (err) { console.error('An error occurred while copying the folder.', err); } try { - fsExtra.removeSync(path.join(reportDir, 'public')); + fsExtra.removeSync(path.join(targetReportDir, 'public')); } catch (err) { console.error('An error occurred while deleting the folder.', err); } @@ -44,14 +41,14 @@ export function generateTestData(testDataList: Array) { if (dumpPath) { const srcFile = dumpPath.split('/').pop(); assert(srcFile, `Failed to get source file name from ${dumpPath}`); - const destFile = path.join(reportDir, 'public', srcFile); + const destFile = path.join(targetReportDir, 'public', srcFile); fsExtra.copySync(dumpPath, destFile); } } try { fsExtra.outputFileSync( - path.join(reportDir, 'public', 'test-data-list.json'), + path.join(targetReportDir, 'public', 'test-data-list.json'), JSON.stringify({ 'test-list': filterDataList }), ); } catch (err) { @@ -60,7 +57,7 @@ export function generateTestData(testDataList: Array) { // modify log content // try { - // const filePath = path.join(reportDir, 'index.js'); // File path + // const filePath = path.join(targetReportDir, 'index.js'); // File path // const searchValue = 'Server is listening on http://[::]:'; // The content to be replaced can be a string or a regular expression // const replaceValue = 'The report has been generated on http://127.0.0.1:'; // The replaced content // // Read file contents @@ -78,7 +75,7 @@ export function generateTestData(testDataList: Array) { // close log // try { - // const filePath = path.join(reportDir, 'node_modules/@modern-js/prod-server/dist/cjs/apply.js'); // File path + // const filePath = path.join(targetReportDir, 'node_modules/@modern-js/prod-server/dist/cjs/apply.js'); // File path // let fileContent = fs.readFileSync(filePath, 'utf8'); // fileContent = fileContent.replace('(0, import_server_core.logPlugin)(),', ''); @@ -89,32 +86,32 @@ export function generateTestData(testDataList: Array) { // } // add static data - modifyRoutesJson(reportDir, testDataList); + // modifyRoutesJson(targetReportDir, testDataList); } -function modifyRoutesJson(reportDir: string, testDataList: Array) { - const filePath = path.join(reportDir, 'route.json'); - try { - const data = fs.readFileSync(filePath, 'utf8'); - - const newPaths = testDataList.map((testData) => { - const fileName = testData.dumpPath?.split('/').pop(); - return { - urlPath: `/${fileName}`, - isSPA: true, - isSSR: false, - entryPath: `public/${fileName}`, - }; - }); - - const jsonData = JSON.parse(data); - - // Insert the new path data into the js, OS and n structure - jsonData.routes.push(...newPaths); - - // Write the updated js on data back to the file - fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), 'utf8'); - } catch (err) { - console.error('modifyRoutesJson fail:', err); - } -} +// function modifyRoutesJson(targetReportDir: string, testDataList: Array) { +// const filePath = path.join(targetReportDir, 'route.json'); +// try { +// const data = fs.readFileSync(filePath, 'utf8'); + +// const newPaths = testDataList.map((testData) => { +// const fileName = testData.dumpPath?.split('/').pop(); +// return { +// urlPath: `/${fileName}`, +// isSPA: true, +// isSSR: false, +// entryPath: `public/${fileName}`, +// }; +// }); + +// const jsonData = JSON.parse(data); + +// // Insert the new path data into the js, OS and n structure +// jsonData.routes.push(...newPaths); + +// // Write the updated js on data back to the file +// fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), 'utf8'); +// } catch (err) { +// console.error('modifyRoutesJson fail:', err); +// } +// }