74 lines
3.7 KiB
TypeScript
74 lines
3.7 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { readFileSync } from "node:fs"
|
|
import { join } from "node:path"
|
|
|
|
const read = (relative: string) =>
|
|
readFileSync(join(import.meta.dir, "..", relative), "utf8")
|
|
|
|
/**
|
|
* Automations shipped out of preview, so there is no per-device preference.
|
|
* Den now advertises deployment-level availability through desktop config;
|
|
* Desktop must honor it across the route, runner, and proposal surface while
|
|
* requiring every deployment to opt in explicitly.
|
|
*/
|
|
describe("Automations availability", () => {
|
|
test("no preview feature flag remains in the local preferences", () => {
|
|
const source = read("src/react-app/kernel/local-provider.tsx")
|
|
expect(source).not.toContain("automations:")
|
|
|
|
const flags = read("src/react-app/domains/settings/state/feature-flags-preferences.ts")
|
|
expect(flags).not.toContain("automations")
|
|
})
|
|
|
|
test("the deployment gate stays off unless desktop config explicitly opts in", () => {
|
|
const availability = read("src/react-app/domains/automations/automation-availability.ts")
|
|
expect(availability).toContain("!loading && config.automationsEnabled === true")
|
|
})
|
|
|
|
test("the shell gates route, Den probe, and navigation on runtime and deployment availability", () => {
|
|
const source = read("src/react-app/shell/session-route.tsx")
|
|
expect(source).toContain("const automationDeploymentEnabled = useAutomationDeploymentEnabled()")
|
|
expect(source).toContain("const automationsEnabled = isDesktopRuntime() && automationDeploymentEnabled")
|
|
expect(source).not.toContain("featureFlags?.automations")
|
|
expect(source).toContain("automationsEnabled && automationsRouteRequested")
|
|
expect(source).toContain("!automationsEnabled || !denAuth.isSignedIn")
|
|
expect(source).toContain("automationsEnabled && automationsSupported")
|
|
})
|
|
|
|
test("the runner bridge registers only when the deployment contract allows it", () => {
|
|
const providers = read("src/react-app/shell/providers.tsx")
|
|
expect(providers).toContain("<AutomationRunnerBridge />")
|
|
expect(providers).not.toContain("featureFlags")
|
|
|
|
const bridge = read("src/react-app/domains/automations/automation-runner-bridge.tsx")
|
|
expect(bridge).toContain("!deploymentEnabled || status !== \"signed_in\"")
|
|
expect(bridge).toContain("[deploymentEnabled, status]")
|
|
expect(bridge).toContain('automationRunnerConfigure", null')
|
|
expect(bridge).toContain("onCredentialRejected?.(() => coordinator.credentialRejected())")
|
|
})
|
|
|
|
test("credential rejection crosses only the Automation runner Electron bridge", () => {
|
|
const main = read("../desktop/electron/main.mjs")
|
|
const preload = read("../desktop/electron/preload.mjs")
|
|
expect(main).toContain('"openwork:automation-runner:credential-rejected"')
|
|
expect(main).toContain("onCredentialRejected: () =>")
|
|
expect(preload).toContain("onCredentialRejected(callback)")
|
|
expect(preload).toContain("ipcRenderer.on(AUTOMATION_RUNNER_CREDENTIAL_REJECTED_EVENT, handler)")
|
|
})
|
|
|
|
test("the in-chat proposal tool blocks creation when the deployment disables Automations", () => {
|
|
const proposal = read("src/components/tools/openwork-automation-proposal.tsx")
|
|
expect(proposal).toContain("useAutomationDeploymentEnabled()")
|
|
expect(proposal).toContain("Automations are disabled for this deployment.")
|
|
expect(proposal).toContain("if (!automationsEnabled) return")
|
|
expect(proposal).toContain("Sign in to OpenWork Cloud")
|
|
expect(proposal).toContain("resolveProposalModel")
|
|
expect(proposal).toContain("data-automation-model-resolution")
|
|
})
|
|
|
|
test("the automations capability stays desktop-only", () => {
|
|
const controls = read("src/react-app/shell/control/control-provider.tsx")
|
|
expect(controls).toContain("...(isDesktopRuntime()")
|
|
})
|
|
})
|