Playwright testing for angular-osf
Playwright/TypeScript migration of the OSF Selenium (pytest) test suite. This is
stage 1 of the migration: project scaffolding, multi-environment/multi-browser
execution, and a full port of test_login.py plus the fixtures and API calls it
(and the wider conftest.py) depend on.
npm install
npx playwright install
cp .env.example .env # then fill in credentialsEnvironment is selected via TEST_ENV (mirrors the old settings.DOMAIN), browser
via Playwright's --project flag.
| Old (pytest/Selenium) | New (Playwright) |
|---|---|
DOMAIN=test4 pytest tests/test_login.py |
npm run test:test4 / TEST_ENV=test4 npx playwright test |
DRIVER=Firefox pytest ... |
npm run test:firefox / npx playwright test --project=firefox |
# Environment shortcuts
npm run test:test # TEST_ENV=test
npm run test:test4 # TEST_ENV=test4
npm run test:stage1 # TEST_ENV=stage1 (staging.osf.io)
npm run test:stage2
npm run test:stage3 # default when TEST_ENV is unset
npm run test:stage4
npm run test:prod
# Browser shortcuts
npm run test:chromium
npm run test:firefox
npm run test:edge
npm run test:all-browsers
# Combine env + browser directly
TEST_ENV=test4 npx playwright test --project=firefox
# Just the login suite
npm run test:login
# View the HTML report after a run
npm run report
# Force trace recording for this run, regardless of the config's trace setting (view after with `npm run report` or `npx playwright show-trace`)
npx playwright test --project=chromium --trace on
# Interactive UI mode (watch/run tests with timeline, DOM, network, console)
npx playwright test --ui
Tests are tagged the same way the old suite used pytest markers:
@smoke (was smoke_test), @core (was core_functionality). Filter with:
npx playwright test --grep @smokedont_run_on_prod is ported as a conditional test.skip(settings.PRODUCTION, ...)
inside a beforeEach, so those tests show as skipped (not absent) when run
against TEST_ENV=prod.
config/
environments.ts # domain map (stage1-4, test, test4, prod) - port of the `domains` dict in settings.py
settings.ts # env-var driven settings - port of settings.py
src/
api/
session.ts # thin JSON:API wrapper around Playwright's APIRequestContext
osfApi.ts # port of the api/osf_api.py functions the fixtures below need
pages/
BasePage.ts # port of pages/base.py (Playwright locators auto-wait, so
# base/locators.py's WebElementWrapper/Locator machinery isn't needed)
LoginPage.ts # LoginPage, Login2FAPage, LoginToSPage, InstitutionalLoginPage,
# generic institution login pages, ForgotPasswordPage,
# UnsupportedInstitutionLoginPage, GenericCASPage,
# CASAuthorizationPage, and the old_login/login/safe_login*/
# accept_cookies/logout helper functions
LandingPage.ts
RegisterPage.ts
fixtures/
index.ts # port of tests/conftest.py fixtures via Playwright's test.extend
utils/
index.ts # port of the utils.py helpers the above depend on
tests/
login.spec.ts # port of tests/test_login.py
- Cross-browser is a Playwright
project(chromium/firefox/edge) instead of SeleniumDRIVER/BrowserStack config. BrowserStack/Remote execution was not ported in this stage - only local chromium/firefox/msedge. driverfixture is replaced by Playwright's built-inpagefixture; there's nolaunch_driver()equivalent to maintain.- Locator waiting: Playwright locators auto-wait, so page objects expose plain
Locatorgetters instead of the customLocator/WebElementWrapperwait logic frombase/locators.py. check_credentialsused to callpytest.exit()to abort the whole run on bad credentials; here it throws inside a fixture, which fails the current test with a clear message instead of aborting the whole run.login()/safe_login()/safe_login_short()had converged on an identical implementation in the Python source (withlogin()'s extra initialgoto()being a redundant double-navigation) - consolidated into one implementation, re-exported under all three names.defaultProjectPagefixture returns a minimal{ page, guid }stub rather than a fullProjectPageport -pages/project.py(~1600 lines) is a separate, much larger page object out of scope for this login-suite stage.- OAuth API tests (
OauthAPIclass in the original) are ported but skipped: that class was never actually collected by pytest (its name didn't start withTest, so it fell outside pytest's defaultpython_classespattern) - it's been dormant in the existing suite. Ported for parity, left skipped since it exercises real token issuance/revocation. - Only the fixtures and
api/osf_api.pyfunctions thatconftest.py's fixtures actually call have been ported; the rest ofosf_api.py(~2600 lines total) covers pages/tests well outside this stage's scope.