Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/playwright-facebook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Playwright - Facebook login e2e

on:
pull_request:
paths:
- 'e2e-playwright/**'
- '.github/workflows/playwright-facebook.yml'

defaults:
run:
working-directory: e2e-playwright

jobs:
facebook-login:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
cache-dependency-path: e2e-playwright/package-lock.json

- run: npm ci

- run: npx playwright install --with-deps chromium

- name: Run the migrated Facebook login spec
run: npx playwright test tests/facebook-login.spec.ts

- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: e2e-playwright/playwright-report/
retention-days: 7
5 changes: 5 additions & 0 deletions e2e-playwright/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
playwright-report/
test-results/
blob-report/
.playwright/
28 changes: 28 additions & 0 deletions e2e-playwright/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# e2e-playwright

Self-contained Playwright (TypeScript, chromium) project holding the modern port of the
legacy Selenium/TestNG `FaceBookLoginTest`. It has its own `package.json` and
`playwright.config.ts` and is independent of the Maven build; the Java suite is unchanged.

```bash
cd e2e-playwright
npm ci
npx playwright install --with-deps chromium
npm test # or: npx playwright test tests/facebook-login.spec.ts
```

## What was migrated

| Legacy (Java) | Here |
| --- | --- |
| `tests/FaceBookLoginTest.java` | `tests/facebook-login.spec.ts` |
| `pages/FacebookLoginPage.java` | `pages/facebook-login.page.ts` |
| `BaseTest` WebDriver setup, `WebDriverContext`, `PageinstancesFactory` | Playwright `page` fixture + config |
| `@FindBy(id = "email")` | `input[name="email"]` (the `id` is generated per render on current facebook.com) |

The legacy test's final step is `Assert.assertTrue(false, "Login failed : Test failed")` -
an unconditional failure rather than a real check, with no credentials available to
actually log in. That step is preserved as a `test.fixme` in the spec with an explanatory
comment instead of being rewritten into an assertion that would pass vacuously.

CI runs only this spec on pull requests via `.github/workflows/playwright-facebook.yml`.
111 changes: 111 additions & 0 deletions e2e-playwright/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions e2e-playwright/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "e2e-playwright",
"private": true,
"version": "1.0.0",
"description": "Playwright TypeScript migration of the legacy Selenium/TestNG FaceBookLoginTest",
"scripts": {
"test": "playwright test",
"test:headed": "playwright test --headed",
"report": "playwright show-report"
},
"devDependencies": {
"@playwright/test": "1.48.2",
"@types/node": "20.16.11",
"typescript": "5.6.3"
}
}
45 changes: 45 additions & 0 deletions e2e-playwright/pages/facebook-login.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Locator, Page, expect } from '@playwright/test';

/**
* Playwright port of the legacy Selenium page object
* src/test/java/example/example/pages/FacebookLoginPage.java.
*
* The legacy page object located the email field by `id=email`, which no longer
* exists: facebook.com now renders inputs with generated ids, so the field is
* addressed by its stable `name` attribute instead.
*/
export class FacebookLoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;

constructor(private readonly page: Page) {
this.emailInput = page.locator('input[name="email"]');
this.passwordInput = page.locator('input[name="pass"]');
this.submitButton = page.locator('form input[type="submit"], form button[type="submit"]').first();
}

async goto(): Promise<void> {
await this.page.goto('/', { waitUntil: 'domcontentloaded' });
}

async expectLoaded(): Promise<void> {
await expect(this.emailInput).toBeVisible();
await expect(this.passwordInput).toBeVisible();
}

async enterEmail(email: string): Promise<this> {
await this.emailInput.fill(email);
return this;
}

async enterPassword(password: string): Promise<this> {
await this.passwordInput.fill(password);
return this;
}

async clickSignIn(): Promise<void> {
await this.passwordInput.press('Enter');
await this.page.waitForLoadState('domcontentloaded');
}
}
24 changes: 24 additions & 0 deletions e2e-playwright/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './tests',
timeout: 60_000,
expect: { timeout: 15_000 },
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 1 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: process.env.CI ? [['github'], ['html', { open: 'never' }]] : [['list'], ['html', { open: 'never' }]],
use: {
baseURL: 'https://www.facebook.com',
trace: 'retain-on-failure',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
53 changes: 53 additions & 0 deletions e2e-playwright/tests/facebook-login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { expect, test } from '@playwright/test';

import { FacebookLoginPage } from '../pages/facebook-login.page';

/**
* Migration of the legacy Selenium/TestNG test
* src/test/java/example/example/tests/FaceBookLoginTest.java.
*
* The legacy test did three things:
* 1. navigated to https://www.facebook.com/
* 2. filled email ("abc") and password ("abc") and submitted the login form
* 3. called `Assert.assertTrue(false, "Login failed : Test failed")`
*
* Steps 1 and 2 are ported below against the current facebook.com markup: the
* legacy `id=email` locator is gone (ids are generated per render), so the
* fields are addressed by their `name` attributes.
*
* Step 3 is a deliberate, unconditional failure in the legacy suite - it
* asserts a literal `false` and is not a statement about the application under
* test. There is also no real credential pair to log in with. It is therefore
* kept as an explicitly pending `test.fixme` rather than rewritten into an
* assertion that would trivially pass and hide the gap.
*/
test.describe('Facebook login (migrated from FaceBookLoginTest)', () => {
test('loads the login page and submits the credentials entered', async ({ page }) => {
const loginPage = new FacebookLoginPage(page);

await loginPage.goto();
await loginPage.expectLoaded();

await (await loginPage.enterEmail('abc')).enterPassword('abc');
await expect(loginPage.emailInput).toHaveValue('abc');
await expect(loginPage.passwordInput).toHaveValue('abc');

await loginPage.clickSignIn();

// The bogus credentials cannot authenticate; all that can honestly be
// asserted is that the submission was handled by facebook.com.
expect(new URL(page.url()).hostname).toContain('facebook.com');
});

test.fixme(
'reports a successful login - legacy assertion is an unconditional failure',
async () => {
// FaceBookLoginTest ends with `Assert.assertTrue(false, "Login failed : Test failed")`,
// so the legacy test can never pass. Verifying a successful login needs
// real credentials (and would require handling Facebook's bot checks),
// neither of which exists in this repository. Left pending on purpose:
// faking a passing assertion here would misrepresent coverage.
expect(true).toBe(false);
},
);
});
13 changes: 13 additions & 0 deletions e2e-playwright/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": ["node"],
"noEmit": true
},
"include": ["tests/**/*.ts", "pages/**/*.ts", "playwright.config.ts"]
}
Loading