import assert from 'node:assert/strict'
import { test } from 'node:test'
import { resolveIntegrationName, resolveSecretName } from './setup.ts'
import {
accessTokenSetupUrl,
clampPageSize,
clientSecretSetupUrl,
inferOperation,
isReadOnlyQuery,
oauthConnectUrl,
scopeForOperation,
} from './setup.ts'
import { todayBounds } from './today.ts'
test('todayBounds uses the Pacific Product Hunt day', () => {
const bounds = todayBounds('America/Los_Angeles', new Date('2026-08-22T18:00:00.000Z'))
assert.equal(bounds.day, '2026-08-22')
assert.equal(bounds.timeZone, 'America/Los_Angeles')
assert.ok(Date.parse(bounds.postedAfter) < Date.parse(bounds.postedBefore))
assert.match(bounds.postedAfter, /T/)
})
test('clampPageSize stays in the Product Hunt 1-20 range', () => {
assert.equal(clampPageSize(undefined), 10)
assert.equal(clampPageSize(1), 1)
assert.equal(clampPageSize(20), 20)
assert.equal(clampPageSize(99), 20)
assert.equal(clampPageSize(0), 1)
})
test('GraphQL mutation documents are not read-only', () => {
assert.equal(inferOperation('query { posts { edges { node { id } } } }'), 'query')
assert.equal(inferOperation('mutation { userFollow(input: { userId: "x" }) { user { id } } }'), 'mutation')
assert.equal(isReadOnlyQuery('query { viewer { user { id } } }'), true)
assert.equal(isReadOnlyQuery('mutation Foo { goalCreate(input: { title: "x" }) { goal { id } } }'), false)
assert.equal(scopeForOperation('query'), 'public')
assert.equal(scopeForOperation('mutation'), 'write')
})
test('setup URLs are prefilled for OAuth and secrets', () => {
const connect = oauthConnectUrl('producthunt')
assert.match(connect, /^https:\/\/kody\.codes\/connect\/oauth\?/)
assert.match(connect, /provider=producthunt/)
assert.match(connect, /scopes=public(\+|%20)private/)
assert.match(connect, /api\.producthunt\.com/)
assert.match(accessTokenSetupUrl(), /name=producthuntAccessToken/)
assert.match(accessTokenSetupUrl(), /allowedHosts=api\.producthunt\.com/)
assert.match(clientSecretSetupUrl(), /name=producthuntClientSecret/)
})
test('account aliases stay generic and unscoped to a person', () => {
assert.equal(resolveIntegrationName({}), 'producthunt')
assert.equal(resolveIntegrationName({ account: 'work' }), 'producthunt-work')
assert.equal(resolveSecretName({ account: 'work' }), 'producthuntAccessToken-work')
assert.equal(resolveSecretName({}), 'producthuntAccessToken')
})