Plan — BJ-12 Unit tests for Atlassian OAuth auth providers#
Summary#
Add Jest unit specs for BitbucketOAuthAuthProvider and JiraOAuthAuthProvider covering cold fetch, caching, near-expiry refresh, concurrent dedup, refresh-token rotation persistence, 401 error propagation, and getBotUsername(). Mirror the existing github-app-auth.provider.spec.ts pattern — fetch spy + mocked ConfigService/AtlassianOAuthStateRepo, no real network.
Files#
| Path | Action | Description |
|---|---|---|
src/atlassian/bitbucket-oauth-auth.provider.spec.ts | create | Unit tests for Bitbucket OAuth provider |
src/atlassian/jira-oauth-auth.provider.spec.ts | create | Unit tests for Jira OAuth provider |
Steps#
- Inspect merged
AtlassianOAuthAuthProviderbase (#541),BitbucketOAuthAuthProvider(#542),JiraOAuthAuthProvider(#543), andAtlassianOAuthStateRepo(#544) to confirm exact method signatures, config keys, token endpoints, and state-repo API before writing assertions. - Create
src/atlassian/bitbucket-oauth-auth.provider.spec.ts— build a reusablecreateConfigProvider()keyed toBITBUCKET_OAUTH_CLIENT_ID,_CLIENT_SECRET,_REFRESH_TOKEN,BITBUCKET_BOT_USERNAME(plus any additional keys the provider reads); mockAtlassianOAuthStateRepowith jest mocks forloadState()/saveState()(or equivalent). - Add test cases in the Bitbucket spec: (a) cold
getToken()posts tohttps://bitbucket.org/site/oauth2/access_tokenwithgrant_type=refresh_token, returns access token, caches it; (b) repeat call within expiry is cache hit — zero additionalfetchcalls; (c) call with<5 minremaining triggers refresh; (d) threePromise.allcallers produce exactly onefetch; (e) rotated refresh token is persisted via the state repo; (f) HTTP 401 throws a descriptive error; (g)getBotUsername()returns configured value; (h)platform === 'bitbucket'. - Create
src/atlassian/jira-oauth-auth.provider.spec.ts— same structure, swap config keys toJIRA_OAUTH_*/JIRA_BOT_USERNAME, assert token endpointhttps://auth.atlassian.com/oauth/token,platform === 'jira'. - Use the existing
jest.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(...))pattern fromsrc/github/github-app-auth.provider.spec.ts— the repo has nonockdependency; a fetch spy is the established convention and satisfies the "no network in CI" criterion. - Run
npm run test -- src/atlassianandnpm run lint; confirmnpm run test:covshows >90% branch coverage for both providers.
Verification#
- Both spec files pass under
npm run test;npm run lintreports zero warnings. npm run test:covbranch coverage > 90% for both provider source files.- Grep confirms no production source edits outside
src/atlassian/*.spec.ts.
Risks#
- Dependencies #541/#542/#543/#544 are still OPEN on
rc/atlassian-integration; implementation must wait until the provider + state-repo files land or the specs will fail to compile. Flag as BLOCKED at Step 1 if not present. - State-repo API (method names, signatures for refresh-token rotation persistence) is not yet frozen — spec assertions must be aligned to the merged implementation, not to assumptions in this plan.
Assumptions#
- Refresh-token rotation edge: server always returns a new refresh token on success (per issue edge case note).
- Expiry boundary uses
<(strict) at T-5 min (per issue edge case note). - Existing
fetch-spy pattern is acceptable in place ofnock— both satisfy the "no network in CI" acceptance criterion.