first commit
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/**
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
57
package-lock.json
generated
Normal file
57
package-lock.json
generated
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"name": "playwright-demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "playwright-demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright": "^1.58.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/playwright": {
|
||||||
|
"version": "1.58.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
|
||||||
|
"integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright-core": "1.58.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/playwright-core": {
|
||||||
|
"version": "1.58.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
|
||||||
|
"integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
|
||||||
|
"bin": {
|
||||||
|
"playwright-core": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "playwright-demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright": "^1.58.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
305
state.json
Normal file
305
state.json
Normal file
File diff suppressed because one or more lines are too long
213
test.js
Normal file
213
test.js
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
const { chromium } = require('playwright');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await chromium.launch({
|
||||||
|
headless: true // 👈 Windows建议先开界面调试
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 👇 关键就在这里
|
||||||
|
let context = null
|
||||||
|
if (fs.existsSync('state.json')) {
|
||||||
|
console.log('✅ state.json 存在');
|
||||||
|
context = await browser.newContext({
|
||||||
|
storageState: 'state.json',
|
||||||
|
locale: "zh-CN"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('❌ state.json 不存在');
|
||||||
|
context = await browser.newContext({
|
||||||
|
locale: "zh-CN"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const page = await context.newPage();
|
||||||
|
await page.goto('https://gitcode.com/setting/points');
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
const isLogin = await page.locator('.g-user-avatar').isVisible();
|
||||||
|
if (isLogin) {
|
||||||
|
console.log('✅ 已登录');
|
||||||
|
runTasks(page)
|
||||||
|
} else {
|
||||||
|
console.log('❌ 未登录');
|
||||||
|
await page.getByText('密码登录').click();
|
||||||
|
await page.getByPlaceholder('请填写手机号/用户名/邮箱').fill('15623979816');
|
||||||
|
await page.getByPlaceholder('请填写密码').fill('Zzy1995115');
|
||||||
|
await page.getByText('登录或注册完成代表你同意').click();
|
||||||
|
await page.getByText('我同意将账号、组织、仓库等信息提供给AtomGit进行 ').click();
|
||||||
|
await page.locator('button:has-text("登 录")').click();
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
await context.storageState({ path: 'state.json' });
|
||||||
|
runTasks(page)
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
async function runTasks(page) {
|
||||||
|
console.log('✅ 开始寻找每日任务');
|
||||||
|
const tasks = await page.locator('.novice-task-item-box').all();
|
||||||
|
console.log('✅ 共找到' + tasks.length + '个每日任务');
|
||||||
|
for (const task of tasks) {
|
||||||
|
const title = await task.locator('.task-card-title__label-text').innerText();
|
||||||
|
if (title.includes("更新项目")) {
|
||||||
|
const taskStat = await taskIsCompleted(task)
|
||||||
|
if (!taskStat) {
|
||||||
|
await doUpdateProject(page)
|
||||||
|
}
|
||||||
|
} else if (title.includes("每日分享")) {
|
||||||
|
const taskStat = await taskIsCompleted(task)
|
||||||
|
if (!taskStat) {
|
||||||
|
await dailyShare(task, page)
|
||||||
|
}
|
||||||
|
} else if (title.includes("每日签到")) {
|
||||||
|
const taskStat = await taskIsCompleted(task)
|
||||||
|
if (!taskStat) {
|
||||||
|
await dailyCheckInTask(task, page)
|
||||||
|
}
|
||||||
|
} else if (title.includes("查看热门")) {
|
||||||
|
const taskStat = await taskIsCompleted(task)
|
||||||
|
if (!taskStat) {
|
||||||
|
await dailyViewTrending(task, page)
|
||||||
|
}
|
||||||
|
} else if (title.includes("每日Star")) {
|
||||||
|
const taskStat = await taskIsCompleted(task)
|
||||||
|
if (!taskStat) {
|
||||||
|
await dailyViewStar(task, page)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.reload({ waitUntil: "domcontentloaded" });
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.locator('button.pickup-btn:has-text("一键领取")').click();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function taskIsCompleted(task) {
|
||||||
|
const taskEnd = await task.locator('button:has-text("领取奖励")').count() > 0
|
||||||
|
if (taskEnd) {
|
||||||
|
task.locator('button:has-text("领取奖励")').click()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const isCompleted = await task.locator('.completed').count() > 0
|
||||||
|
if (isCompleted) {
|
||||||
|
console.log('✅ 已完成,跳过');
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doUpdateProject(page) {
|
||||||
|
console.log('👉 执行项目更新');
|
||||||
|
const context = page.context();
|
||||||
|
const newPage = await context.newPage();
|
||||||
|
await newPage.goto('https://gitcode.com/fzxlzy/test/edit/main/testjpgp11');
|
||||||
|
// 你可以自己补逻辑
|
||||||
|
const frame = newPage.frameLocator('#codeartside');
|
||||||
|
|
||||||
|
// 1️⃣ 点击编辑器
|
||||||
|
await frame.locator('.monaco-editor').click({
|
||||||
|
position: { x: 200, y: 100 }
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2️⃣ 把光标移动到末尾(关键!)
|
||||||
|
await newPage.keyboard.press('Control+End');
|
||||||
|
|
||||||
|
// 3️⃣ 追加内容
|
||||||
|
await newPage.keyboard.type(`\n测试图片生成功能
|
||||||
|
11
|
||||||
|
22
|
||||||
|
33`, { delay: 50 });
|
||||||
|
// 等按钮出现
|
||||||
|
await newPage.locator('button:has-text("提交修改")').click();
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
const submitButton = newPage.locator('button:has-text("提交修改")').nth(1); // 0 是页面按钮,1 是弹框按钮
|
||||||
|
await submitButton.click();
|
||||||
|
await newPage.waitForTimeout(500);
|
||||||
|
await newPage.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dailyShare(task, page) {
|
||||||
|
// 等待新页面打开
|
||||||
|
const [newPage] = await Promise.all([
|
||||||
|
page.context().waitForEvent('page'), // 等待新页面事件
|
||||||
|
task.locator('.toComplete').click()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 点击第一个
|
||||||
|
await newPage.waitForTimeout(1000);
|
||||||
|
await newPage.locator('.immediately-invite-btn').nth(0).click();
|
||||||
|
await newPage.waitForTimeout(2000);
|
||||||
|
await newPage.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dailyCheckInTask(task, page) {
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
task.locator('button:has-text("签到")').click()
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dailyViewTrending(task, page) {
|
||||||
|
// 等待新页面打开
|
||||||
|
const [newPage] = await Promise.all([
|
||||||
|
page.context().waitForEvent('page'), // 等待新页面事件
|
||||||
|
task.locator('.toComplete').click()
|
||||||
|
])
|
||||||
|
await newPage.waitForSelector('.hot-selection .recommend-card');
|
||||||
|
// 获取第一个热门项目卡片
|
||||||
|
const firstHotProjectCard = await newPage.$('.hot-selection .recommend-card');
|
||||||
|
await newPage.waitForTimeout(1000);
|
||||||
|
// 点击它
|
||||||
|
const [newPage2] = await Promise.all([
|
||||||
|
newPage.context().waitForEvent('page'), // 等待新页面事件
|
||||||
|
await firstHotProjectCard.click()
|
||||||
|
])
|
||||||
|
await newPage2.waitForTimeout(2000);
|
||||||
|
newPage2.close()
|
||||||
|
newPage.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dailyViewStar(task, page) {
|
||||||
|
// 等待新页面打开
|
||||||
|
const [newPage] = await Promise.all([
|
||||||
|
page.context().waitForEvent('page'), // 等待新页面事件
|
||||||
|
task.locator('.toComplete').click()
|
||||||
|
])
|
||||||
|
// 等待元素出现在 DOM(不要用 visible,容易超时)
|
||||||
|
await newPage.waitForSelector('.hot-selection-list a.recommend-card', { state: 'attached' });
|
||||||
|
const cards = newPage.locator('.hot-selection-list a.recommend-card');
|
||||||
|
const count = await cards.count();
|
||||||
|
|
||||||
|
console.log("热门项目数量:", count);
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
throw new Error("没有找到热门项目");
|
||||||
|
}
|
||||||
|
await newPage.waitForTimeout(2000);
|
||||||
|
// 随机选一个
|
||||||
|
const index = Math.floor(Math.random() * count);
|
||||||
|
console.log("随机选择 index:", index);
|
||||||
|
// 点击并捕获新 tab
|
||||||
|
const [newPage2] = await Promise.all([
|
||||||
|
newPage.context().waitForEvent('page'),
|
||||||
|
cards.nth(index).click()
|
||||||
|
]);
|
||||||
|
// 等待 Star 按钮出现
|
||||||
|
const starBtn = newPage2.locator('#repo-header-tab .status-btn').filter({ hasText: 'Star' }).nth(1);
|
||||||
|
await newPage2.waitForTimeout(2000);
|
||||||
|
await starBtn.waitFor({ state: 'visible' });
|
||||||
|
// 判断是否已 Starred
|
||||||
|
const text = await starBtn.innerText();
|
||||||
|
await newPage2.waitForTimeout(2000);
|
||||||
|
if (text.includes('Starred')) {
|
||||||
|
// 已经 Starred -> 先取消
|
||||||
|
await starBtn.click();
|
||||||
|
|
||||||
|
// 等待变回 Star
|
||||||
|
await newPage2.waitForTimeout(500);
|
||||||
|
}
|
||||||
|
await starBtn.click();
|
||||||
|
await newPage2.waitForTimeout(2000);
|
||||||
|
newPage2.close()
|
||||||
|
newPage.close()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user