@@ -40,14 +40,47 @@ const createMockCache = () => {
40
40
}
41
41
42
42
describe ( `gatsby-node` , ( ) => {
43
+ function deleteDescendants ( node ) {
44
+ if ( ! node ) {
45
+ return
46
+ }
47
+
48
+ for ( const childId of node . children ?? [ ] ) {
49
+ const child = currentNodeMap . get ( childId )
50
+ if ( child ) {
51
+ deleteDescendants ( child )
52
+ currentNodeMap . delete ( child . id )
53
+ }
54
+ }
55
+ }
56
+
43
57
const actions = {
44
58
createTypes : jest . fn ( ) ,
45
59
setPluginStatus : jest . fn ( ) ,
46
60
createNode : jest . fn ( async node => {
61
+ // similar checks as gatsby does
62
+ if ( ! _ . isPlainObject ( node ) ) {
63
+ throw new Error (
64
+ `The node passed to the "createNode" action creator must be an object`
65
+ )
66
+ }
67
+
68
+ if ( node . internal . owner ) {
69
+ throw new Error (
70
+ `The node internal.owner field is set automatically by Gatsby and not by plugins`
71
+ )
72
+ }
73
+
74
+ // recursively delete children of node if it existed already
75
+ deleteDescendants ( currentNodeMap . get ( node . id ) )
76
+
47
77
node . internal . owner = `gatsby-source-contentful`
48
78
currentNodeMap . set ( node . id , node )
49
79
} ) ,
50
80
deleteNode : jest . fn ( node => {
81
+ // recursively delete children of deleted node same as gatsby
82
+ deleteDescendants ( node )
83
+
51
84
currentNodeMap . delete ( node . id )
52
85
} ) ,
53
86
touchNode : jest . fn ( ) ,
@@ -80,8 +113,12 @@ describe(`gatsby-node`, () => {
80
113
const parentSpan = { }
81
114
const createNodeId = jest . fn ( value => value )
82
115
let currentNodeMap
83
- const getNodes = ( ) => Array . from ( currentNodeMap . values ( ) )
84
- const getNode = id => currentNodeMap . get ( id )
116
+
117
+ // returning clones of nodes to test if we are updating nodes correctly
118
+ // as it's not enough to mutate a node, we need to call an update function
119
+ // to actually update datastore
120
+ const getNodes = ( ) => Array . from ( currentNodeMap . values ( ) ) . map ( _ . cloneDeep )
121
+ const getNode = id => _ . cloneDeep ( currentNodeMap . get ( id ) )
85
122
86
123
const getFieldValue = ( value , locale , defaultLocale ) =>
87
124
value [ locale ] ?? value [ defaultLocale ]
@@ -179,7 +216,9 @@ describe(`gatsby-node`, () => {
179
216
const linkedNode = getNode ( linkId )
180
217
reference [ referenceKey ] =
181
218
reference [ referenceKey ] || linkedNode [ referenceKey ] || [ ]
182
- reference [ referenceKey ] . push ( nodeId )
219
+ if ( ! reference [ referenceKey ] . includes ( nodeId ) ) {
220
+ reference [ referenceKey ] . push ( nodeId )
221
+ }
183
222
references . set ( linkId , reference )
184
223
}
185
224
break
@@ -549,7 +588,7 @@ describe(`gatsby-node`, () => {
549
588
expect ( getNode ( blogEntry [ `author___NODE` ] ) ) . toBeTruthy ( )
550
589
} )
551
590
552
- expect ( actions . createNode ) . toHaveBeenCalledTimes ( 42 )
591
+ expect ( actions . createNode ) . toHaveBeenCalledTimes ( 46 )
553
592
expect ( actions . deleteNode ) . toHaveBeenCalledTimes ( 0 )
554
593
expect ( actions . touchNode ) . toHaveBeenCalledTimes ( 32 )
555
594
expect ( reporter . info . mock . calls ) . toMatchInlineSnapshot ( `
@@ -564,7 +603,7 @@ describe(`gatsby-node`, () => {
564
603
"Contentful: 0 deleted entries",
565
604
],
566
605
Array [
567
- "Contentful: 11 cached entries",
606
+ "Contentful: 4 cached entries",
568
607
],
569
608
Array [
570
609
"Contentful: 1 new assets",
@@ -639,7 +678,7 @@ describe(`gatsby-node`, () => {
639
678
expect ( getNode ( blogEntry [ `author___NODE` ] ) ) . toBeTruthy ( )
640
679
} )
641
680
642
- expect ( actions . createNode ) . toHaveBeenCalledTimes ( 50 )
681
+ expect ( actions . createNode ) . toHaveBeenCalledTimes ( 54 )
643
682
expect ( actions . deleteNode ) . toHaveBeenCalledTimes ( 0 )
644
683
expect ( actions . touchNode ) . toHaveBeenCalledTimes ( 72 )
645
684
expect ( reporter . info . mock . calls ) . toMatchInlineSnapshot ( `
@@ -654,7 +693,7 @@ describe(`gatsby-node`, () => {
654
693
"Contentful: 0 deleted entries",
655
694
],
656
695
Array [
657
- "Contentful: 14 cached entries",
696
+ "Contentful: 5 cached entries",
658
697
],
659
698
Array [
660
699
"Contentful: 0 new assets",
@@ -701,6 +740,23 @@ describe(`gatsby-node`, () => {
701
740
// initial sync
702
741
await simulateGatsbyBuild ( )
703
742
743
+ for ( const author of getNodes ( ) . filter (
744
+ n => n . internal . type === `ContentfulPerson`
745
+ ) ) {
746
+ expect ( author [ `blog post___NODE` ] . length ) . toEqual ( 3 )
747
+ expect ( author [ `blog post___NODE` ] ) . toEqual (
748
+ expect . not . arrayContaining ( [
749
+ makeId ( {
750
+ spaceId : removedBlogEntry . sys . space . sys . id ,
751
+ currentLocale : author . node_locale ,
752
+ defaultLocale : locales [ 0 ] ,
753
+ id : removedBlogEntry . sys . id ,
754
+ type : normalizedType ,
755
+ } ) ,
756
+ ] )
757
+ )
758
+ }
759
+
704
760
// create blog post
705
761
await simulateGatsbyBuild ( )
706
762
@@ -712,6 +768,23 @@ describe(`gatsby-node`, () => {
712
768
expect ( blogEntry ) . not . toBeUndefined ( )
713
769
} )
714
770
771
+ for ( const author of getNodes ( ) . filter (
772
+ n => n . internal . type === `ContentfulPerson`
773
+ ) ) {
774
+ expect ( author [ `blog post___NODE` ] . length ) . toEqual ( 4 )
775
+ expect ( author [ `blog post___NODE` ] ) . toEqual (
776
+ expect . arrayContaining ( [
777
+ makeId ( {
778
+ spaceId : removedBlogEntry . sys . space . sys . id ,
779
+ currentLocale : author . node_locale ,
780
+ defaultLocale : locales [ 0 ] ,
781
+ id : removedBlogEntry . sys . id ,
782
+ type : normalizedType ,
783
+ } ) ,
784
+ ] )
785
+ )
786
+ }
787
+
715
788
// remove blog post
716
789
reporter . info . mockClear ( )
717
790
await simulateGatsbyBuild ( )
@@ -734,14 +807,31 @@ describe(`gatsby-node`, () => {
734
807
)
735
808
)
736
809
810
+ for ( const author of getNodes ( ) . filter (
811
+ n => n . internal . type === `ContentfulPerson`
812
+ ) ) {
813
+ expect ( author [ `blog post___NODE` ] . length ) . toEqual ( 3 )
814
+ expect ( author [ `blog post___NODE` ] ) . toEqual (
815
+ expect . not . arrayContaining ( [
816
+ makeId ( {
817
+ spaceId : removedBlogEntry . sys . space . sys . id ,
818
+ currentLocale : author . node_locale ,
819
+ defaultLocale : locales [ 0 ] ,
820
+ id : removedBlogEntry . sys . id ,
821
+ type : normalizedType ,
822
+ } ) ,
823
+ ] )
824
+ )
825
+ }
826
+
737
827
// check if references are gone
738
828
authorIds . forEach ( authorId => {
739
829
expect ( getNode ( authorId ) [ `blog post___NODE` ] ) . toEqual (
740
830
expect . not . arrayContaining ( deletedEntryIds )
741
831
)
742
832
} )
743
833
744
- expect ( actions . createNode ) . toHaveBeenCalledTimes ( 44 )
834
+ expect ( actions . createNode ) . toHaveBeenCalledTimes ( 52 )
745
835
expect ( actions . deleteNode ) . toHaveBeenCalledTimes ( 2 )
746
836
expect ( actions . touchNode ) . toHaveBeenCalledTimes ( 74 )
747
837
expect ( reporter . info . mock . calls ) . toMatchInlineSnapshot ( `
@@ -756,7 +846,7 @@ describe(`gatsby-node`, () => {
756
846
"Contentful: 1 deleted entries",
757
847
],
758
848
Array [
759
- "Contentful: 14 cached entries",
849
+ "Contentful: 5 cached entries",
760
850
],
761
851
Array [
762
852
"Contentful: 0 new assets",
@@ -827,7 +917,7 @@ describe(`gatsby-node`, () => {
827
917
locales
828
918
)
829
919
830
- expect ( actions . createNode ) . toHaveBeenCalledTimes ( 44 )
920
+ expect ( actions . createNode ) . toHaveBeenCalledTimes ( 54 )
831
921
expect ( actions . deleteNode ) . toHaveBeenCalledTimes ( 2 )
832
922
expect ( actions . touchNode ) . toHaveBeenCalledTimes ( 74 )
833
923
expect ( reporter . info . mock . calls ) . toMatchInlineSnapshot ( `
@@ -842,7 +932,7 @@ describe(`gatsby-node`, () => {
842
932
"Contentful: 0 deleted entries",
843
933
],
844
934
Array [
845
- "Contentful: 14 cached entries",
935
+ "Contentful: 5 cached entries",
846
936
],
847
937
Array [
848
938
"Contentful: 0 new assets",
0 commit comments