11import { expect } from "chai" ;
2+ import * as sinon from "sinon" ;
23
34import * as runv2 from "./runv2" ;
45import * as backend from "../deploy/functions/backend" ;
56import { latest } from "../deploy/functions/runtimes/supported" ;
67import { CODEBASE_LABEL } from "../functions/constants" ;
8+ import { Client } from "../apiv2" ;
9+ import { FirebaseError } from "../error" ;
710
811describe ( "runv2" , ( ) => {
912 const PROJECT_ID = "project-id" ;
@@ -201,13 +204,11 @@ describe("runv2", () => {
201204 const service : Omit < runv2 . Service , runv2 . ServiceOutputFields > = {
202205 ...BASE_RUN_SERVICE ,
203206 name : `projects/${ PROJECT_ID } /locations/${ LOCATION } /services/${ SERVICE_ID } ` ,
204- labels : {
205- [ runv2 . RUNTIME_LABEL ] : latest ( "nodejs" ) ,
206- } ,
207207 annotations : {
208208 ...BASE_RUN_SERVICE . annotations ,
209209 [ runv2 . FUNCTION_ID_ANNOTATION ] : FUNCTION_ID , // Using FUNCTION_ID_ANNOTATION as primary source for id
210210 [ runv2 . FUNCTION_TARGET_ANNOTATION ] : "customEntryPoint" ,
211+ [ runv2 . TRIGGER_TYPE_ANNOTATION ] : "HTTP_TRIGGER" ,
211212 } ,
212213 template : {
213214 containers : [
@@ -239,6 +240,7 @@ describe("runv2", () => {
239240 httpsTrigger : { } ,
240241 labels : {
241242 [ runv2 . RUNTIME_LABEL ] : latest ( "nodejs" ) ,
243+ [ runv2 . CLIENT_NAME_LABEL ] : "firebase-functions" ,
242244 } ,
243245 environmentVariables : { } ,
244246 secretEnvironmentVariables : [ ] ,
@@ -259,6 +261,7 @@ describe("runv2", () => {
259261 ...BASE_RUN_SERVICE . annotations ,
260262 [ runv2 . FUNCTION_ID_ANNOTATION ] : FUNCTION_ID , // Using FUNCTION_ID_ANNOTATION as primary source for id
261263 [ runv2 . FUNCTION_TARGET_ANNOTATION ] : "customEntryPoint" ,
264+ [ runv2 . TRIGGER_TYPE_ANNOTATION ] : "HTTP_TRIGGER" ,
262265 } ,
263266 template : {
264267 containers : [
@@ -442,7 +445,7 @@ describe("runv2", () => {
442445 entryPoint : SERVICE_ID , // No FUNCTION_TARGET_ANNOTATION
443446 availableMemoryMb : 128 ,
444447 cpu : 0.5 ,
445- httpsTrigger : { } ,
448+ eventTrigger : { eventType : "unknown" , retry : false } ,
446449 labels : { } ,
447450 environmentVariables : { } ,
448451 secretEnvironmentVariables : [ ] ,
@@ -452,4 +455,114 @@ describe("runv2", () => {
452455 expect ( runv2 . endpointFromService ( service ) ) . to . deep . equal ( expectedEndpoint ) ;
453456 } ) ;
454457 } ) ;
458+
459+ describe ( "listServices" , ( ) => {
460+ let sandbox : sinon . SinonSandbox ;
461+ let getStub : sinon . SinonStub ;
462+
463+ beforeEach ( ( ) => {
464+ sandbox = sinon . createSandbox ( ) ;
465+ getStub = sandbox . stub ( Client . prototype , "get" ) ;
466+ } ) ;
467+
468+ afterEach ( ( ) => {
469+ sandbox . restore ( ) ;
470+ } ) ;
471+
472+ it ( "should return a list of services" , async ( ) => {
473+ const mockServices = [
474+ {
475+ name : "service1" ,
476+ labels : { "goog-managed-by" : "cloud-functions" } ,
477+ } ,
478+ {
479+ name : "service2" ,
480+ labels : { "goog-managed-by" : "firebase-functions" } ,
481+ } ,
482+ ] ;
483+ getStub . resolves ( { status : 200 , body : { services : mockServices } } ) ;
484+
485+ const services = await runv2 . listServices ( PROJECT_ID ) ;
486+
487+ expect ( services ) . to . deep . equal ( mockServices ) ;
488+ expect ( getStub ) . to . have . been . calledOnceWithExactly (
489+ `/projects/${ PROJECT_ID } /locations/-/services` ,
490+ { queryParams : { } } ,
491+ ) ;
492+ } ) ;
493+
494+ it ( "should handle pagination" , async ( ) => {
495+ const mockServices1 = [
496+ {
497+ name : "service1" ,
498+ labels : { "goog-managed-by" : "cloud-functions" } ,
499+ } ,
500+ ] ;
501+ const mockServices2 = [
502+ {
503+ name : "service2" ,
504+ labels : { "goog-managed-by" : "firebase-functions" } ,
505+ } ,
506+ ] ;
507+ getStub
508+ . onFirstCall ( )
509+ . resolves ( { status : 200 , body : { services : mockServices1 , nextPageToken : "nextPage" } } ) ;
510+ getStub . onSecondCall ( ) . resolves ( { status : 200 , body : { services : mockServices2 } } ) ;
511+
512+ const services = await runv2 . listServices ( PROJECT_ID ) ;
513+
514+ expect ( services ) . to . deep . equal ( [ ...mockServices1 , ...mockServices2 ] ) ;
515+ expect ( getStub ) . to . have . been . calledTwice ;
516+ expect ( getStub . firstCall ) . to . have . been . calledWithExactly (
517+ `/projects/${ PROJECT_ID } /locations/-/services` ,
518+ { queryParams : { } } ,
519+ ) ;
520+ expect ( getStub . secondCall ) . to . have . been . calledWithExactly (
521+ `/projects/${ PROJECT_ID } /locations/-/services` ,
522+ { queryParams : { pageToken : "nextPage" } } ,
523+ ) ;
524+ } ) ;
525+
526+ it ( "should throw an error if the API call fails" , async ( ) => {
527+ getStub . resolves ( { status : 500 , body : "Internal Server Error" } ) ;
528+
529+ try {
530+ await runv2 . listServices ( PROJECT_ID ) ;
531+ expect . fail ( "Should have thrown an error" ) ;
532+ } catch ( err : any ) {
533+ expect ( err ) . to . be . instanceOf ( FirebaseError ) ;
534+ expect ( err . message ) . to . contain ( "Failed to list services. HTTP Error: 500" ) ;
535+ }
536+ } ) ;
537+
538+ it ( "should filter for gcfv2 and firebase-managed services" , async ( ) => {
539+ const mockServices = [
540+ {
541+ name : "service1" ,
542+ labels : { "goog-managed-by" : "cloud-functions" } ,
543+ } ,
544+ {
545+ name : "service2" ,
546+ labels : { "goog-managed-by" : "firebase-functions" } ,
547+ } ,
548+ {
549+ name : "service3" ,
550+ labels : { "goog-managed-by" : "other" } ,
551+ } ,
552+ {
553+ name : "service4" ,
554+ labels : { } ,
555+ } ,
556+ ] ;
557+ getStub . resolves ( { status : 200 , body : { services : mockServices } } ) ;
558+
559+ const services = await runv2 . listServices ( PROJECT_ID ) ;
560+
561+ expect ( services ) . to . deep . equal ( [ mockServices [ 0 ] , mockServices [ 1 ] ] ) ;
562+ expect ( getStub ) . to . have . been . calledOnceWithExactly (
563+ `/projects/${ PROJECT_ID } /locations/-/services` ,
564+ { queryParams : { } } ,
565+ ) ;
566+ } ) ;
567+ } ) ;
455568} ) ;
0 commit comments