1- import type { AnyMessage , MethodInfo , PartialMessage , ServiceType } from '@bufbuild/protobuf' ;
2- import type { UnaryResponse } from '@connectrpc/connect' ;
3- import { createConnectTransport } from '@connectrpc/connect-node' ;
41import * as grpcReflection from 'grpc-reflection-js' ;
52import protobuf from 'protobufjs' ;
6- import { beforeEach , describe , expect , it , vi } from 'vitest' ;
3+ import { beforeEach , describe , expect , it , type Mock , vi } from 'vitest' ;
74
85import { loadMethodsFromReflection } from '../grpc' ;
96
107vi . mock ( 'grpc-reflection-js' ) ;
11- vi . mock ( '@connectrpc/connect-node' ) ;
128
139describe ( 'loadMethodsFromReflection' , ( ) => {
1410 describe ( 'one service reflection' , ( ) => {
1511 beforeEach ( ( ) => {
1612 // we want to test that the values that are passed to axios are returned in the config key
17- ( grpcReflection . Client as unknown as vi . Mock ) . mockImplementation ( ( ) => ( {
18- listServices : ( ) => Promise . resolve ( [ 'FooService' ] ) ,
19- fileContainingSymbol : async ( ) => {
20- const parsed = protobuf . parse ( `
13+ ( grpcReflection . Client as unknown as Mock ) . mockImplementation ( function ( ) {
14+ return {
15+ listServices : ( ) => Promise . resolve ( [ 'FooService' ] ) ,
16+ fileContainingSymbol : async ( ) => {
17+ const parsed = protobuf . parse ( `
2118 syntax = "proto3";
2219
2320 message FooRequest {
@@ -31,16 +28,18 @@ describe('loadMethodsFromReflection', () => {
3128 service FooService {
3229 rpc Foo (FooRequest) returns (FooResponse);
3330 }` ) ;
34- return parsed . root ;
35- } ,
36- } ) ) ;
31+ return parsed . root ;
32+ } ,
33+ } ;
34+ } ) ;
3735 } ) ;
3836
3937 it ( 'parses methods' , async ( ) => {
4038 const methods = await loadMethodsFromReflection ( {
4139 url : 'foo.com' ,
4240 metadata : [ ] ,
4341 reflectionApi : { enabled : false , apiKey : '' , url : '' , module : '' } ,
42+ rejectUnauthorized : true ,
4443 } ) ;
4544 expect ( methods ) . toStrictEqual ( [
4645 {
@@ -57,10 +56,11 @@ describe('loadMethodsFromReflection', () => {
5756 describe ( 'format service reflection' , ( ) => {
5857 beforeEach ( ( ) => {
5958 // we want to test that the values that are passed to axios are returned in the config key
60- ( grpcReflection . Client as unknown as vi . Mock ) . mockImplementation ( ( ) => ( {
61- listServices : ( ) => Promise . resolve ( [ 'FooService' ] ) ,
62- fileContainingSymbol : async ( ) => {
63- const parsed = protobuf . parse ( `
59+ ( grpcReflection . Client as unknown as Mock ) . mockImplementation ( function ( ) {
60+ return {
61+ listServices : ( ) => Promise . resolve ( [ 'FooService' ] ) ,
62+ fileContainingSymbol : async ( ) => {
63+ const parsed = protobuf . parse ( `
6464 syntax = "proto3";
6565
6666 message FooRequest {
@@ -74,16 +74,18 @@ describe('loadMethodsFromReflection', () => {
7474 service FooService {
7575 rpc format (FooRequest) returns (FooResponse);
7676 }` ) ;
77- return parsed . root ;
78- } ,
79- } ) ) ;
77+ return parsed . root ;
78+ } ,
79+ } ;
80+ } ) ;
8081 } ) ;
8182
8283 it ( 'parses methods' , async ( ) => {
8384 const methods = await loadMethodsFromReflection ( {
8485 url : 'foo.com' ,
8586 metadata : [ ] ,
8687 reflectionApi : { enabled : false , apiKey : '' , url : '' , module : '' } ,
88+ rejectUnauthorized : true ,
8789 } ) ;
8890 expect ( methods ) . toStrictEqual ( [
8991 {
@@ -100,10 +102,11 @@ describe('loadMethodsFromReflection', () => {
100102 describe ( 'multiple service reflection' , ( ) => {
101103 beforeEach ( ( ) => {
102104 // we want to test that the values that are passed to axios are returned in the config key
103- ( grpcReflection . Client as unknown as vi . Mock ) . mockImplementation ( ( ) => ( {
104- listServices : ( ) => Promise . resolve ( [ 'FooService' , 'BarService' ] ) ,
105- fileContainingSymbol : async ( ) => {
106- const parsed = protobuf . parse ( `
105+ ( grpcReflection . Client as unknown as Mock ) . mockImplementation ( function ( ) {
106+ return {
107+ listServices : ( ) => Promise . resolve ( [ 'FooService' , 'BarService' ] ) ,
108+ fileContainingSymbol : async ( ) => {
109+ const parsed = protobuf . parse ( `
107110 syntax = "proto3";
108111
109112 message FooRequest {
@@ -129,16 +132,18 @@ describe('loadMethodsFromReflection', () => {
129132 service BarService {
130133 rpc Bar (BarRequest) returns (BarResponse);
131134 }` ) ;
132- return parsed . root ;
133- } ,
134- } ) ) ;
135+ return parsed . root ;
136+ } ,
137+ } ;
138+ } ) ;
135139 } ) ;
136140
137141 it ( 'parses methods' , async ( ) => {
138142 const methods = await loadMethodsFromReflection ( {
139143 url : 'foo-bar.com' ,
140144 metadata : [ ] ,
141145 reflectionApi : { enabled : false , apiKey : '' , url : '' , module : '' } ,
146+ rejectUnauthorized : true ,
142147 } ) ;
143148 expect ( methods ) . toStrictEqual ( [
144149 {
@@ -161,60 +166,49 @@ describe('loadMethodsFromReflection', () => {
161166
162167 describe ( 'buf reflection api' , ( ) => {
163168 it ( 'loads module' , async ( ) => {
164- ( createConnectTransport as unknown as vi . Mock ) . mockImplementation ( options => {
165- expect ( options . baseUrl ) . toStrictEqual ( 'https://buf.build' ) ;
166- return {
167- async unary (
168- service : ServiceType ,
169- method : MethodInfo ,
170- _ : AbortSignal | undefined ,
171- __ : number | undefined ,
172- header : HeadersInit | undefined ,
173- input : PartialMessage < AnyMessage > ,
174- ) : Promise < UnaryResponse > {
175- expect ( new Headers ( header ) . get ( 'Authorization' ) ) . toStrictEqual ( 'Bearer TEST_KEY' ) ;
176- expect ( input ) . toStrictEqual ( { module : 'buf.build/connectrpc/eliza' } ) ;
177- return {
178- service : service ,
179- method : method ,
180- header : new Headers ( ) ,
181- trailer : new Headers ( ) ,
182- stream : false ,
183- // Output of running `buf curl https://buf.build/buf.reflect.v1beta1.FileDescriptorSetService/GetFileDescriptorSet --data '{"module": "buf.build/connectrpc/eliza"}' --schema buf.build/bufbuild/reflect -H 'Authorization: Bearer buf-token'`
184- message : method . O . fromJsonString (
185- '{"fileDescriptorSet":{"file":[{"name":"connectrpc/eliza/v1/eliza.proto","package":"connectrpc.eliza.v1","messageType":[{"name":"SayRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"SayResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"IntroduceRequest","field":[{"name":"name","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"name"}]},{"name":"IntroduceResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]}],"service":[{"name":"ElizaService","method":[{"name":"Say","inputType":".connectrpc.eliza.v1.SayRequest","outputType":".connectrpc.eliza.v1.SayResponse","options":{"idempotencyLevel":"NO_SIDE_EFFECTS"}},{"name":"Converse","inputType":".connectrpc.eliza.v1.ConverseRequest","outputType":".connectrpc.eliza.v1.ConverseResponse","options":{},"clientStreaming":true,"serverStreaming":true},{"name":"Introduce","inputType":".connectrpc.eliza.v1.IntroduceRequest","outputType":".connectrpc.eliza.v1.IntroduceResponse","options":{},"serverStreaming":true}]}],"syntax":"proto3"}]},"version":"233fca715f49425581ec0a1b660be886"}' ,
186- ) ,
187- } ;
188- } ,
189- } ;
169+ const bufReflectJson = '{"fileDescriptorSet":{"file":[{"name":"connectrpc/eliza/v1/eliza.proto","package":"connectrpc.eliza.v1","messageType":[{"name":"SayRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"SayResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseRequest","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"ConverseResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]},{"name":"IntroduceRequest","field":[{"name":"name","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"name"}]},{"name":"IntroduceResponse","field":[{"name":"sentence","number":1,"label":"LABEL_OPTIONAL","type":"TYPE_STRING","jsonName":"sentence"}]}],"service":[{"name":"ElizaService","method":[{"name":"Say","inputType":".connectrpc.eliza.v1.SayRequest","outputType":".connectrpc.eliza.v1.SayResponse","options":{"idempotencyLevel":"NO_SIDE_EFFECTS"}},{"name":"Converse","inputType":".connectrpc.eliza.v1.ConverseRequest","outputType":".connectrpc.eliza.v1.ConverseResponse","options":{},"clientStreaming":true,"serverStreaming":true},{"name":"Introduce","inputType":".connectrpc.eliza.v1.IntroduceRequest","outputType":".connectrpc.eliza.v1.IntroduceResponse","options":{},"serverStreaming":true}]}],"syntax":"proto3"}]},"version":"233fca715f49425581ec0a1b660be886"}' ;
170+ const fetchMock = vi . spyOn ( globalThis , 'fetch' ) . mockImplementation ( async ( input , init ) => {
171+ expect ( String ( input ) ) . toStrictEqual ( 'https://buf.build/buf.reflect.v1beta1.FileDescriptorSetService/GetFileDescriptorSet' ) ;
172+ expect ( init ?. method ) . toStrictEqual ( 'POST' ) ;
173+ expect ( JSON . parse ( String ( init ?. body ) ) ) . toStrictEqual ( { module : 'buf.build/connectrpc/eliza' } ) ;
174+ expect ( new Headers ( init ?. headers as HeadersInit ) . get ( 'Authorization' ) ) . toStrictEqual ( 'Bearer TEST_KEY' ) ;
175+ return new Response ( bufReflectJson , {
176+ status : 200 ,
177+ headers : { 'Content-Type' : 'application/json' } ,
178+ } ) ;
190179 } ) ;
191- const methods = await loadMethodsFromReflection ( {
192- url : 'foo.com' ,
193- metadata : [ ] ,
194- reflectionApi : {
195- enabled : true ,
196- apiKey : 'TEST_KEY' ,
197- url : 'https://buf.build' ,
198- module : 'buf.build/connectrpc/eliza' ,
199- } ,
200- } ) ;
201- expect ( methods ) . toStrictEqual ( [
202- {
203- example : undefined ,
204- fullPath : '/connectrpc.eliza.v1.ElizaService/Say' ,
205- type : 'unary' ,
206- } ,
207- {
208- example : undefined ,
209- fullPath : '/connectrpc.eliza.v1.ElizaService/Converse' ,
210- type : 'bidi' ,
211- } ,
212- {
213- example : undefined ,
214- fullPath : '/connectrpc.eliza.v1.ElizaService/Introduce' ,
215- type : 'server' ,
216- } ,
217- ] ) ;
180+ try {
181+ const methods = await loadMethodsFromReflection ( {
182+ url : 'foo.com' ,
183+ metadata : [ ] ,
184+ rejectUnauthorized : true ,
185+ reflectionApi : {
186+ enabled : true ,
187+ apiKey : 'TEST_KEY' ,
188+ url : 'https://buf.build' ,
189+ module : 'buf.build/connectrpc/eliza' ,
190+ } ,
191+ } ) ;
192+ expect ( methods ) . toStrictEqual ( [
193+ {
194+ example : undefined ,
195+ fullPath : '/connectrpc.eliza.v1.ElizaService/Say' ,
196+ type : 'unary' ,
197+ } ,
198+ {
199+ example : undefined ,
200+ fullPath : '/connectrpc.eliza.v1.ElizaService/Converse' ,
201+ type : 'bidi' ,
202+ } ,
203+ {
204+ example : undefined ,
205+ fullPath : '/connectrpc.eliza.v1.ElizaService/Introduce' ,
206+ type : 'server' ,
207+ } ,
208+ ] ) ;
209+ } finally {
210+ fetchMock . mockRestore ( ) ;
211+ }
218212 } ) ;
219213 } ) ;
220214} ) ;
0 commit comments