// @ts-check const { test, expect } = require('@playwright/test'); const fs = require('fs'); const path = require('path'); const RESULT_PATH = path.join(__dirname, '..', 'test-results', 'result.json'); function writeResult(result) { fs.mkdirSync(path.dirname(RESULT_PATH), { recursive: true }); fs.writeFileSync(RESULT_PATH, JSON.stringify(result)); } test.describe('linkedin post', () => { let outcome = { success: false, error: 'Test did not complete' }; let outcomeFinalized = false; test.afterEach(async () => { writeResult(outcome); }); test('logs into LinkedIn and creates a post', async ({ page }) => { const email = process.env.LINKEDIN_EMAIL; const password = process.env.LINKEDIN_PASSWORD; const postContent = process.env.POST_CONTENT; for (const [name, value] of Object.entries({ LINKEDIN_EMAIL: email, LINKEDIN_PASSWORD: password, POST_CONTENT: postContent, })) { if (!value) { outcome = { success: false, error: `Missing required environment variable: ${name}` }; outcomeFinalized = true; throw new Error(outcome.error); } } try { await page.goto('https://www.linkedin.com/login'); // Wait for page to load await page.waitForLoadState('networkidle'); // Check for login form const emailField = page.getByLabel(/email|phone/i).first(); if (!await emailField.isVisible({ timeout: 10000 }).catch(() => false)) { outcome = { success: false, error: 'LinkedIn login form not found — page structure may have changed', }; outcomeFinalized = true; throw new Error(outcome.error); } // Fill email await emailField.fill(email); // Fill password const passwordField = page.getByLabel(/password/i).first(); if (await passwordField.isVisible({ timeout: 10000 }).catch(() => false)) { await passwordField.fill(password); } // Click sign in button const signInButton = page.getByRole('button', { name: /sign in|signin|log in/i, exact: false }).first(); await signInButton.click(); // Wait for login to complete - check for feed or start post button try { await page.waitForURL('https://www.linkedin.com/feed/', { timeout: 20000 }); } catch { // Check if we're logged in by looking for start post button const startPostButton = page.getByRole('button', { name: /start a post|post/i, exact: false }).first(); if (!await startPostButton.isVisible({ timeout: 10000 }).catch(() => false)) { const errorText = await page.textContent('body').catch(() => ''); outcome = { success: false, error: errorText.toLowerCase().includes('invalid') || errorText.toLowerCase().includes('incorrect') ? 'Invalid LinkedIn credentials' : 'LinkedIn login did not complete — possible CAPTCHA, 2FA, or invalid credentials', }; outcomeFinalized = true; throw new Error(outcome.error); } } // Click "Start a post" button const startPostButton = page.getByRole('button', { name: /start a post|post/i, exact: false }).first(); await startPostButton.click(); // Wait for post composer const postTextarea = page.getByRole('textbox', { name: /what do you want to talk about/i, exact: false }).first(); if (!await postTextarea.isVisible({ timeout: 10000 }).catch(() => false)) { // Try alternative selector const altTextarea = page.locator('div[contenteditable="true"]').first(); if (await altTextarea.isVisible({ timeout: 5000 }).catch(() => false)) { await altTextarea.click(); await page.keyboard.type(postContent); } else { outcome = { success: false, error: 'LinkedIn post composer not found — UI may have changed', }; outcomeFinalized = true; throw new Error(outcome.error); } } else { await postTextarea.fill(postContent); } // Click post button const postButton = page.getByRole('button', { name: /^post$/i, exact: true }).first(); if (await postButton.isVisible({ timeout: 5000 }).catch(() => false)) { await postButton.click(); } else { // Try alternative post button selectors const altPostButton = page.getByRole('button', { name: /share|post/i, exact: false }).nth(1); if (await altPostButton.isVisible({ timeout: 5000 }).catch(() => false)) { await altPostButton.click(); } } // Wait for post to be created await page.waitForTimeout(3000); // Get current URL (should be the post URL or feed) outcome = { success: true, url: page.url() }; outcomeFinalized = true; expect(outcome.success).toBe(true); } catch (err) { if (!outcomeFinalized) { outcome = { success: false, error: err instanceof Error ? err.message : String(err) }; } throw err; } }); });