refactor(websearch): rename search domain
This commit is contained in:
parent
97aa6713b5
commit
c86f4e9b9b
51 changed files with 478 additions and 462 deletions
|
|
@ -75,11 +75,11 @@ describe("Config", () => {
|
|||
})
|
||||
|
||||
const config = yield* ConfigGlobal.Service
|
||||
yield* config.update(["search"], { provider: "exa" })
|
||||
yield* config.update(["websearch"], { provider: "exa" })
|
||||
|
||||
const text = yield* Effect.promise(() => Bun.file(file).text())
|
||||
expect(text).toContain("// user config")
|
||||
expect(parse(text)).toEqual({ username: "tester", search: { provider: "exa" } })
|
||||
expect(parse(text)).toEqual({ username: "tester", websearch: { provider: "exa" } })
|
||||
}).pipe(
|
||||
Effect.provide(
|
||||
AppNodeBuilder.build(LayerNode.group([ConfigGlobal.node]), [
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ function resourceMcpLayer(url: string) {
|
|||
complete: unusedIntegration,
|
||||
cancel: unusedIntegration,
|
||||
},
|
||||
search: {
|
||||
websearch: {
|
||||
list: unusedIntegration,
|
||||
get: unusedIntegration,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -259,11 +259,11 @@ function registerIntegration(draft: Integration.Draft, definition: IntegrationDe
|
|||
}),
|
||||
)
|
||||
}
|
||||
if (!definition.search) return
|
||||
draft.search.update({
|
||||
if (!definition.websearch) return
|
||||
draft.websearch.update({
|
||||
integrationID,
|
||||
connection: definition.search.connection,
|
||||
execute: definition.search.execute,
|
||||
connection: definition.websearch.connection,
|
||||
execute: definition.websearch.execute,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,19 +95,19 @@ describe("fromPromise", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("adapts promise search capability execution", () =>
|
||||
it.effect("adapts promise web search capability execution", () =>
|
||||
Effect.gen(function* () {
|
||||
const integrations = yield* Integration.Service
|
||||
const plugin = yield* PluginV2.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
const promisePlugin = Plugin.define({
|
||||
id: "promise-search",
|
||||
id: "promise-websearch",
|
||||
setup: async (ctx) => {
|
||||
await ctx.integration.register({
|
||||
id: "promise-search",
|
||||
name: "Promise Search",
|
||||
methods: [{ type: "env", names: ["PROMISE_SEARCH_KEY"] }],
|
||||
search: {
|
||||
id: "promise-websearch",
|
||||
name: "Promise Web Search",
|
||||
methods: [{ type: "env", names: ["PROMISE_WEBSEARCH_KEY"] }],
|
||||
websearch: {
|
||||
connection: "optional",
|
||||
execute: async (input) => ({ text: `promise: ${input.query}` }),
|
||||
},
|
||||
|
|
@ -116,12 +116,12 @@ describe("fromPromise", () => {
|
|||
})
|
||||
|
||||
yield* PluginPromise.fromPromise(promisePlugin).effect(host)
|
||||
expect(yield* integrations.get(Integration.ID.make("promise-search"))).toMatchObject({
|
||||
name: "Promise Search",
|
||||
methods: [{ type: "env", names: ["PROMISE_SEARCH_KEY"] }],
|
||||
expect(yield* integrations.get(Integration.ID.make("promise-websearch"))).toMatchObject({
|
||||
name: "Promise Web Search",
|
||||
methods: [{ type: "env", names: ["PROMISE_WEBSEARCH_KEY"] }],
|
||||
})
|
||||
const provider = yield* integrations.search.get(Integration.ID.make("promise-search"))
|
||||
if (!provider) return yield* Effect.die("Expected promise search provider")
|
||||
const provider = yield* integrations.websearch.get(Integration.ID.make("promise-websearch"))
|
||||
if (!provider) return yield* Effect.die("Expected promise web search provider")
|
||||
expect(yield* provider.execute({ query: "effect" }, {})).toEqual({ text: "promise: effect" })
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ import { EventV2 } from "@opencode-ai/core/event"
|
|||
import { Integration } from "@opencode-ai/core/integration"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
export interface SearchRequest {
|
||||
export interface WebSearchRequest {
|
||||
readonly url: string
|
||||
readonly headers: Record<string, string>
|
||||
readonly body: unknown
|
||||
}
|
||||
|
||||
export const requests: SearchRequest[] = []
|
||||
export const requests: WebSearchRequest[] = []
|
||||
export const response = { body: "" }
|
||||
|
||||
export function resetSearchFixture(body: string) {
|
||||
export function resetWebSearchFixture(body: string) {
|
||||
requests.length = 0
|
||||
response.body = body
|
||||
}
|
||||
|
|
@ -36,6 +36,6 @@ const http = Layer.succeed(
|
|||
),
|
||||
)
|
||||
|
||||
export const searchIntegrationTest = testEffect(
|
||||
export const webSearchIntegrationTest = testEffect(
|
||||
Layer.merge(AppNodeBuilder.build(LayerNode.group([Integration.node, Credential.node, EventV2.node])), http),
|
||||
)
|
||||
|
|
@ -2,13 +2,13 @@ import { beforeEach, describe, expect } from "bun:test"
|
|||
import { Effect } from "effect"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { Integration } from "@opencode-ai/core/integration"
|
||||
import { SearchExa } from "@opencode-ai/core/plugin/search/exa"
|
||||
import { SearchParallel } from "@opencode-ai/core/plugin/search/parallel"
|
||||
import { WebSearchExa } from "@opencode-ai/core/plugin/websearch/exa"
|
||||
import { WebSearchParallel } from "@opencode-ai/core/plugin/websearch/parallel"
|
||||
import { host, integrationHost } from "./host"
|
||||
import { requests, resetSearchFixture, searchIntegrationTest } from "./search-fixture"
|
||||
import { requests, resetWebSearchFixture, webSearchIntegrationTest } from "./websearch-fixture"
|
||||
|
||||
beforeEach(() => {
|
||||
resetSearchFixture(
|
||||
resetWebSearchFixture(
|
||||
`event: message\ndata: ${JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: 1,
|
||||
|
|
@ -17,46 +17,46 @@ beforeEach(() => {
|
|||
)
|
||||
})
|
||||
|
||||
const it = searchIntegrationTest
|
||||
const it = webSearchIntegrationTest
|
||||
|
||||
describe("built-in search integrations", () => {
|
||||
it.effect("registers and disposes an atomic search integration", () =>
|
||||
describe("built-in web search integrations", () => {
|
||||
it.effect("registers and disposes an atomic web search integration", () =>
|
||||
Effect.gen(function* () {
|
||||
const integrations = yield* Integration.Service
|
||||
const registration = yield* integrationHost(integrations).register({
|
||||
id: "test-search",
|
||||
name: "Test Search",
|
||||
id: "test-websearch",
|
||||
name: "Test Web Search",
|
||||
methods: [{ type: "key", label: "API key" }],
|
||||
search: {
|
||||
websearch: {
|
||||
connection: "required",
|
||||
execute: (input) => Effect.succeed({ text: input.query }),
|
||||
},
|
||||
})
|
||||
|
||||
expect(yield* integrations.get(Integration.ID.make("test-search"))).toMatchObject({
|
||||
name: "Test Search",
|
||||
expect(yield* integrations.get(Integration.ID.make("test-websearch"))).toMatchObject({
|
||||
name: "Test Web Search",
|
||||
methods: [{ type: "key", label: "API key" }],
|
||||
search: { connection: "required" },
|
||||
websearch: { connection: "required" },
|
||||
})
|
||||
yield* registration.dispose
|
||||
expect(yield* integrations.get(Integration.ID.make("test-search"))).toBeUndefined()
|
||||
expect(yield* integrations.get(Integration.ID.make("test-websearch"))).toBeUndefined()
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("registers Exa with its MCP schema", () =>
|
||||
Effect.gen(function* () {
|
||||
const integrations = yield* Integration.Service
|
||||
yield* SearchExa.Plugin.effect(host({ integration: integrationHost(integrations) }))
|
||||
yield* WebSearchExa.Plugin.effect(host({ integration: integrationHost(integrations) }))
|
||||
|
||||
const info = yield* integrations.get(Integration.ID.make("exa"))
|
||||
expect(info).toMatchObject({
|
||||
id: "exa",
|
||||
name: "Exa",
|
||||
methods: [{ type: "key" }, { type: "env", names: ["EXA_API_KEY"] }],
|
||||
search: { connection: "optional" },
|
||||
websearch: { connection: "optional" },
|
||||
})
|
||||
const provider = yield* integrations.search.get(Integration.ID.make("exa"))
|
||||
if (!provider) return yield* Effect.die("Expected Exa search provider")
|
||||
const provider = yield* integrations.websearch.get(Integration.ID.make("exa"))
|
||||
if (!provider) return yield* Effect.die("Expected Exa web search provider")
|
||||
expect(
|
||||
yield* provider.execute(
|
||||
{ query: "effect typescript" },
|
||||
|
|
@ -65,7 +65,7 @@ describe("built-in search integrations", () => {
|
|||
).toEqual({ text: "search results", metadata: { searchTime: 123 } })
|
||||
expect(requests).toEqual([
|
||||
{
|
||||
url: `${SearchExa.endpoint}?exaApiKey=exa+secret`,
|
||||
url: `${WebSearchExa.endpoint}?exaApiKey=exa+secret`,
|
||||
headers: expect.any(Object),
|
||||
body: {
|
||||
jsonrpc: "2.0",
|
||||
|
|
@ -73,7 +73,7 @@ describe("built-in search integrations", () => {
|
|||
method: "tools/call",
|
||||
params: {
|
||||
name: "web_search_exa",
|
||||
arguments: { query: "effect typescript" },
|
||||
arguments: { query: "effect typescript", numResults: 8 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -83,7 +83,7 @@ describe("built-in search integrations", () => {
|
|||
|
||||
it.effect("registers Parallel and keeps its credential in the authorization header", () =>
|
||||
Effect.gen(function* () {
|
||||
resetSearchFixture(
|
||||
resetWebSearchFixture(
|
||||
JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: 1,
|
||||
|
|
@ -107,9 +107,9 @@ describe("built-in search integrations", () => {
|
|||
}),
|
||||
)
|
||||
const integrations = yield* Integration.Service
|
||||
yield* SearchParallel.Plugin.effect(host({ integration: integrationHost(integrations) }))
|
||||
const provider = yield* integrations.search.get(Integration.ID.make("parallel"))
|
||||
if (!provider) return yield* Effect.die("Expected Parallel search provider")
|
||||
yield* WebSearchParallel.Plugin.effect(host({ integration: integrationHost(integrations) }))
|
||||
const provider = yield* integrations.websearch.get(Integration.ID.make("parallel"))
|
||||
if (!provider) return yield* Effect.die("Expected Parallel web search provider")
|
||||
|
||||
const output = yield* provider.execute(
|
||||
{ query: "effect layers" },
|
||||
|
|
@ -136,7 +136,7 @@ describe("built-in search integrations", () => {
|
|||
},
|
||||
})
|
||||
expect(requests[0]).toMatchObject({
|
||||
url: SearchParallel.endpoint,
|
||||
url: WebSearchParallel.endpoint,
|
||||
headers: { authorization: "Bearer parallel-secret" },
|
||||
body: {
|
||||
jsonrpc: "2.0",
|
||||
|
|
@ -4,7 +4,7 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
|||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { Integration } from "@opencode-ai/core/integration"
|
||||
import { Search } from "@opencode-ai/core/search"
|
||||
import { WebSearch } from "@opencode-ai/core/websearch"
|
||||
import { SessionV2 } from "@opencode-ai/core/session"
|
||||
import { ToolRegistry } from "@opencode-ai/core/tool/registry"
|
||||
import { WebSearchTool } from "@opencode-ai/core/tool/websearch"
|
||||
|
|
@ -16,18 +16,18 @@ import { executeTool, registerToolPlugin, settleTool, toolDefinitions, toolIdent
|
|||
const webSearchToolNode = makeLocationNode({
|
||||
name: "test/websearch-tool-plugin",
|
||||
layer: Layer.effectDiscard(registerToolPlugin(WebSearchTool.Plugin)),
|
||||
deps: [ToolRegistry.toolsNode, PermissionV2.node, Search.node],
|
||||
deps: [ToolRegistry.toolsNode, PermissionV2.node, WebSearch.node],
|
||||
})
|
||||
|
||||
const sessionID = SessionV2.ID.make("ses_websearch_test")
|
||||
const assertions: PermissionV2.AssertInput[] = []
|
||||
const queries: Search.QueryInput[] = []
|
||||
let result = new Search.Result({ providerID: Integration.ID.make("exa"), text: "search results" })
|
||||
const queries: WebSearch.QueryInput[] = []
|
||||
let result = new WebSearch.Result({ providerID: Integration.ID.make("exa"), text: "search results" })
|
||||
|
||||
beforeEach(() => {
|
||||
assertions.length = 0
|
||||
queries.length = 0
|
||||
result = new Search.Result({ providerID: Integration.ID.make("exa"), text: "search results" })
|
||||
result = new WebSearch.Result({ providerID: Integration.ID.make("exa"), text: "search results" })
|
||||
})
|
||||
|
||||
const permission = Layer.succeed(
|
||||
|
|
@ -41,9 +41,9 @@ const permission = Layer.succeed(
|
|||
list: () => Effect.die("unused"),
|
||||
}),
|
||||
)
|
||||
const search = Layer.succeed(
|
||||
Search.Service,
|
||||
Search.Service.of({
|
||||
const websearch = Layer.succeed(
|
||||
WebSearch.Service,
|
||||
WebSearch.Service.of({
|
||||
selected: () => Effect.succeed(undefined),
|
||||
select: () => Effect.die("unused"),
|
||||
query: (input) =>
|
||||
|
|
@ -54,15 +54,15 @@ const search = Layer.succeed(
|
|||
}),
|
||||
)
|
||||
const it = testEffect(
|
||||
AppNodeBuilder.build(LayerNode.group([ToolRegistry.node, ToolRegistry.toolsNode, Search.node, webSearchToolNode]), [
|
||||
AppNodeBuilder.build(LayerNode.group([ToolRegistry.node, ToolRegistry.toolsNode, WebSearch.node, webSearchToolNode]), [
|
||||
[PermissionV2.node, permission],
|
||||
[Search.node, search],
|
||||
[WebSearch.node, websearch],
|
||||
[ToolOutputStore.node, ToolOutputStore.nodeWithoutConfig],
|
||||
]),
|
||||
)
|
||||
|
||||
describe("WebSearchTool registration", () => {
|
||||
it.effect("asserts permission before delegating to Search", () =>
|
||||
it.effect("asserts permission before delegating to WebSearch", () =>
|
||||
Effect.gen(function* () {
|
||||
const registry = yield* ToolRegistry.Service
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ describe("WebSearchTool registration", () => {
|
|||
|
||||
it.effect("keeps provider metadata in structured output", () =>
|
||||
Effect.gen(function* () {
|
||||
result = new Search.Result({
|
||||
result = new WebSearch.Result({
|
||||
providerID: Integration.ID.make("parallel"),
|
||||
text: "parallel results",
|
||||
metadata: { requestID: "req_1" },
|
||||
|
|
@ -124,7 +124,7 @@ describe("WebSearchTool registration", () => {
|
|||
|
||||
it.effect("uses the concise no-results fallback", () =>
|
||||
Effect.gen(function* () {
|
||||
result = new Search.Result({ providerID: Integration.ID.make("exa"), text: "" })
|
||||
result = new WebSearch.Result({ providerID: Integration.ID.make("exa"), text: "" })
|
||||
const registry = yield* ToolRegistry.Service
|
||||
|
||||
expect(
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
|||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Config } from "@opencode-ai/core/config"
|
||||
import { ConfigGlobal } from "@opencode-ai/core/config/global"
|
||||
import { ConfigSearch } from "@opencode-ai/core/config/search"
|
||||
import { ConfigWebSearch } from "@opencode-ai/core/config/websearch"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
import { Form } from "@opencode-ai/core/form"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Integration } from "@opencode-ai/core/integration"
|
||||
import { Search } from "@opencode-ai/core/search"
|
||||
import { WebSearch } from "@opencode-ai/core/websearch"
|
||||
import { testEffect } from "./lib/effect"
|
||||
|
||||
let entries: Config.Entry[] = []
|
||||
|
|
@ -23,7 +23,7 @@ const configGlobal = Layer.succeed(
|
|||
)
|
||||
const it = testEffect(
|
||||
AppNodeBuilder.build(
|
||||
LayerNode.group([Search.node, Integration.node, Credential.node, EventV2.node, Form.node, ConfigGlobal.node]),
|
||||
LayerNode.group([WebSearch.node, Integration.node, Credential.node, EventV2.node, Form.node, ConfigGlobal.node]),
|
||||
[
|
||||
[Config.node, config],
|
||||
[ConfigGlobal.node, configGlobal],
|
||||
|
|
@ -35,10 +35,10 @@ const register = (id: string, connection: "optional" | "required" = "optional")
|
|||
Effect.gen(function* () {
|
||||
const integrations = yield* Integration.Service
|
||||
const integrationID = Integration.ID.make(id)
|
||||
const calls: { input: Search.Input; credential?: Credential.Value; sessionID?: string }[] = []
|
||||
const calls: { input: WebSearch.Input; credential?: Credential.Value; sessionID?: string }[] = []
|
||||
yield* integrations.transform((draft) => {
|
||||
draft.update(integrationID, (integration) => (integration.name = id.toUpperCase()))
|
||||
draft.search.update({
|
||||
draft.websearch.update({
|
||||
integrationID,
|
||||
connection,
|
||||
execute: (input, context) =>
|
||||
|
|
@ -56,20 +56,20 @@ beforeEach(() => {
|
|||
writes.length = 0
|
||||
})
|
||||
|
||||
describe("Search", () => {
|
||||
describe("WebSearch", () => {
|
||||
it.effect("executes an explicit provider without changing the default", () =>
|
||||
Effect.gen(function* () {
|
||||
const provider = yield* register("exa")
|
||||
const search = yield* Search.Service
|
||||
const websearch = yield* WebSearch.Service
|
||||
|
||||
expect(yield* search.query({ query: "effect", providerID: provider.integrationID })).toEqual(
|
||||
new Search.Result({
|
||||
expect(yield* websearch.query({ query: "effect", providerID: provider.integrationID })).toEqual(
|
||||
new WebSearch.Result({
|
||||
providerID: provider.integrationID,
|
||||
text: "exa: effect",
|
||||
metadata: { id: "exa" },
|
||||
}),
|
||||
)
|
||||
expect(yield* search.selected()).toBeUndefined()
|
||||
expect(yield* websearch.selected()).toBeUndefined()
|
||||
expect(provider.calls).toEqual([
|
||||
{
|
||||
input: { query: "effect", providerID: provider.integrationID },
|
||||
|
|
@ -84,29 +84,31 @@ describe("Search", () => {
|
|||
Effect.gen(function* () {
|
||||
yield* register("exa")
|
||||
const parallel = yield* register("parallel")
|
||||
const search = yield* Search.Service
|
||||
yield* search.select(parallel.integrationID)
|
||||
const websearch = yield* WebSearch.Service
|
||||
yield* websearch.select(parallel.integrationID)
|
||||
|
||||
expect((yield* search.query({ query: "layers" })).providerID).toBe(parallel.integrationID)
|
||||
expect(yield* search.selected()).toBe(parallel.integrationID)
|
||||
expect(writes).toEqual([{ path: ["search"], value: new ConfigSearch.Info({ provider: parallel.integrationID }) }])
|
||||
expect((yield* websearch.query({ query: "layers" })).providerID).toBe(parallel.integrationID)
|
||||
expect(yield* websearch.selected()).toBe(parallel.integrationID)
|
||||
expect(writes).toEqual([
|
||||
{ path: ["websearch"], value: new ConfigWebSearch.Info({ provider: parallel.integrationID }) },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("reads the selected provider from global config", () =>
|
||||
Effect.gen(function* () {
|
||||
const provider = yield* register("exa")
|
||||
const search = yield* Search.Service
|
||||
const websearch = yield* WebSearch.Service
|
||||
entries = [
|
||||
new Config.Document({
|
||||
type: "document",
|
||||
path: path.join(Global.Path.config, "opencode.json"),
|
||||
info: new Config.Info({ search: new ConfigSearch.Info({ provider: provider.integrationID }) }),
|
||||
info: new Config.Info({ websearch: new ConfigWebSearch.Info({ provider: provider.integrationID }) }),
|
||||
}),
|
||||
]
|
||||
|
||||
expect(yield* search.selected()).toBe(provider.integrationID)
|
||||
expect((yield* search.query({ query: "configured" })).providerID).toBe(provider.integrationID)
|
||||
expect(yield* websearch.selected()).toBe(provider.integrationID)
|
||||
expect((yield* websearch.query({ query: "configured" })).providerID).toBe(provider.integrationID)
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -114,29 +116,29 @@ describe("Search", () => {
|
|||
Effect.gen(function* () {
|
||||
const exa = yield* register("exa")
|
||||
const parallel = yield* register("parallel")
|
||||
const search = yield* Search.Service
|
||||
yield* search.select(exa.integrationID)
|
||||
const websearch = yield* WebSearch.Service
|
||||
yield* websearch.select(exa.integrationID)
|
||||
entries = [
|
||||
new Config.Document({
|
||||
type: "document",
|
||||
info: new Config.Info({ search: new ConfigSearch.Info({ provider: parallel.integrationID }) }),
|
||||
info: new Config.Info({ websearch: new ConfigWebSearch.Info({ provider: parallel.integrationID }) }),
|
||||
}),
|
||||
]
|
||||
|
||||
expect((yield* search.query({ query: "configured" })).providerID).toBe(parallel.integrationID)
|
||||
expect((yield* websearch.query({ query: "configured" })).providerID).toBe(parallel.integrationID)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("serializes concurrent first-use onboarding and persists the answer", () =>
|
||||
Effect.gen(function* () {
|
||||
const provider = yield* register("exa")
|
||||
const search = yield* Search.Service
|
||||
const websearch = yield* WebSearch.Service
|
||||
const forms = yield* Form.Service
|
||||
const first = yield* search.query({ query: "one", sessionID: "ses_search" }).pipe(Effect.forkChild)
|
||||
const second = yield* search.query({ query: "two", sessionID: "ses_search" }).pipe(Effect.forkChild)
|
||||
const first = yield* websearch.query({ query: "one", sessionID: "ses_websearch" }).pipe(Effect.forkChild)
|
||||
const second = yield* websearch.query({ query: "two", sessionID: "ses_websearch" }).pipe(Effect.forkChild)
|
||||
yield* Effect.yieldNow
|
||||
|
||||
const pending = yield* forms.list({ sessionID: "ses_search" })
|
||||
const pending = yield* forms.list({ sessionID: "ses_websearch" })
|
||||
expect(pending).toHaveLength(1)
|
||||
const form = pending[0]
|
||||
if (!form) return yield* Effect.die("Expected an onboarding form")
|
||||
|
|
@ -144,18 +146,18 @@ describe("Search", () => {
|
|||
|
||||
expect((yield* Fiber.join(first)).providerID).toBe(provider.integrationID)
|
||||
expect((yield* Fiber.join(second)).providerID).toBe(provider.integrationID)
|
||||
expect(yield* search.selected()).toBe(provider.integrationID)
|
||||
expect(yield* websearch.selected()).toBe(provider.integrationID)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("requires a connection before invoking a required provider", () =>
|
||||
Effect.gen(function* () {
|
||||
const provider = yield* register("private", "required")
|
||||
const search = yield* Search.Service
|
||||
const websearch = yield* WebSearch.Service
|
||||
|
||||
expect(
|
||||
yield* search.query({ query: "secret", providerID: provider.integrationID }).pipe(Effect.flip),
|
||||
).toBeInstanceOf(Search.ConnectionRequiredError)
|
||||
yield* websearch.query({ query: "secret", providerID: provider.integrationID }).pipe(Effect.flip),
|
||||
).toBeInstanceOf(WebSearch.ConnectionRequiredError)
|
||||
expect(provider.calls).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
|
@ -165,9 +167,9 @@ describe("Search", () => {
|
|||
const integrations = yield* Integration.Service
|
||||
const scope = yield* Scope.fork(yield* Scope.Scope)
|
||||
const provider = yield* register("temporary").pipe(Scope.provide(scope))
|
||||
expect(yield* integrations.search.get(provider.integrationID)).toBeDefined()
|
||||
expect(yield* integrations.websearch.get(provider.integrationID)).toBeDefined()
|
||||
yield* Scope.close(scope, Exit.void)
|
||||
expect(yield* integrations.search.get(provider.integrationID)).toBeUndefined()
|
||||
expect(yield* integrations.websearch.get(provider.integrationID)).toBeUndefined()
|
||||
}),
|
||||
)
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue