Test sign-ins
Sign in as a made-up GitHub or Google account in your end-to-end tests, with the age, repositories or Workspace domain your rules look at, everywhere but production.
An app that judges people by their GitHub or Google account, such as a free service that wants a GitHub account at least a month old, needs tests that sign in as a young account, an old one, a Google Workspace account and a personal one. Real accounts can't be made to order. Test sign-ins can: turn them on for an app, and its sign-ins also offer test, which signs in as a made-up account your test describes.
They exist on Synq's stages other than production: preview, where your end-to-end tests run, and a local stack. Production never offers them, and refuses the switch.
Turning them on
Make or change the app with test_sign_ins:
{ "test_sign_ins": true }A machine app signs no one in, so it has none. From an MCP host or an agent, set_app_test_sign_ins turns them on or off (MCP tools). The audit log records each change as app.updated.
A test sign-in stands in for GitHub or Google, the providers the app takes: an app that takes GitHub and Google alone offers both, one that takes Google alone offers Google. The brand needn't have the provider turned on.
The account a test describes
| Field | What it is |
|---|---|
provider | github or google. |
account | The account's id for this test: lowercase letters, digits and dashes, at most 40. The same id is the same person again. |
username, email, name | Optional. GitHub's login, the address the provider gives (never verified at Synq) and a name. |
account_type | GitHub: User, Organization or Bot. User unless named. |
account_age_days | GitHub: how many days old the account is, 365 unless named. Or created_at, an ISO 8601 time, instead. |
public_repos, followers | GitHub: 1 and 0 unless named. |
email_verified | Google: whether Google checked the address, true unless named. |
workspace_domain | Google: the Workspace domain. A personal account unless named. |
The person it signs in is an ordinary user of the brand, with an identity at the provider. Their linked_accounts entry carries what the test said, and test: true:
{
"provider": "github",
"subject": "test-young-dev",
"username": "young-dev",
"details_read_at": "2026-10-23T09:12:40.000Z",
"account_type": "User",
"created_at": "2026-10-11T09:12:40.000Z",
"public_repos": 0,
"followers": 0,
"test": true
}On the hosted page
The sign-in page lists Test sign-in beside the other ways. Its form takes the fields above, so a browser test fills it in and submits it like any other sign-in.
Headless, on your app's own screens
An app that signs people in on its own screens gets tokens with no browser at all: synq_method=test, with each field as synq_test_<field>, on /authorize-challenge, signs in at once and answers with the authorization code. With @synqauth/js:
import { createSynqClient } from '@synqauth/js'
// Your test app: a native app with own_ui_sign_in and test_sign_ins on.
const synq = createSynqClient({ issuer, clientId, redirectUri })
const result = await synq.startSignIn().test.signIn({
provider: 'github',
account: 'young-dev',
accountAgeDays: 12,
publicRepos: 0,
})
// result.status is 'signed-in', with the session's tokens.The app needs own_ui_sign_in for this, as for any sign-in on its own screens. A test app of its own, beside your real one, keeps both settings out of the app people use.
What keeps them apart from real accounts
- Production never offers them, whatever an app says.
- Their subject starts with
test-, which no GitHub or Google account's ever does, so a test sign-in never signs in as a real account or takes one over. - Their address is never verified at Synq and never links to another account, whatever
email_verifiedsays: that is Google's word in the details alone. - Every linked account they make says
test: true. Refuse those wherever real people sign in, if your code ever runs against a stage that has them.