@@ -34,9 +34,12 @@ import {
3434 testLab ,
3535 eventarc ,
3636 https ,
37+ firestore ,
3738} from 'firebase-functions/v2' ;
3839import { defineString } from 'firebase-functions/params' ;
3940import { makeDataSnapshot } from '../src/providers/database' ;
41+ import { makeDocumentSnapshot } from '../src/providers/firestore' ;
42+ import { inspect } from 'util' ;
4043
4144describe ( 'v2' , ( ) => {
4245 describe ( '#wrapV2' , ( ) => {
@@ -460,6 +463,275 @@ describe('v2', () => {
460463 } ) ;
461464 } ) ;
462465
466+ describe ( 'firestore' , ( ) => {
467+ describe ( 'document path' , ( ) => {
468+ it ( 'should resolve default document path' , ( ) => {
469+ const cloudFn = firestore . onDocumentCreated ( 'foo/bar/baz' , handler ) ;
470+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
471+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
472+
473+ expect ( cloudEvent . document ) . equal ( 'foo/bar/baz' ) ;
474+ } ) ;
475+
476+ it ( 'should resolve default document given StringParam' , ( ) => {
477+ process . env . doc_path = 'foo/StringParam/baz' ;
478+ const cloudFn = firestore . onDocumentCreated ( '' , handler ) ;
479+ cloudFn . __endpoint . eventTrigger . eventFilterPathPatterns . document = defineString (
480+ 'doc_path'
481+ ) ;
482+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
483+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
484+
485+ expect ( cloudEvent . document ) . equal ( 'foo/StringParam/baz' ) ;
486+ } ) ;
487+
488+ it ( 'should resolve using params' , ( ) => {
489+ const cloudFn = firestore . onDocumentCreated ( 'users/{user}' , handler ) ;
490+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
491+ const partial = {
492+ params : {
493+ user : '123' ,
494+ } ,
495+ } ;
496+ const cloudEvent = cloudFnWrap ( partial ) . cloudEvent ;
497+
498+ expect ( cloudEvent . document ) . equal ( 'users/123' ) ;
499+ } ) ;
500+
501+ it ( 'should resolve with undefined string if variable is missing' , ( ) => {
502+ const cloudFn = firestore . onDocumentCreated ( 'users/{user}' , handler ) ;
503+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
504+ const partial = {
505+ params : { } ,
506+ } ;
507+ const cloudEvent = cloudFnWrap ( partial ) . cloudEvent ;
508+
509+ expect ( cloudEvent . document ) . equal ( 'users/undefined' ) ;
510+ } ) ;
511+ } ) ;
512+
513+ describe ( 'document options' , ( ) => {
514+ it ( 'resolves default document options correctly' , ( ) => {
515+ const cloudFn = firestore . onDocumentCreated ( 'foo/bar/baz' , handler ) ;
516+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
517+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
518+
519+ expect ( cloudEvent . document ) . equal ( 'foo/bar/baz' ) ;
520+ expect ( cloudEvent . database ) . equal ( '(default)' ) ;
521+ expect ( cloudEvent . namespace ) . equal ( '(default)' ) ;
522+ } ) ;
523+
524+ it ( 'reads custom DocumentOptions correctly' , ( ) => {
525+ const documentOptions = {
526+ document : 'foo/bar/baz' ,
527+ database : 'custom-database' ,
528+ namespace : 'custom-namespace' ,
529+ } ;
530+ const cloudFn = firestore . onDocumentCreated ( documentOptions , handler ) ;
531+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
532+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
533+
534+ expect ( cloudEvent . document ) . equal ( documentOptions . document ) ;
535+ expect ( cloudEvent . database ) . equal ( documentOptions . database ) ;
536+ expect ( cloudEvent . namespace ) . equal ( documentOptions . namespace ) ;
537+ } ) ;
538+ } ) ;
539+
540+ describe ( 'firestore.onDocumentCreated' , ( ) => {
541+ it ( 'should update CloudEvent appropriately' , ( ) => {
542+ const cloudFn = firestore . onDocumentCreated ( 'foo/bar/baz' , handler ) ;
543+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
544+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
545+
546+ expect ( cloudEvent ) . deep . equal ( {
547+ id : cloudEvent . id ,
548+ time : cloudEvent . time ,
549+ specversion : '1.0' ,
550+ type : 'google.cloud.firestore.document.v1.created' ,
551+ source : '' ,
552+
553+ data : cloudEvent . data ,
554+ location : 'us-central1' ,
555+ project : 'testproject' ,
556+ database : '(default)' ,
557+ namespace : '(default)' ,
558+ document : 'foo/bar/baz' ,
559+ params : { } ,
560+ } ) ;
561+ } ) ;
562+
563+ it ( 'should use overridden data' , ( ) => {
564+ const cloudFn = firestore . onDocumentCreated ( 'foo/bar/baz' , handler ) ;
565+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
566+ const docData = { foo : 'bar' } ;
567+ const data = makeDocumentSnapshot ( docData , 'foo/bar/baz' ) ;
568+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
569+
570+ expect ( cloudEvent . data . data ( ) ) . deep . equal ( docData ) ;
571+ } ) ;
572+
573+ it ( 'should accept json data' , ( ) => {
574+ const cloudFn = firestore . onDocumentCreated ( 'foo/bar/baz' , handler ) ;
575+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
576+ const docData = { foo : 'bar' } ;
577+ const cloudEvent = cloudFnWrap ( { data : docData } ) . cloudEvent ;
578+
579+ expect ( cloudEvent . data . data ( ) ) . deep . equal ( docData ) ;
580+ } ) ;
581+ } ) ;
582+
583+ describe ( 'firestore.onDocumentDeleted()' , ( ) => {
584+ it ( 'should update CloudEvent appropriately' , ( ) => {
585+ const cloudFn = firestore . onDocumentDeleted ( 'foo/bar/baz' , handler ) ;
586+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
587+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
588+
589+ expect ( cloudEvent ) . deep . equal ( {
590+ id : cloudEvent . id ,
591+ time : cloudEvent . time ,
592+ specversion : '1.0' ,
593+ type : 'google.cloud.firestore.document.v1.deleted' ,
594+ source : '' ,
595+
596+ data : cloudEvent . data ,
597+ location : 'us-central1' ,
598+ project : 'testproject' ,
599+ database : '(default)' ,
600+ namespace : '(default)' ,
601+ document : 'foo/bar/baz' ,
602+ params : { } ,
603+ } ) ;
604+ } ) ;
605+
606+ it ( 'should use overridden data' , ( ) => {
607+ const cloudFn = firestore . onDocumentDeleted ( 'foo/bar/baz' , handler ) ;
608+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
609+ const docData = { foo : 'bar' } ;
610+ const data = makeDocumentSnapshot ( docData , 'foo/bar/baz' ) ;
611+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
612+
613+ expect ( cloudEvent . data . data ( ) ) . deep . equal ( docData ) ;
614+ } ) ;
615+
616+ it ( 'should accept json data' , ( ) => {
617+ const cloudFn = firestore . onDocumentDeleted ( 'foo/bar/baz' , handler ) ;
618+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
619+ const docData = { foo : 'bar' } ;
620+ const cloudEvent = cloudFnWrap ( { data : docData } ) . cloudEvent ;
621+
622+ expect ( cloudEvent . data . data ( ) ) . deep . equal ( docData ) ;
623+ } ) ;
624+ } ) ;
625+
626+ describe ( 'firestore.onDocumentUpdated' , ( ) => {
627+ it ( 'should update CloudEvent appropriately' , ( ) => {
628+ const cloudFn = firestore . onDocumentUpdated ( 'foo/bar/baz' , handler ) ;
629+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
630+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
631+
632+ expect ( cloudEvent ) . deep . equal ( {
633+ id : cloudEvent . id ,
634+ time : cloudEvent . time ,
635+ specversion : '1.0' ,
636+ type : 'google.cloud.firestore.document.v1.updated' ,
637+ source : '' ,
638+
639+ data : cloudEvent . data ,
640+ location : 'us-central1' ,
641+ project : 'testproject' ,
642+ database : '(default)' ,
643+ namespace : '(default)' ,
644+ document : 'foo/bar/baz' ,
645+ params : { } ,
646+ } ) ;
647+ } ) ;
648+
649+ it ( 'should use overridden data' , ( ) => {
650+ const cloudFn = firestore . onDocumentUpdated ( 'foo/bar/baz' , handler ) ;
651+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
652+
653+ const afterDataVal = { snapshot : 'after' } ;
654+ const after = makeDocumentSnapshot ( afterDataVal , 'foo/bar/baz' ) ;
655+
656+ const beforeDataVal = { snapshot : 'before' } ;
657+ const before = makeDocumentSnapshot ( beforeDataVal , 'foo/bar/baz' ) ;
658+
659+ const data = { before, after } ;
660+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
661+
662+ expect ( cloudEvent . data . before . data ( ) ) . deep . equal ( beforeDataVal ) ;
663+ expect ( cloudEvent . data . after . data ( ) ) . deep . equal ( afterDataVal ) ;
664+ } ) ;
665+
666+ it ( 'should accept json data' , ( ) => {
667+ const cloudFn = firestore . onDocumentUpdated ( 'foo/bar/baz' , handler ) ;
668+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
669+ const afterDataVal = { snapshot : 'after' } ;
670+ const beforeDataVal = { snapshot : 'before' } ;
671+
672+ const data = { before : beforeDataVal , after : afterDataVal } ;
673+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
674+
675+ expect ( cloudEvent . data . before . data ( ) ) . deep . equal ( beforeDataVal ) ;
676+ expect ( cloudEvent . data . after . data ( ) ) . deep . equal ( afterDataVal ) ;
677+ } ) ;
678+ } ) ;
679+
680+ describe ( 'firestore.onDocumentWritten' , ( ) => {
681+ it ( 'should update CloudEvent appropriately' , ( ) => {
682+ const cloudFn = firestore . onDocumentWritten ( 'foo/bar/baz' , handler ) ;
683+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
684+ const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
685+
686+ expect ( cloudEvent ) . deep . equal ( {
687+ id : cloudEvent . id ,
688+ time : cloudEvent . time ,
689+ specversion : '1.0' ,
690+ type : 'google.cloud.firestore.document.v1.written' ,
691+ source : '' ,
692+
693+ data : cloudEvent . data ,
694+ location : 'us-central1' ,
695+ project : 'testproject' ,
696+ database : '(default)' ,
697+ namespace : '(default)' ,
698+ document : 'foo/bar/baz' ,
699+ params : { } ,
700+ } ) ;
701+ } ) ;
702+
703+ it ( 'should use overridden data' , ( ) => {
704+ const cloudFn = firestore . onDocumentWritten ( 'foo/bar/baz' , handler ) ;
705+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
706+
707+ const afterDataVal = { snapshot : 'after' } ;
708+ const after = makeDocumentSnapshot ( afterDataVal , 'foo/bar/baz' ) ;
709+
710+ const beforeDataVal = { snapshot : 'before' } ;
711+ const before = makeDocumentSnapshot ( beforeDataVal , 'foo/bar/baz' ) ;
712+
713+ const data = { before, after } ;
714+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
715+
716+ expect ( cloudEvent . data . before . data ( ) ) . deep . equal ( beforeDataVal ) ;
717+ expect ( cloudEvent . data . after . data ( ) ) . deep . equal ( afterDataVal ) ;
718+ } ) ;
719+
720+ it ( 'should accept json data' , ( ) => {
721+ const cloudFn = firestore . onDocumentWritten ( 'foo/bar/baz' , handler ) ;
722+ const cloudFnWrap = wrapV2 ( cloudFn ) ;
723+ const afterDataVal = { snapshot : 'after' } ;
724+ const beforeDataVal = { snapshot : 'before' } ;
725+
726+ const data = { before : beforeDataVal , after : afterDataVal } ;
727+ const cloudEvent = cloudFnWrap ( { data } ) . cloudEvent ;
728+
729+ expect ( cloudEvent . data . before . data ( ) ) . deep . equal ( beforeDataVal ) ;
730+ expect ( cloudEvent . data . after . data ( ) ) . deep . equal ( afterDataVal ) ;
731+ } ) ;
732+ } ) ;
733+ } ) ;
734+
463735 describe ( 'database' , ( ) => {
464736 describe ( 'ref' , ( ) => {
465737 it ( 'should resolve default ref' , ( ) => {
@@ -488,23 +760,23 @@ describe('v2', () => {
488760 expect ( cloudEvent . ref ) . equal ( 'foo/StringParam/baz' ) ;
489761 } ) ;
490762
491- it . skip ( 'should resolve default ref given TernaryExpression' , ( ) => {
492- const ref1 = defineString ( 'rtdb_ref_1' ) ;
493- process . env . rtdb_ref_1 = 'foo/StringParam/1' ;
494- const ref2 = defineString ( 'rtdb_ref_2' ) ;
495- process . env . rtdb_ref_2 = 'foo/StringParam/2' ;
496- const referenceOptions = {
497- ref : '' ,
498- instance : 'instance-1' ,
499- } ;
500- const cloudFn = database . onValueCreated ( referenceOptions , handler ) ;
501- cloudFn . __endpoint . eventTrigger . eventFilterPathPatterns . ref = ref1
502- . equals ( 'aa' )
503- . then ( 'rtdb_ref_1' , 'rtdb_ref_2' ) ;
504- const cloudFnWrap = wrapV2 ( cloudFn ) ;
505- const cloudEvent = cloudFnWrap ( ) . cloudEvent ;
506- expect ( cloudEvent . ref ) . equal ( 'rtdb_ref_2' ) ;
507- } ) ;
763+ // it ('should resolve default ref given TernaryExpression', () => {
764+ // const ref1 = defineString('rtdb_ref_1');
765+ // process.env.rtdb_ref_1 = 'foo/StringParam/1';
766+ // const ref2 = defineString('rtdb_ref_2');
767+ // process.env.rtdb_ref_2 = 'foo/StringParam/2';
768+ // const referenceOptions = {
769+ // ref: '',
770+ // instance: 'instance-1',
771+ // };
772+ // const cloudFn = database.onValueCreated(referenceOptions, handler);
773+ // cloudFn.__endpoint.eventTrigger.eventFilterPathPatterns.ref = ref1
774+ // .equals('aa')
775+ // .then('rtdb_ref_1', 'rtdb_ref_2');
776+ // const cloudFnWrap = wrapV2(cloudFn);
777+ // const cloudEvent = cloudFnWrap().cloudEvent;
778+ // expect(cloudEvent.ref).equal('rtdb_ref_2');
779+ // });
508780
509781 it ( 'should resolve using params' , ( ) => {
510782 const referenceOptions = {
0 commit comments