Skip to content
← Public packages

@kentcdodds/audible

Personal Audible library app — browser re-auth, library, wishlist, NAS archive stub.

src/__tests__/login.test.ts

69 lines · 2.2 KB · TypeScript
import assert from 'node:assert/strict'
import { test } from 'node:test'
import {
	buildOAuthUrl,
	createCodeVerifier,
	createS256CodeChallenge,
	extractAuthorizationCode,
	shortAuthSessionId,
	buildClientId,
	buildDeviceSerial,
} from '../login.ts'

test('createCodeVerifier is url-safe and unpadded', () => {
	const v = createCodeVerifier()
	assert.match(v, /^[A-Za-z0-9_-]+$/)
	assert.ok(v.length >= 32)
})

test('S256 challenge is deterministic for a verifier', async () => {
	const verifier = 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'
	const a = await createS256CodeChallenge(verifier)
	const b = await createS256CodeChallenge(verifier)
	assert.equal(a, b)
	assert.match(a, /^[A-Za-z0-9_-]+$/)
})

test('buildOAuthUrl defaults to US amazon maplanding + PKCE', async () => {
	const verifier = createCodeVerifier()
	const { loginUrl, serial, locale } = await buildOAuthUrl({
		codeVerifier: verifier,
		locale: 'us',
	})
	assert.equal(locale.countryCode, 'us')
	assert.ok(serial.length >= 16)
	const url = new URL(loginUrl)
	assert.equal(url.hostname, 'www.amazon.com')
	assert.equal(url.pathname, '/ap/signin')
	assert.equal(url.searchParams.get('openid.oa2.response_type'), 'code')
	assert.equal(url.searchParams.get('openid.oa2.code_challenge_method'), 'S256')
	assert.ok(url.searchParams.get('openid.oa2.code_challenge'))
	assert.equal(
		url.searchParams.get('openid.return_to'),
		'https://www.amazon.com/ap/maplanding',
	)
	assert.match(url.searchParams.get('openid.oa2.client_id') || '', /^device:/)
})

test('extractAuthorizationCode reads maplanding query', () => {
	const code = extractAuthorizationCode(
		'https://www.amazon.com/ap/maplanding?openid.oa2.authorization_code=ABC123&foo=1',
	)
	assert.equal(code, 'ABC123')
})

test('extractAuthorizationCode rejects missing code', () => {
	assert.throws(() => extractAuthorizationCode('https://www.amazon.com/ap/maplanding?x=1'))
})

test('buildClientId embeds device type', () => {
	const serial = buildDeviceSerial()
	const id = buildClientId(serial)
	assert.match(id, /^[0-9a-f]+$/)
	assert.ok(id.length > serial.length)
})

test('shortAuthSessionId is compact hex', () => {
	const id = shortAuthSessionId()
	assert.match(id, /^[0-9a-f]{12}$/)
})