fix: 修复课程运行时初始化与拖拽测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.8 committed 2026-08-27 10:35:17 +08:00
1 parent d77281ff0d
commit 1e02c7835e
6 files changed
+173 -154

No files matched your search

+84 -80
View File
@@ -1,4 +1,42 @@
import { expect, test } from "@playwright/test";
import { expect, type Locator, type Page, test } from "@playwright/test";
async function dragWithPointer(
page: Page,
source: Locator,
target: Locator,
): Promise<void> {
const sourceBox = await source.boundingBox();
const targetBox = await target.boundingBox();
if (!sourceBox || !targetBox) {
throw new Error("Drag source or target is not visible");
}
const sourcePosition = {
x: sourceBox.x + sourceBox.width / 2,
y: sourceBox.y + sourceBox.height / 2,
};
const targetPosition = {
x: targetBox.x + targetBox.width / 2,
y: targetBox.y + targetBox.height / 2,
};
await page.mouse.move(sourcePosition.x, sourcePosition.y);
await page.mouse.down();
await page.mouse.move(sourcePosition.x + 10, sourcePosition.y, { steps: 5 });
await page.waitForTimeout(150);
await page.mouse.move(targetPosition.x, targetPosition.y, { steps: 20 });
await page.waitForTimeout(150);
await page.mouse.up();
}
function getResource(page: Page, title: string): Locator {
return page.getByRole("button", { name: new RegExp(title) });
}
function getCategory(page: Page, title: string): Locator {
return page.getByRole("heading", { name: title, exact: true }).locator("..");
}
test.describe("CourseDemo connected flow", () => {
test.beforeEach(async ({ page }) => {
@@ -67,104 +105,70 @@ test.describe("CourseDemo connected flow", () => {
await expect(page.locator("text=先阅读资源卡片")).not.toBeVisible();
});
// TODO: @dnd-kit drag automation is unreliable in Playwright.
// Manual verification confirms drag-drop works correctly in real browsers.
// Skip these tests until a stable automation approach is found.
test.skip("drag and drop resource classification", async ({ page }) => {
// Wait for resources to load
await expect(page.locator('[data-guide="course-resources"]')).toBeVisible();
test("drag and drop resource classification", async ({ page }) => {
const policyResource = getResource(page, "资助政策微课");
const policyZone = getCategory(page, "政策学习");
// Find first resource card (资助政策微课)
const policyResource = page
.locator('[data-guide="course-resources"]')
.locator("text=资助政策微课")
.first();
await expect(policyResource).toBeVisible();
// Find the policy-learning drop zone
const policyZone = page.locator("text=政策学习").first();
await expect(policyZone).toBeVisible();
await dragWithPointer(page, policyResource, policyZone);
// Use Playwright's native dragTo which works better with dnd-kit
await policyResource.dragTo(policyZone, {
force: true,
timeout: 10000,
});
await page.waitForTimeout(1000);
// Success toast should appear (exact match with dynamic title)
await expect(page.locator("text=/分类正确/")).toBeVisible();
await page.waitForTimeout(300);
// Progress should update
const progressText = page.locator("text=/已完成 \\d+\\/6/");
await expect(progressText).toBeVisible();
await expect(page.getByText("分类正确:资助政策微课")).toBeVisible();
await expect(page.getByText("已完成 1/6")).toBeVisible();
await expect(policyResource).not.toBeVisible();
});
test.skip("wrong category shows error toast", async ({ page }) => {
await expect(page.locator('[data-guide="course-resources"]')).toBeVisible();
// Try to drop policy resource into practice (wrong category)
const policyResource = page
.locator('[data-guide="course-resources"]')
.locator("text=资助政策微课")
.first();
const wrongZone = page.locator("text=互动实践").first();
test("wrong category shows error toast", async ({ page }) => {
const policyResource = getResource(page, "资助政策微课");
const wrongZone = getCategory(page, "互动实践");
await expect(policyResource).toBeVisible();
await expect(wrongZone).toBeVisible();
await dragWithPointer(page, policyResource, wrongZone);
// Use Playwright's native dragTo
await policyResource.dragTo(wrongZone, {
force: true,
timeout: 10000,
});
await page.waitForTimeout(1000);
// Error toast should appear (exact match with dynamic title)
await expect(page.locator("text=/不属于这个分类/")).toBeVisible();
await expect(
page.getByText("“资助政策微课”不属于这个分类,再想一想。"),
).toBeVisible();
await expect(page.getByText("已完成 0/6")).toBeVisible();
await expect(policyResource).toBeVisible();
});
test("completion overlay appears after all resources placed", async ({
page,
}) => {
// This would require placing all 6 resources correctly, which is slow
// Instead we'll just verify the reset button works
await page.click("text=重新开始");
await page.waitForTimeout(500);
const placements = [
["资助政策微课", "政策学习"],
["申请流程图", "政策学习"],
["诚信申请案例", "互动实践"],
["材料自查清单", "互动实践"],
["常见问题答疑", "学习支持"],
["校园咨询渠道", "学习支持"],
] as const;
// Toast should confirm reset
await expect(page.locator("text=练习已重置")).toBeVisible();
for (const [resourceTitle, categoryTitle] of placements) {
await dragWithPointer(
page,
getResource(page, resourceTitle),
getCategory(page, categoryTitle),
);
}
await expect(page.getByText("资源地图已建立")).toBeVisible();
await expect(page.getByText("已完成 6/6")).toBeVisible();
await expect(page.getByText("100%")).toBeVisible();
});
test.skip("persists progress (session fallback)", async ({
page,
context,
}) => {
// Place one resource
const resource = page
.locator('[data-guide="course-resources"]')
.locator("text=资助政策微课")
.first();
const zone = page.locator("text=政策学习").first();
test("persists progress with session fallback", async ({ page }) => {
await dragWithPointer(
page,
getResource(page, "资助政策微课"),
getCategory(page, "政策学习"),
);
await expect(page.getByText("已完成 1/6")).toBeVisible();
await expect(resource).toBeVisible();
await expect(zone).toBeVisible();
// Use Playwright's native dragTo
await resource.dragTo(zone, {
force: true,
timeout: 10000,
});
await page.waitForTimeout(1000);
// Reload page
await page.reload();
await page.waitForLoadState("networkidle");
await page.waitForTimeout(1500);
// Progress should show 1/6
await expect(page.locator("text=已完成 1/6")).toBeVisible();
await expect(page.locator("text=进度已恢复")).toBeVisible();
await expect(page.getByText("进度已恢复")).toBeVisible();
await expect(page.getByText("已完成 1/6")).toBeVisible();
await expect(getResource(page, "资助政策微课")).not.toBeVisible();
});
});