Spaces:
Paused
Paused
yaGeey commited on
Commit ·
7102b00
1
Parent(s): 72a2326
- src/actions.ts +36 -37
- src/browser.ts +2 -0
src/actions.ts
CHANGED
|
@@ -17,38 +17,38 @@ const dismissConsentIfPresent = async (page: Page) => {
|
|
| 17 |
}
|
| 18 |
|
| 19 |
export const addToPlaylistAction = async (page: Page) => {
|
| 20 |
-
const slowHostTimeoutMs = 90000
|
| 21 |
|
| 22 |
-
await page.waitForLoadState('
|
| 23 |
-
console.log('page loaded')
|
| 24 |
await dismissConsentIfPresent(page)
|
| 25 |
-
console.log('page loaded and dissmissed')
|
| 26 |
|
| 27 |
const track = page.locator('[data-testid="tracklist-row"]').first()
|
| 28 |
await track.waitFor({ state: 'visible', timeout: slowHostTimeoutMs })
|
| 29 |
-
console.log('track visible')
|
| 30 |
|
|
|
|
|
|
|
| 31 |
await track.click({ button: 'right', timeout: slowHostTimeoutMs })
|
| 32 |
-
console.log('track right-clicked')
|
| 33 |
|
| 34 |
const menu = page.locator('[data-testid="context-menu"]')
|
| 35 |
-
await menu.waitFor({ timeout: slowHostTimeoutMs })
|
| 36 |
-
console.log('context menu visible')
|
| 37 |
|
| 38 |
const addToPlaylistButton = menu.getByText('Add to Playlist', { exact: false })
|
| 39 |
-
await addToPlaylistButton.waitFor({ state: 'visible'
|
| 40 |
-
|
| 41 |
-
await addToPlaylistButton.hover({ timeout: slowHostTimeoutMs })
|
| 42 |
-
console.log('add to playlist button hovered')
|
| 43 |
|
| 44 |
const input = page.locator('[placeholder="Find a playlist"]')
|
| 45 |
await input.waitFor({ state: 'visible', timeout: slowHostTimeoutMs })
|
| 46 |
-
console.log('playlist search input visible')
|
| 47 |
-
await input.fill('TEST', { timeout: slowHostTimeoutMs })
|
| 48 |
-
console.log('playlist search input filled')
|
| 49 |
-
// await page.waitForTimeout(5000)
|
| 50 |
-
console.log('waited for search results to populate')
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
const targetPlaylist = page.getByRole('menuitem', { name: 'TEST', exact: true }).first()
|
| 53 |
if (!(await targetPlaylist.isVisible())) {
|
| 54 |
console.log('playlist not found in search results, clicking search result to trigger playlist loading')
|
|
@@ -64,26 +64,25 @@ export const addToPlaylistAction = async (page: Page) => {
|
|
| 64 |
console.log('clicked playlist in search results')
|
| 65 |
}
|
| 66 |
|
| 67 |
-
// Wait for context menu to close
|
| 68 |
-
await menu.waitFor({ state: 'hidden', timeout:
|
| 69 |
-
console.log('context menu closed')
|
| 70 |
-
|
| 71 |
-
// Wait for UI to settle
|
| 72 |
-
await page.waitForTimeout(2000)
|
| 73 |
-
|
| 74 |
-
// Check if "Already added" dialog appeared (only if song was already in playlist)
|
| 75 |
-
const addAnywayBtn = page.getByRole('button', { name: /add anyway/i })
|
| 76 |
-
await addAnywayBtn.waitFor({ timeout: 5000 }).catch(() => console.log('"Add anyway" button did not appear'))
|
| 77 |
-
const isVisible = await addAnywayBtn.isVisible().catch(() => false)
|
| 78 |
-
console.log(`is "Add anyway" button visible? ${isVisible}`)
|
| 79 |
-
if (isVisible) {
|
| 80 |
-
await addAnywayBtn.click({ timeout: slowHostTimeoutMs })
|
| 81 |
-
console.log('clicked "Add anyway" button')
|
| 82 |
-
}
|
| 83 |
|
| 84 |
-
//
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
-
|
|
|
|
| 89 |
}
|
|
|
|
| 17 |
}
|
| 18 |
|
| 19 |
export const addToPlaylistAction = async (page: Page) => {
|
| 20 |
+
const slowHostTimeoutMs = 90000 // Зменшив, 90с це занадто, краще впасти раніше
|
| 21 |
|
| 22 |
+
await page.waitForLoadState('networkidle', { timeout: slowHostTimeoutMs }) // Важливо: networkidle краще ніж domcontentloaded для SPA
|
|
|
|
| 23 |
await dismissConsentIfPresent(page)
|
|
|
|
| 24 |
|
| 25 |
const track = page.locator('[data-testid="tracklist-row"]').first()
|
| 26 |
await track.waitFor({ state: 'visible', timeout: slowHostTimeoutMs })
|
|
|
|
| 27 |
|
| 28 |
+
// ТРЮК 1: Примусовий скрол до елемента перед кліком
|
| 29 |
+
await track.scrollIntoViewIfNeeded()
|
| 30 |
await track.click({ button: 'right', timeout: slowHostTimeoutMs })
|
|
|
|
| 31 |
|
| 32 |
const menu = page.locator('[data-testid="context-menu"]')
|
| 33 |
+
await menu.waitFor({ state: 'visible', timeout: slowHostTimeoutMs })
|
|
|
|
| 34 |
|
| 35 |
const addToPlaylistButton = menu.getByText('Add to Playlist', { exact: false })
|
| 36 |
+
await addToPlaylistButton.waitFor({ state: 'visible' })
|
| 37 |
+
await addToPlaylistButton.hover() // Hover обов'язковий
|
|
|
|
|
|
|
| 38 |
|
| 39 |
const input = page.locator('[placeholder="Find a playlist"]')
|
| 40 |
await input.waitFor({ state: 'visible', timeout: slowHostTimeoutMs })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
+
// ТРЮК 2: Повільний ввід тексту. Це дає React час обробити стейт.
|
| 43 |
+
// Замість fill використовуємо pressSequentially з затримкою
|
| 44 |
+
await input.pressSequentially('TEST', { delay: 100 })
|
| 45 |
+
|
| 46 |
+
// Даємо час на рендеринг відфільтрованого списку
|
| 47 |
+
await page.waitForTimeout(1500)
|
| 48 |
+
|
| 49 |
+
// ТРЮК 3: Замість кліку мишкою - ENTER
|
| 50 |
+
// Після пошуку фокус зазвичай залишається в input або перший елемент стає активним.
|
| 51 |
+
// Спробуємо натиснути стрілку вниз (щоб точно вибрати плейліст) і Enter.
|
| 52 |
const targetPlaylist = page.getByRole('menuitem', { name: 'TEST', exact: true }).first()
|
| 53 |
if (!(await targetPlaylist.isVisible())) {
|
| 54 |
console.log('playlist not found in search results, clicking search result to trigger playlist loading')
|
|
|
|
| 64 |
console.log('clicked playlist in search results')
|
| 65 |
}
|
| 66 |
|
| 67 |
+
// Wait for context menu to close implicitly
|
| 68 |
+
await menu.waitFor({ state: 'hidden', timeout: 15000 }).catch(() => {})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
+
// --- БЛОК ОБРОБКИ "Add Anyway" ---
|
| 71 |
+
// Тут важливо чекати не просто появи, а появи АБО зникнення діалогу
|
| 72 |
+
// Але оскільки нам треба клікнути, чекаємо кнопку.
|
| 73 |
+
|
| 74 |
+
try {
|
| 75 |
+
const addAnywayBtn = page.getByRole('button', { name: /add anyway/i })
|
| 76 |
+
// Чекаємо трохи довше, бо модалка може мати анімацію появи
|
| 77 |
+
await addAnywayBtn.waitFor({ state: 'visible', timeout: 15000 })
|
| 78 |
+
|
| 79 |
+
console.log('"Add anyway" visible, clicking...')
|
| 80 |
+
// Тут теж краще без force, якщо можливо, але для мо��алок force допустимий
|
| 81 |
+
await addAnywayBtn.click()
|
| 82 |
+
} catch (e) {
|
| 83 |
+
console.log('"Add anyway" button did not appear (track likely added or not duplicate)')
|
| 84 |
+
}
|
| 85 |
|
| 86 |
+
// Фінальне очікування, щоб запит встиг піти
|
| 87 |
+
await page.waitForTimeout(3000)
|
| 88 |
}
|
src/browser.ts
CHANGED
|
@@ -22,6 +22,8 @@ export async function createInstance() {
|
|
| 22 |
locale: 'en-US',
|
| 23 |
timezoneId: 'America/New_York',
|
| 24 |
bypassCSP: true,
|
|
|
|
|
|
|
| 25 |
})
|
| 26 |
await context.addCookies([
|
| 27 |
{
|
|
|
|
| 22 |
locale: 'en-US',
|
| 23 |
timezoneId: 'America/New_York',
|
| 24 |
bypassCSP: true,
|
| 25 |
+
// viewport: { width: 1920, height: 1080 }, // <--- ДОДАЙ ЦЕ
|
| 26 |
+
deviceScaleFactor: 1,
|
| 27 |
})
|
| 28 |
await context.addCookies([
|
| 29 |
{
|