11import { describe , expect , it } from "@effect/vitest" ;
22import { Effect , Predicate } from "effect" ;
3+ import type * as Tracer from "effect/Tracer" ;
34
45import {
56 AuthTemplateSlug ,
@@ -29,6 +30,37 @@ const INTEG = IntegrationSlug.make("acme");
2930const TEMPLATE = AuthTemplateSlug . make ( "oauth" ) ;
3031const FIRST_PARTY = firstPartyOAuthClientSlug ( "acme" ) ;
3132
33+ const makeRecordingTracer = ( spans : Map < string , Map < string , unknown > > ) : Tracer . Tracer => ( {
34+ span : ( options ) => {
35+ const attributes = new Map < string , unknown > ( ) ;
36+ spans . set ( options . name , attributes ) ;
37+ let status : Tracer . SpanStatus = { _tag : "Started" , startTime : options . startTime } ;
38+ return {
39+ _tag : "Span" ,
40+ name : options . name ,
41+ spanId : "0000000000000001" ,
42+ traceId : "00000000000000000000000000000001" ,
43+ parent : options . parent ,
44+ annotations : options . annotations ,
45+ get status ( ) {
46+ return status ;
47+ } ,
48+ attributes,
49+ links : options . links ,
50+ sampled : options . sampled ,
51+ kind : options . kind ,
52+ end : ( endTime , exit ) => {
53+ status = { _tag : "Ended" , startTime : options . startTime , endTime, exit } ;
54+ } ,
55+ attribute : ( key , value ) => {
56+ attributes . set ( key , value ) ;
57+ } ,
58+ event : ( ) => undefined ,
59+ addLinks : ( ) => undefined ,
60+ } ;
61+ } ,
62+ } ) ;
63+
3264const oauthPlugin = definePlugin ( ( ) => ( {
3365 id : "acme" as const ,
3466 storage : ( ) => ( { } ) ,
@@ -81,8 +113,9 @@ const firstPartyClientFor = (server: {
81113describe ( "first-party oauth clients" , ( ) => {
82114 it . effect (
83115 "start → complete through a config-declared client mints an executable connection" ,
84- ( ) =>
85- Effect . scoped (
116+ ( ) => {
117+ const spans = new Map < string , Map < string , unknown > > ( ) ;
118+ return Effect . scoped (
86119 Effect . gen ( function * ( ) {
87120 const server = yield * serveOAuthTestServer ( { scopes : [ "read" ] } ) ;
88121 const { executor } = yield * makeTestWorkspaceHarness ( {
@@ -101,6 +134,9 @@ describe("first-party oauth clients", () => {
101134 template : TEMPLATE ,
102135 } ) ;
103136 expect ( started . status ) . toBe ( "redirect" ) ;
137+ expect (
138+ spans . get ( "test.oauth.first_party" ) ?. get ( "executor.oauth.client_first_party" ) ,
139+ ) . toBe ( true ) ;
104140 if ( started . status !== "redirect" ) return ;
105141
106142 const callback = yield * server . completeAuthorizationCodeFlow ( {
@@ -111,6 +147,9 @@ describe("first-party oauth clients", () => {
111147 code : callback . code ,
112148 } ) ;
113149 expect ( String ( connection . address ) ) . toBe ( "tools.acme.org.mainAccount" ) ;
150+ expect (
151+ spans . get ( "executor.oauth.complete" ) ?. get ( "executor.oauth.client_first_party" ) ,
152+ ) . toBe ( true ) ;
114153
115154 const out = ( yield * executor . execute (
116155 ToolAddress . make ( "tools.acme.org.mainAccount.whoami" ) ,
@@ -119,7 +158,11 @@ describe("first-party oauth clients", () => {
119158 expect ( out . token ) . toMatch ( / ^ a t _ / ) ;
120159 expect ( yield * server . acceptsAccessToken ( out . token ) ) . toBe ( true ) ;
121160 } ) ,
122- ) ,
161+ ) . pipe (
162+ Effect . withSpan ( "test.oauth.first_party" ) ,
163+ Effect . withTracer ( makeRecordingTracer ( spans ) ) ,
164+ ) ;
165+ } ,
123166 ) ;
124167
125168 it . effect ( "refresh resolves the config-declared client (no oauth_client row exists)" , ( ) =>
0 commit comments