@@ -5,6 +5,19 @@ const request = require('../lib/request');
5
5
const InMemoryCacheAdapter = require ( '../lib/Adapters/Cache/InMemoryCacheAdapter' )
6
6
. InMemoryCacheAdapter ;
7
7
8
+ const mockAdapter = {
9
+ createFile : async ( filename ) => ( {
10
+ name : filename ,
11
+ location : `http://www.somewhere.com/${ filename } ` ,
12
+ } ) ,
13
+ deleteFile : ( ) => { } ,
14
+ getFileData : ( ) => { } ,
15
+ getFileLocation : ( config , filename ) => `http://www.somewhere.com/${ filename } ` ,
16
+ validateFilename : ( ) => {
17
+ return null ;
18
+ } ,
19
+ } ;
20
+
8
21
describe ( 'Cloud Code' , ( ) => {
9
22
it ( 'can load absolute cloud code file' , done => {
10
23
reconfigureServer ( {
@@ -2595,6 +2608,246 @@ describe('beforeLogin hook', () => {
2595
2608
expect ( beforeFinds ) . toEqual ( 1 ) ;
2596
2609
expect ( afterFinds ) . toEqual ( 1 ) ;
2597
2610
} ) ;
2611
+
2612
+ it ( 'beforeSaveFile should not change file if nothing is returned' , async ( ) => {
2613
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2614
+ Parse . Cloud . beforeSaveFile ( ( ) => {
2615
+ return ;
2616
+ } ) ;
2617
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2618
+ const result = await file . save ( { useMasterKey : true } ) ;
2619
+ expect ( result ) . toBe ( file ) ;
2620
+ } ) ;
2621
+
2622
+ it ( 'beforeSaveFile should return file that is already saved and not save anything to files adapter' , async ( ) => {
2623
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2624
+ const createFileSpy = spyOn ( mockAdapter , 'createFile' ) . and . callThrough ( ) ;
2625
+ Parse . Cloud . beforeSaveFile ( ( ) => {
2626
+ const newFile = new Parse . File ( 'some-file.txt' ) ;
2627
+ newFile . _url = 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt' ;
2628
+ return newFile ;
2629
+ } ) ;
2630
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2631
+ const result = await file . save ( { useMasterKey : true } ) ;
2632
+ expect ( result ) . toBe ( file ) ;
2633
+ expect ( result . _name ) . toBe ( 'some-file.txt' ) ;
2634
+ expect ( result . _url ) . toBe ( 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt' ) ;
2635
+ expect ( createFileSpy ) . not . toHaveBeenCalled ( ) ;
2636
+ } ) ;
2637
+
2638
+ it ( 'beforeSaveFile should throw error' , async ( ) => {
2639
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2640
+ Parse . Cloud . beforeSaveFile ( ( ) => {
2641
+ throw new Parse . Error ( 400 , 'some-error-message' ) ;
2642
+ } ) ;
2643
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2644
+ try {
2645
+ await file . save ( { useMasterKey : true } ) ;
2646
+ } catch ( error ) {
2647
+ expect ( error . message ) . toBe ( 'some-error-message' ) ;
2648
+ }
2649
+ } ) ;
2650
+
2651
+ it ( 'beforeSaveFile should change values of uploaded file by editing fileObject directly' , async ( ) => {
2652
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2653
+ const createFileSpy = spyOn ( mockAdapter , 'createFile' ) . and . callThrough ( ) ;
2654
+ Parse . Cloud . beforeSaveFile ( async ( req ) => {
2655
+ expect ( req . triggerName ) . toEqual ( 'beforeSaveFile' ) ;
2656
+ expect ( req . master ) . toBe ( true ) ;
2657
+ req . file . addMetadata ( 'foo' , 'bar' ) ;
2658
+ req . file . addTag ( 'tagA' , 'some-tag' ) ;
2659
+ } ) ;
2660
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2661
+ const result = await file . save ( { useMasterKey : true } ) ;
2662
+ expect ( result ) . toBe ( file ) ;
2663
+ const newData = new Buffer ( [ 1 , 2 , 3 ] ) ;
2664
+ const newOptions = {
2665
+ tags : {
2666
+ tagA : 'some-tag' ,
2667
+ } ,
2668
+ metadata : {
2669
+ foo : 'bar' ,
2670
+ } ,
2671
+ } ;
2672
+ expect ( createFileSpy ) . toHaveBeenCalledWith ( jasmine . any ( String ) , newData , 'text/plain' , newOptions ) ;
2673
+ } ) ;
2674
+
2675
+ it ( 'beforeSaveFile should change values by returning new fileObject' , async ( ) => {
2676
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2677
+ const createFileSpy = spyOn ( mockAdapter , 'createFile' ) . and . callThrough ( ) ;
2678
+ Parse . Cloud . beforeSaveFile ( async ( req ) => {
2679
+ expect ( req . triggerName ) . toEqual ( 'beforeSaveFile' ) ;
2680
+ expect ( req . fileSize ) . toBe ( 3 ) ;
2681
+ const newFile = new Parse . File ( 'donald_duck.pdf' , [ 4 , 5 , 6 ] , 'application/pdf' ) ;
2682
+ newFile . setMetadata ( { foo : 'bar' } ) ;
2683
+ newFile . setTags ( { tagA : 'some-tag' } ) ;
2684
+ return newFile ;
2685
+ } ) ;
2686
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2687
+ const result = await file . save ( { useMasterKey : true } ) ;
2688
+ expect ( result ) . toBeInstanceOf ( Parse . File ) ;
2689
+ const newData = new Buffer ( [ 4 , 5 , 6 ] ) ;
2690
+ const newContentType = 'application/pdf' ;
2691
+ const newOptions = {
2692
+ tags : {
2693
+ tagA : 'some-tag' ,
2694
+ } ,
2695
+ metadata : {
2696
+ foo : 'bar' ,
2697
+ } ,
2698
+ } ;
2699
+ expect ( createFileSpy ) . toHaveBeenCalledWith ( jasmine . any ( String ) , newData , newContentType , newOptions ) ;
2700
+ const expectedFileName = 'donald_duck.pdf' ;
2701
+ expect ( file . _name . indexOf ( expectedFileName ) ) . toBe ( file . _name . length - expectedFileName . length ) ;
2702
+ } ) ;
2703
+
2704
+ it ( 'beforeSaveFile should contain metadata and tags saved from client' , async ( ) => {
2705
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2706
+ const createFileSpy = spyOn ( mockAdapter , 'createFile' ) . and . callThrough ( ) ;
2707
+ Parse . Cloud . beforeSaveFile ( async ( req ) => {
2708
+ expect ( req . triggerName ) . toEqual ( 'beforeSaveFile' ) ;
2709
+ expect ( req . fileSize ) . toBe ( 3 ) ;
2710
+ expect ( req . file ) . toBeInstanceOf ( Parse . File ) ;
2711
+ expect ( req . file . name ( ) ) . toBe ( 'popeye.txt' ) ;
2712
+ expect ( req . file . metadata ( ) ) . toEqual ( { foo : 'bar' } ) ;
2713
+ expect ( req . file . tags ( ) ) . toEqual ( { bar : 'foo' } ) ;
2714
+ } ) ;
2715
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2716
+ file . setMetadata ( { foo : 'bar' } ) ;
2717
+ file . setTags ( { bar : 'foo' } ) ;
2718
+ const result = await file . save ( { useMasterKey : true } ) ;
2719
+ expect ( result ) . toBeInstanceOf ( Parse . File ) ;
2720
+ const options = {
2721
+ metadata : { foo : 'bar' } ,
2722
+ tags : { bar : 'foo' } ,
2723
+ } ;
2724
+ expect ( createFileSpy ) . toHaveBeenCalledWith ( jasmine . any ( String ) , jasmine . any ( Buffer ) , 'text/plain' , options ) ;
2725
+ } ) ;
2726
+
2727
+ it ( 'beforeSaveFile should return same file data with new file name' , async ( ) => {
2728
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2729
+ const config = Config . get ( 'test' ) ;
2730
+ config . filesController . options . preserveFileName = true ;
2731
+ Parse . Cloud . beforeSaveFile ( async ( { file } ) => {
2732
+ expect ( file . name ( ) ) . toBe ( 'popeye.txt' ) ;
2733
+ const fileData = await file . getData ( ) ;
2734
+ const newFile = new Parse . File ( '2020-04-01.txt' , { base64 : fileData } ) ;
2735
+ return newFile ;
2736
+ } ) ;
2737
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2738
+ const result = await file . save ( { useMasterKey : true } ) ;
2739
+ expect ( result . name ( ) ) . toBe ( '2020-04-01.txt' ) ;
2740
+ } ) ;
2741
+
2742
+ it ( 'afterSaveFile should set fileSize to null if beforeSave returns an already saved file' , async ( ) => {
2743
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2744
+ const createFileSpy = spyOn ( mockAdapter , 'createFile' ) . and . callThrough ( ) ;
2745
+ Parse . Cloud . beforeSaveFile ( ( req ) => {
2746
+ expect ( req . fileSize ) . toBe ( 3 ) ;
2747
+ const newFile = new Parse . File ( 'some-file.txt' ) ;
2748
+ newFile . _url = 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt' ;
2749
+ return newFile ;
2750
+ } ) ;
2751
+ Parse . Cloud . afterSaveFile ( ( req ) => {
2752
+ expect ( req . fileSize ) . toBe ( null ) ;
2753
+ } ) ;
2754
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2755
+ const result = await file . save ( { useMasterKey : true } ) ;
2756
+ expect ( result ) . toBe ( result ) ;
2757
+ expect ( result . _name ) . toBe ( 'some-file.txt' ) ;
2758
+ expect ( result . _url ) . toBe ( 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt' ) ;
2759
+ expect ( createFileSpy ) . not . toHaveBeenCalled ( ) ;
2760
+ } ) ;
2761
+
2762
+ it ( 'afterSaveFile should throw error' , async ( ) => {
2763
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2764
+ Parse . Cloud . afterSaveFile ( async ( ) => {
2765
+ throw new Parse . Error ( 400 , 'some-error-message' ) ;
2766
+ } ) ;
2767
+ const filename = 'donald_duck.pdf' ;
2768
+ const file = new Parse . File ( filename , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2769
+ try {
2770
+ await file . save ( { useMasterKey : true } ) ;
2771
+ } catch ( error ) {
2772
+ expect ( error . message ) . toBe ( 'some-error-message' ) ;
2773
+ }
2774
+ } ) ;
2775
+
2776
+ it ( 'afterSaveFile should call with fileObject' , async ( done ) => {
2777
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2778
+ Parse . Cloud . beforeSaveFile ( async ( req ) => {
2779
+ req . file . setTags ( { tagA : 'some-tag' } ) ;
2780
+ req . file . setMetadata ( { foo : 'bar' } ) ;
2781
+ } ) ;
2782
+ Parse . Cloud . afterSaveFile ( async ( req ) => {
2783
+ expect ( req . master ) . toBe ( true ) ;
2784
+ expect ( req . file . _tags ) . toEqual ( { tagA : 'some-tag' } ) ;
2785
+ expect ( req . file . _metadata ) . toEqual ( { foo : 'bar' } ) ;
2786
+ done ( ) ;
2787
+ } ) ;
2788
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2789
+ await file . save ( { useMasterKey : true } ) ;
2790
+ } ) ;
2791
+
2792
+ it ( 'afterSaveFile should change fileSize when file data changes' , async ( done ) => {
2793
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2794
+ Parse . Cloud . beforeSaveFile ( async ( req ) => {
2795
+ expect ( req . fileSize ) . toBe ( 3 ) ;
2796
+ expect ( req . master ) . toBe ( true ) ;
2797
+ const newFile = new Parse . File ( 'donald_duck.pdf' , [ 4 , 5 , 6 , 7 , 8 , 9 ] , 'application/pdf' ) ;
2798
+ return newFile ;
2799
+ } ) ;
2800
+ Parse . Cloud . afterSaveFile ( async ( req ) => {
2801
+ expect ( req . fileSize ) . toBe ( 6 ) ;
2802
+ expect ( req . master ) . toBe ( true ) ;
2803
+ done ( ) ;
2804
+ } ) ;
2805
+ const file = new Parse . File ( 'popeye.txt' , [ 1 , 2 , 3 ] , 'text/plain' ) ;
2806
+ await file . save ( { useMasterKey : true } ) ;
2807
+ } ) ;
2808
+
2809
+ it ( 'beforeDeleteFile should call with fileObject' , async ( ) => {
2810
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2811
+ Parse . Cloud . beforeDeleteFile ( ( req ) => {
2812
+ expect ( req . file ) . toBeInstanceOf ( Parse . File ) ;
2813
+ expect ( req . file . _name ) . toEqual ( 'popeye.txt' ) ;
2814
+ expect ( req . file . _url ) . toEqual ( 'http://www.somewhere.com/popeye.txt' ) ;
2815
+ expect ( req . fileSize ) . toBe ( null ) ;
2816
+ } ) ;
2817
+ const file = new Parse . File ( 'popeye.txt' ) ;
2818
+ await file . destroy ( { useMasterKey : true } ) ;
2819
+ } ) ;
2820
+
2821
+ it ( 'beforeDeleteFile should throw error' , async ( done ) => {
2822
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2823
+ Parse . Cloud . beforeDeleteFile ( ( ) => {
2824
+ throw new Error ( 'some error message' ) ;
2825
+ } ) ;
2826
+ const file = new Parse . File ( 'popeye.txt' ) ;
2827
+ try {
2828
+ await file . destroy ( { useMasterKey : true } ) ;
2829
+ } catch ( error ) {
2830
+ expect ( error . message ) . toBe ( 'some error message' ) ;
2831
+ done ( ) ;
2832
+ }
2833
+ } )
2834
+
2835
+ it ( 'afterDeleteFile should call with fileObject' , async ( done ) => {
2836
+ await reconfigureServer ( { filesAdapter : mockAdapter } ) ;
2837
+ Parse . Cloud . beforeDeleteFile ( ( req ) => {
2838
+ expect ( req . file ) . toBeInstanceOf ( Parse . File ) ;
2839
+ expect ( req . file . _name ) . toEqual ( 'popeye.txt' ) ;
2840
+ expect ( req . file . _url ) . toEqual ( 'http://www.somewhere.com/popeye.txt' ) ;
2841
+ } ) ;
2842
+ Parse . Cloud . afterDeleteFile ( ( req ) => {
2843
+ expect ( req . file ) . toBeInstanceOf ( Parse . File ) ;
2844
+ expect ( req . file . _name ) . toEqual ( 'popeye.txt' ) ;
2845
+ expect ( req . file . _url ) . toEqual ( 'http://www.somewhere.com/popeye.txt' ) ;
2846
+ done ( ) ;
2847
+ } ) ;
2848
+ const file = new Parse . File ( 'popeye.txt' ) ;
2849
+ await file . destroy ( { useMasterKey : true } ) ;
2850
+ } ) ;
2598
2851
} ) ;
2599
2852
2600
2853
describe ( 'afterLogin hook' , ( ) => {
0 commit comments