diff --git a/google-cloud-firestore/conformance/v1/create-all-transforms.json b/google-cloud-firestore/conformance/v1/create-all-transforms.json index 82831624bb1f..638959998797 100644 --- a/google-cloud-firestore/conformance/v1/create-all-transforms.json +++ b/google-cloud-firestore/conformance/v1/create-all-transforms.json @@ -20,50 +20,45 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayremove-multi.json b/google-cloud-firestore/conformance/v1/create-arrayremove-multi.json index 548a9838089e..331a53bf9c86 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayremove-multi.json +++ b/google-cloud-firestore/conformance/v1/create-arrayremove-multi.json @@ -20,46 +20,41 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayremove-nested.json b/google-cloud-firestore/conformance/v1/create-arrayremove-nested.json index fa01bd7e0071..00c73d05ccf2 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayremove-nested.json +++ b/google-cloud-firestore/conformance/v1/create-arrayremove-nested.json @@ -20,30 +20,25 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayremove.json b/google-cloud-firestore/conformance/v1/create-arrayremove.json index a69be14b7b12..646e259f6ffc 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayremove.json +++ b/google-cloud-firestore/conformance/v1/create-arrayremove.json @@ -20,30 +20,25 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayunion-multi.json b/google-cloud-firestore/conformance/v1/create-arrayunion-multi.json index 7ca9852f48d9..5ba324f4297d 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayunion-multi.json +++ b/google-cloud-firestore/conformance/v1/create-arrayunion-multi.json @@ -20,46 +20,41 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "appendMissingElements": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "appendMissingElements": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayunion-nested.json b/google-cloud-firestore/conformance/v1/create-arrayunion-nested.json index a2f20299d3be..2a215090045f 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayunion-nested.json +++ b/google-cloud-firestore/conformance/v1/create-arrayunion-nested.json @@ -20,30 +20,25 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-arrayunion.json b/google-cloud-firestore/conformance/v1/create-arrayunion.json index 26d079946645..99a75feded09 100644 --- a/google-cloud-firestore/conformance/v1/create-arrayunion.json +++ b/google-cloud-firestore/conformance/v1/create-arrayunion.json @@ -20,30 +20,25 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-st-alone.json b/google-cloud-firestore/conformance/v1/create-st-alone.json index 20c5e8ec32a3..177293906b48 100644 --- a/google-cloud-firestore/conformance/v1/create-st-alone.json +++ b/google-cloud-firestore/conformance/v1/create-st-alone.json @@ -10,18 +10,19 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "setToServerValue": "REQUEST_TIME" - } - ] - }, "currentDocument": { "exists": false - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateTransforms": [ + { + "fieldPath": "a", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-st-multi.json b/google-cloud-firestore/conformance/v1/create-st-multi.json index 89430e2b64d6..41f3cd811cf7 100644 --- a/google-cloud-firestore/conformance/v1/create-st-multi.json +++ b/google-cloud-firestore/conformance/v1/create-st-multi.json @@ -20,22 +20,17 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c.d", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c.d", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-st-nested.json b/google-cloud-firestore/conformance/v1/create-st-nested.json index f2a3a8d1f624..7316d916f424 100644 --- a/google-cloud-firestore/conformance/v1/create-st-nested.json +++ b/google-cloud-firestore/conformance/v1/create-st-nested.json @@ -20,18 +20,13 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-st-with-empty-map.json b/google-cloud-firestore/conformance/v1/create-st-with-empty-map.json index 730afd154fd8..b638a0c9db70 100644 --- a/google-cloud-firestore/conformance/v1/create-st-with-empty-map.json +++ b/google-cloud-firestore/conformance/v1/create-st-with-empty-map.json @@ -28,18 +28,13 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/create-st.json b/google-cloud-firestore/conformance/v1/create-st.json index 705f76ed16ac..c4ad4be46b43 100644 --- a/google-cloud-firestore/conformance/v1/create-st.json +++ b/google-cloud-firestore/conformance/v1/create-st.json @@ -20,18 +20,13 @@ }, "currentDocument": { "exists": false - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-all-transforms.json b/google-cloud-firestore/conformance/v1/set-all-transforms.json index 5c8b1373d4c0..a26b51b00710 100644 --- a/google-cloud-firestore/conformance/v1/set-all-transforms.json +++ b/google-cloud-firestore/conformance/v1/set-all-transforms.json @@ -17,50 +17,45 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + } + }, + { + "fieldPath": "d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayremove-multi.json b/google-cloud-firestore/conformance/v1/set-arrayremove-multi.json index 3ea9b0dbd8a8..dc2ace22f845 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayremove-multi.json +++ b/google-cloud-firestore/conformance/v1/set-arrayremove-multi.json @@ -17,46 +17,41 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + } + }, + { + "fieldPath": "c.d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayremove-nested.json b/google-cloud-firestore/conformance/v1/set-arrayremove-nested.json index 4db133f2c54c..1e25b8f26b33 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayremove-nested.json +++ b/google-cloud-firestore/conformance/v1/set-arrayremove-nested.json @@ -17,30 +17,25 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayremove.json b/google-cloud-firestore/conformance/v1/set-arrayremove.json index 18969ef80a5f..e0506b22be4e 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayremove.json +++ b/google-cloud-firestore/conformance/v1/set-arrayremove.json @@ -17,30 +17,25 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayunion-multi.json b/google-cloud-firestore/conformance/v1/set-arrayunion-multi.json index 3d076397c5ff..502d7dc7dff1 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayunion-multi.json +++ b/google-cloud-firestore/conformance/v1/set-arrayunion-multi.json @@ -17,46 +17,41 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "appendMissingElements": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + } + }, + { + "fieldPath": "c.d", + "appendMissingElements": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayunion-nested.json b/google-cloud-firestore/conformance/v1/set-arrayunion-nested.json index e265f6c61375..7084e6bcd91b 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayunion-nested.json +++ b/google-cloud-firestore/conformance/v1/set-arrayunion-nested.json @@ -17,30 +17,25 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-arrayunion.json b/google-cloud-firestore/conformance/v1/set-arrayunion.json index 856e07517327..af12b33dd03e 100644 --- a/google-cloud-firestore/conformance/v1/set-arrayunion.json +++ b/google-cloud-firestore/conformance/v1/set-arrayunion.json @@ -17,30 +17,25 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-alone-mergeall.json b/google-cloud-firestore/conformance/v1/set-st-alone-mergeall.json index d95bf0973b79..f6b60af81095 100644 --- a/google-cloud-firestore/conformance/v1/set-st-alone-mergeall.json +++ b/google-cloud-firestore/conformance/v1/set-st-alone-mergeall.json @@ -13,15 +13,19 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "setToServerValue": "REQUEST_TIME" - } - ] - } + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-alone.json b/google-cloud-firestore/conformance/v1/set-st-alone.json index 3fe931394b0e..1d28fd6f18dc 100644 --- a/google-cloud-firestore/conformance/v1/set-st-alone.json +++ b/google-cloud-firestore/conformance/v1/set-st-alone.json @@ -13,18 +13,13 @@ "update": { "name": "projects/projectID/databases/(default)/documents/C/d", "fields": {} - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-merge-both.json b/google-cloud-firestore/conformance/v1/set-st-merge-both.json index a39ada55f738..359c899a1e26 100644 --- a/google-cloud-firestore/conformance/v1/set-st-merge-both.json +++ b/google-cloud-firestore/conformance/v1/set-st-merge-both.json @@ -36,18 +36,13 @@ "fieldPaths": [ "a" ] - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf-alone.json b/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf-alone.json index 4193b00ea683..5af99ab0a565 100644 --- a/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf-alone.json +++ b/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf-alone.json @@ -26,18 +26,13 @@ "fieldPaths": [ "h" ] - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "h.g", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "h.g", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf.json b/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf.json index 5e91d663b8c6..e66ca87bf829 100644 --- a/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf.json +++ b/google-cloud-firestore/conformance/v1/set-st-merge-nonleaf.json @@ -37,18 +37,13 @@ "fieldPaths": [ "h" ] - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "h.g", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "h.g", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-merge-nowrite.json b/google-cloud-firestore/conformance/v1/set-st-merge-nowrite.json index 08fa8b52f54b..44091b1276e3 100644 --- a/google-cloud-firestore/conformance/v1/set-st-merge-nowrite.json +++ b/google-cloud-firestore/conformance/v1/set-st-merge-nowrite.json @@ -19,15 +19,19 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-mergeall.json b/google-cloud-firestore/conformance/v1/set-st-mergeall.json index 26883c03820d..f913d69e61fe 100644 --- a/google-cloud-firestore/conformance/v1/set-st-mergeall.json +++ b/google-cloud-firestore/conformance/v1/set-st-mergeall.json @@ -25,18 +25,13 @@ "fieldPaths": [ "a" ] - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-multi.json b/google-cloud-firestore/conformance/v1/set-st-multi.json index 23c06f4976f7..03200729cad5 100644 --- a/google-cloud-firestore/conformance/v1/set-st-multi.json +++ b/google-cloud-firestore/conformance/v1/set-st-multi.json @@ -17,22 +17,17 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c.d", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c.d", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-nested.json b/google-cloud-firestore/conformance/v1/set-st-nested.json index 5c94c33f943d..58406e80b366 100644 --- a/google-cloud-firestore/conformance/v1/set-st-nested.json +++ b/google-cloud-firestore/conformance/v1/set-st-nested.json @@ -17,18 +17,13 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st-with-empty-map.json b/google-cloud-firestore/conformance/v1/set-st-with-empty-map.json index 063c94a0e6cd..a40786653783 100644 --- a/google-cloud-firestore/conformance/v1/set-st-with-empty-map.json +++ b/google-cloud-firestore/conformance/v1/set-st-with-empty-map.json @@ -25,18 +25,13 @@ } } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/set-st.json b/google-cloud-firestore/conformance/v1/set-st.json index 42f2b14f1c7f..3e55ae111b50 100644 --- a/google-cloud-firestore/conformance/v1/set-st.json +++ b/google-cloud-firestore/conformance/v1/set-st.json @@ -17,18 +17,13 @@ "integerValue": "1" } } - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-all-transforms.json b/google-cloud-firestore/conformance/v1/update-all-transforms.json index 6f6a725df0fc..72b16d3a1b07 100644 --- a/google-cloud-firestore/conformance/v1/update-all-transforms.json +++ b/google-cloud-firestore/conformance/v1/update-all-transforms.json @@ -25,50 +25,45 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayremove-alone.json b/google-cloud-firestore/conformance/v1/update-arrayremove-alone.json index 86fc8802e52e..93b8ff0528b7 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayremove-alone.json +++ b/google-cloud-firestore/conformance/v1/update-arrayremove-alone.json @@ -10,31 +10,35 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - } - ] - }, "currentDocument": { "exists": true - } - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + } + } + ] + } ] } } diff --git a/google-cloud-firestore/conformance/v1/update-arrayremove-multi.json b/google-cloud-firestore/conformance/v1/update-arrayremove-multi.json index df880f6792b9..18ed0fddea37 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayremove-multi.json +++ b/google-cloud-firestore/conformance/v1/update-arrayremove-multi.json @@ -26,46 +26,41 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayremove-nested.json b/google-cloud-firestore/conformance/v1/update-arrayremove-nested.json index 28d59aff661f..7159797c77bc 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayremove-nested.json +++ b/google-cloud-firestore/conformance/v1/update-arrayremove-nested.json @@ -26,30 +26,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayremove.json b/google-cloud-firestore/conformance/v1/update-arrayremove.json index d925704db63b..2311f916de50 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayremove.json +++ b/google-cloud-firestore/conformance/v1/update-arrayremove.json @@ -25,30 +25,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayunion-alone.json b/google-cloud-firestore/conformance/v1/update-arrayunion-alone.json index 757ea48c3b7f..5cb08579cb1f 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayunion-alone.json +++ b/google-cloud-firestore/conformance/v1/update-arrayunion-alone.json @@ -10,30 +10,34 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + }, + "fieldPath": "a" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayunion-multi.json b/google-cloud-firestore/conformance/v1/update-arrayunion-multi.json index 3aafcd0f3545..674ce2b4c25b 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayunion-multi.json +++ b/google-cloud-firestore/conformance/v1/update-arrayunion-multi.json @@ -26,46 +26,41 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "appendMissingElements": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "appendMissingElements": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayunion-nested.json b/google-cloud-firestore/conformance/v1/update-arrayunion-nested.json index f2bf3770dc77..841ceed0acce 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayunion-nested.json +++ b/google-cloud-firestore/conformance/v1/update-arrayunion-nested.json @@ -26,30 +26,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-arrayunion.json b/google-cloud-firestore/conformance/v1/update-arrayunion.json index 60192c9f8c0b..0aca2356c1a2 100644 --- a/google-cloud-firestore/conformance/v1/update-arrayunion.json +++ b/google-cloud-firestore/conformance/v1/update-arrayunion.json @@ -25,30 +25,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-nested-transform-and-nested-value.json b/google-cloud-firestore/conformance/v1/update-nested-transform-and-nested-value.json index ff7bfc6ee944..2ccba0985a7f 100644 --- a/google-cloud-firestore/conformance/v1/update-nested-transform-and-nested-value.json +++ b/google-cloud-firestore/conformance/v1/update-nested-transform-and-nested-value.json @@ -31,18 +31,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-all-transforms.json b/google-cloud-firestore/conformance/v1/update-paths-all-transforms.json index 01a4c1143dc1..40adbcaf5674 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-all-transforms.json +++ b/google-cloud-firestore/conformance/v1/update-paths-all-transforms.json @@ -52,50 +52,45 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-alone.json b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-alone.json index 9bc8a1440137..4097f58885b5 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-alone.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-alone.json @@ -19,30 +19,34 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-multi.json b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-multi.json index 9a8547120e3a..5e76d07bac9b 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-multi.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-multi.json @@ -47,46 +47,41 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "removeAllFromArray": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "removeAllFromArray": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-nested.json b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-nested.json index e7f952ec3423..9ee1b2a6fe68 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayremove-nested.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayremove-nested.json @@ -41,30 +41,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayremove.json b/google-cloud-firestore/conformance/v1/update-paths-arrayremove.json index 673a2ca2c1af..a7be888daf04 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayremove.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayremove.json @@ -40,30 +40,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "removeAllFromArray": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "removeAllFromArray": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-alone.json b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-alone.json index 81e1e9771ab7..2375d0cedb66 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-alone.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-alone.json @@ -19,30 +19,34 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] + }, + "fieldPath": "a" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-multi.json b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-multi.json index ef421bdad180..afb6437417a6 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-multi.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-multi.json @@ -47,46 +47,41 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } - }, - { - "fieldPath": "c.d", - "appendMissingElements": { - "values": [ - { - "integerValue": "4" - }, - { - "integerValue": "5" - }, - { - "integerValue": "6" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + }, + { + "fieldPath": "c.d", + "appendMissingElements": { + "values": [ + { + "integerValue": "4" + }, + { + "integerValue": "5" + }, + { + "integerValue": "6" + } + ] + } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-nested.json b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-nested.json index 2d73527a4048..d908d02055a5 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayunion-nested.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayunion-nested.json @@ -41,30 +41,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-arrayunion.json b/google-cloud-firestore/conformance/v1/update-paths-arrayunion.json index 1401993d059d..ed2966aede75 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-arrayunion.json +++ b/google-cloud-firestore/conformance/v1/update-paths-arrayunion.json @@ -40,30 +40,25 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "appendMissingElements": { - "values": [ - { - "integerValue": "1" - }, - { - "integerValue": "2" - }, - { - "integerValue": "3" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "appendMissingElements": { + "values": [ + { + "integerValue": "1" + }, + { + "integerValue": "2" + }, + { + "integerValue": "3" + } + ] } - ] - } + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-nested-transform-and-nested-value.json b/google-cloud-firestore/conformance/v1/update-paths-nested-transform-and-nested-value.json index 927d783aee46..c4dead09e0b4 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-nested-transform-and-nested-value.json +++ b/google-cloud-firestore/conformance/v1/update-paths-nested-transform-and-nested-value.json @@ -48,18 +48,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-st-alone.json b/google-cloud-firestore/conformance/v1/update-paths-st-alone.json index 085d04987713..668c1c932bf0 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-st-alone.json +++ b/google-cloud-firestore/conformance/v1/update-paths-st-alone.json @@ -19,18 +19,22 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "setToServerValue": "REQUEST_TIME" - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-st-multi.json b/google-cloud-firestore/conformance/v1/update-paths-st-multi.json index 2d813801ac33..8767cf349795 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-st-multi.json +++ b/google-cloud-firestore/conformance/v1/update-paths-st-multi.json @@ -47,22 +47,17 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c.d", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c.d", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-st-nested.json b/google-cloud-firestore/conformance/v1/update-paths-st-nested.json index 8bd35c9111b1..94ecaccaa403 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-st-nested.json +++ b/google-cloud-firestore/conformance/v1/update-paths-st-nested.json @@ -41,18 +41,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-st-with-empty-map.json b/google-cloud-firestore/conformance/v1/update-paths-st-with-empty-map.json index ac60b2771d37..a86ae46cd183 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-st-with-empty-map.json +++ b/google-cloud-firestore/conformance/v1/update-paths-st-with-empty-map.json @@ -40,20 +40,15 @@ "a" ] }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ], "currentDocument": { "exists": true } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } } ] } diff --git a/google-cloud-firestore/conformance/v1/update-paths-st.json b/google-cloud-firestore/conformance/v1/update-paths-st.json index 011405b9bf7b..1710508b2d17 100644 --- a/google-cloud-firestore/conformance/v1/update-paths-st.json +++ b/google-cloud-firestore/conformance/v1/update-paths-st.json @@ -40,18 +40,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st-alone.json b/google-cloud-firestore/conformance/v1/update-st-alone.json index 1a333f30cbb6..49fab1769153 100644 --- a/google-cloud-firestore/conformance/v1/update-st-alone.json +++ b/google-cloud-firestore/conformance/v1/update-st-alone.json @@ -10,18 +10,22 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a", - "setToServerValue": "REQUEST_TIME" - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st-dot.json b/google-cloud-firestore/conformance/v1/update-st-dot.json index 83422ca5271f..8b9a76902166 100644 --- a/google-cloud-firestore/conformance/v1/update-st-dot.json +++ b/google-cloud-firestore/conformance/v1/update-st-dot.json @@ -10,18 +10,22 @@ "database": "projects/projectID/databases/(default)", "writes": [ { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.b.c", - "setToServerValue": "REQUEST_TIME" - } - ] - }, "currentDocument": { "exists": true - } + }, + "update": { + "fields": {}, + "name": "projects/projectID/databases/(default)/documents/C/d" + }, + "updateMask": { + "fieldPaths": [] + }, + "updateTransforms": [ + { + "fieldPath": "a.b.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st-multi.json b/google-cloud-firestore/conformance/v1/update-st-multi.json index 8105ec27f543..f474112b635f 100644 --- a/google-cloud-firestore/conformance/v1/update-st-multi.json +++ b/google-cloud-firestore/conformance/v1/update-st-multi.json @@ -26,22 +26,17 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - }, - { - "fieldPath": "c.d", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + }, + { + "fieldPath": "c.d", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st-nested.json b/google-cloud-firestore/conformance/v1/update-st-nested.json index 5a8e73237c34..fa9f46b49f6a 100644 --- a/google-cloud-firestore/conformance/v1/update-st-nested.json +++ b/google-cloud-firestore/conformance/v1/update-st-nested.json @@ -26,18 +26,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st-with-empty-map.json b/google-cloud-firestore/conformance/v1/update-st-with-empty-map.json index abeceb03ea8e..4a2c27dfb017 100644 --- a/google-cloud-firestore/conformance/v1/update-st-with-empty-map.json +++ b/google-cloud-firestore/conformance/v1/update-st-with-empty-map.json @@ -33,18 +33,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "a.c", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/conformance/v1/update-st.json b/google-cloud-firestore/conformance/v1/update-st.json index 6249d8bda90d..71d17f3c7a86 100644 --- a/google-cloud-firestore/conformance/v1/update-st.json +++ b/google-cloud-firestore/conformance/v1/update-st.json @@ -25,18 +25,13 @@ }, "currentDocument": { "exists": true - } - }, - { - "transform": { - "document": "projects/projectID/databases/(default)/documents/C/d", - "fieldTransforms": [ - { - "fieldPath": "b", - "setToServerValue": "REQUEST_TIME" - } - ] - } + }, + "updateTransforms": [ + { + "fieldPath": "b", + "setToServerValue": "REQUEST_TIME" + } + ] } ] } diff --git a/google-cloud-firestore/lib/google/cloud/firestore/batch.rb b/google-cloud-firestore/lib/google/cloud/firestore/batch.rb index 6f64a8cb63c0..a2ced094de02 100644 --- a/google-cloud-firestore/lib/google/cloud/firestore/batch.rb +++ b/google-cloud-firestore/lib/google/cloud/firestore/batch.rb @@ -119,7 +119,7 @@ def create doc, data doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_create(doc_path, data) + @writes << Convert.write_for_create(doc_path, data) nil end @@ -218,7 +218,7 @@ def set doc, data, merge: nil doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_set(doc_path, data, merge: merge) + @writes << Convert.write_for_set(doc_path, data, merge: merge) nil end @@ -322,8 +322,8 @@ def update doc, data, update_time: nil doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_update(doc_path, data, - update_time: update_time) + @writes << Convert.write_for_update(doc_path, data, + update_time: update_time) nil end diff --git a/google-cloud-firestore/lib/google/cloud/firestore/convert.rb b/google-cloud-firestore/lib/google/cloud/firestore/convert.rb index 94afbb78ed74..1dbf67b332e8 100644 --- a/google-cloud-firestore/lib/google/cloud/firestore/convert.rb +++ b/google-cloud-firestore/lib/google/cloud/firestore/convert.rb @@ -24,7 +24,13 @@ module Firestore ## # @private Helper module for converting Protobuf values. module Convert - # rubocop:disable all + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/BlockLength + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/ModuleLength + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Style/CaseEquality module ClassMethods def time_to_timestamp time return nil if time.nil? @@ -32,9 +38,10 @@ def time_to_timestamp time # Force the object to be a Time object. time = time.to_time - Google::Protobuf::Timestamp.new \ + Google::Protobuf::Timestamp.new( seconds: time.to_i, - nanos: time.nsec + nanos: time.nsec + ) end def timestamp_to_time timestamp @@ -100,9 +107,10 @@ def raw_to_value obj elsif Google::Cloud::Firestore::DocumentReference === obj Google::Cloud::Firestore::V1::Value.new reference_value: obj.path elsif Array === obj - values = obj.map { |o| raw_to_value(o) } - Google::Cloud::Firestore::V1::Value.new(array_value: - Google::Cloud::Firestore::V1::ArrayValue.new(values: values)) + values = obj.map { |o| raw_to_value o } + Google::Cloud::Firestore::V1::Value.new( + array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: values) + ) elsif Hash === obj # keys have been changed to strings before the hash gets here geo_pairs = hash_is_geo_point? obj @@ -112,8 +120,9 @@ def raw_to_value obj ) else fields = hash_to_fields obj - Google::Cloud::Firestore::V1::Value.new(map_value: - Google::Cloud::Firestore::V1::MapValue.new(fields: fields)) + Google::Cloud::Firestore::V1::Value.new( + map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: fields) + ) end elsif obj.respond_to?(:read) && obj.respond_to?(:rewind) obj.rewind @@ -129,9 +138,7 @@ def hash_is_geo_point? hash return false unless hash.keys.count == 2 pairs = hash.map { |k, v| [String(k), v] }.sort - if pairs.map(&:first) == ["latitude", "longitude"] - pairs - end + pairs if pairs.map(&:first) == ["latitude", "longitude"] end def hash_to_geo_point hash, pairs = nil @@ -140,47 +147,39 @@ def hash_to_geo_point hash, pairs = nil raise ArgumentError, "value is not a geo point" unless pairs Google::Type::LatLng.new( - latitude: pairs.first.last, - longitude: pairs.last.last, + latitude: pairs.first.last, + longitude: pairs.last.last ) end - def writes_for_create doc_path, data - writes = [] - - if is_field_value_nested data, :delete + def write_for_create doc_path, data + if field_value_nested? data, :delete raise ArgumentError, "DELETE not allowed on create" end raise ArgumentError, "data is required" unless data.is_a? Hash data, field_paths_and_values = remove_field_value_from data - if data.any? || field_paths_and_values.empty? - write = Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: doc_path, - fields: hash_to_fields(data)), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ) - writes << write - end - - if field_paths_and_values.any? - transform_write = transform_write doc_path, field_paths_and_values - - if data.empty? - transform_write.current_document = \ - Google::Cloud::Firestore::V1::Precondition.new(exists: false) - end - - writes << transform_write - end + doc = Google::Cloud::Firestore::V1::Document.new( + name: doc_path, + fields: hash_to_fields(data) + ) + precondition = Google::Cloud::Firestore::V1::Precondition.new exists: false + Google::Cloud::Firestore::V1::Write.new( + update: doc, + current_document: precondition, + update_transforms: field_transforms(field_paths_and_values) + ) + end - writes + def field_transforms paths + return nil if paths.empty? + paths.map do |field_path, field_value| + to_field_transform field_path, field_value + end.to_a end - def writes_for_set doc_path, data, merge: nil + def write_for_set doc_path, data, merge: nil raise ArgumentError, "data is required" unless data.is_a? Hash if merge @@ -195,11 +194,9 @@ def writes_for_set doc_path, data, merge: nil end allow_empty = false end - return writes_for_set_merge doc_path, data, field_paths, allow_empty + return write_for_set_merge doc_path, data, field_paths, allow_empty end - writes = [] - data, delete_paths = remove_field_value_from data, :delete if delete_paths.any? raise ArgumentError, "DELETE not allowed on set" @@ -207,30 +204,25 @@ def writes_for_set doc_path, data, merge: nil data, field_paths_and_values = remove_field_value_from data - writes << Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: doc_path, - fields: hash_to_fields(data)) + doc = Google::Cloud::Firestore::V1::Document.new( + name: doc_path, + fields: hash_to_fields(data) + ) + Google::Cloud::Firestore::V1::Write.new( + update: doc, + update_transforms: field_transforms(field_paths_and_values) ) - - if field_paths_and_values.any? - writes << transform_write(doc_path, field_paths_and_values) - end - - writes end - def writes_for_set_merge doc_path, data, field_paths, allow_empty + def write_for_set_merge doc_path, data, field_paths, allow_empty raise ArgumentError, "data is required" unless data.is_a? Hash validate_field_paths! field_paths - writes = [] - # Ensure provided field paths are valid. all_valid = identify_leaf_nodes data all_valid_check = field_paths.map do |verify_path| - if all_valid.include?(verify_path) + if all_valid.include? verify_path true else found_in_all_valid = all_valid.select do |fp| @@ -277,26 +269,21 @@ def writes_for_set_merge doc_path, data, field_paths, allow_empty end end - if data.any? || field_paths.any? || (allow_empty && field_paths_and_values.empty?) - writes << Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: doc_path, - fields: hash_to_fields(data)), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: field_paths.map(&:formatted_string).sort) - ) - end - - if field_paths_and_values.any? - writes << transform_write(doc_path, field_paths_and_values) - end - - writes + doc = Google::Cloud::Firestore::V1::Document.new( + name: doc_path, + fields: hash_to_fields(data) + ) + doc_mask = Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: field_paths.map(&:formatted_string).sort + ) + Google::Cloud::Firestore::V1::Write.new( + update: doc, + update_mask: doc_mask, + update_transforms: field_transforms(field_paths_and_values) + ) end - def writes_for_update doc_path, data, update_time: nil - writes = [] - + def write_for_update doc_path, data, update_time: nil raise ArgumentError, "data is required" unless data.is_a? Hash # Convert data to use FieldPath @@ -308,11 +295,11 @@ def writes_for_update doc_path, data, update_time: nil # Duplicate field paths check validate_field_paths! new_data_pairs.map(&:first) - delete_paths, new_data_pairs = new_data_pairs.partition do |field_path, value| + delete_paths, new_data_pairs = new_data_pairs.partition do |_field_path, value| value.is_a?(FieldValue) && value.type == :delete end - root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do |field_path, value| + root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do |_field_path, value| value.is_a? FieldValue end @@ -325,7 +312,7 @@ def writes_for_update doc_path, data, update_time: nil data, nested_deletes = remove_field_value_from data, :delete raise ArgumentError, "DELETE cannot be nested" if nested_deletes.any? - data, nested_field_paths_and_values = remove_field_value_from data + data, nested_field_paths_and_values = remove_field_value_from data field_paths_and_values = root_field_paths_and_values.merge nested_field_paths_and_values @@ -338,34 +325,31 @@ def writes_for_update doc_path, data, update_time: nil raise ArgumentError, "data is required" end + write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new(name: doc_path), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + if data.any? || delete_paths.any? - write = Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: doc_path, - fields: hash_to_fields(data)), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: (field_paths).map(&:formatted_string).sort), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: true) - ) + htf = hash_to_fields data + htf.each_pair do |k, v| + write.update.fields[k] = v + end + write.update_mask.field_paths += field_paths.map(&:formatted_string).sort + if update_time - write.current_document = \ - Google::Cloud::Firestore::V1::Precondition.new( - update_time: time_to_timestamp(update_time)) + write.current_document = Google::Cloud::Firestore::V1::Precondition.new( + update_time: time_to_timestamp(update_time) + ) end - writes << write end if field_paths_and_values.any? - transform_write = transform_write doc_path, field_paths_and_values - if data.empty? - transform_write.current_document = \ - Google::Cloud::Firestore::V1::Precondition.new(exists: true) - end - writes << transform_write + write.update_transforms += field_transforms field_paths_and_values end - writes + write end def write_for_delete doc_path, exists: nil, update_time: nil @@ -387,13 +371,19 @@ def write_for_delete doc_path, exists: nil, update_time: nil write end - def is_field_value_nested obj, field_value_type = nil + def field_value_nested? obj, field_value_type = nil return obj if obj.is_a?(FieldValue) && (field_value_type.nil? || obj.type == field_value_type) if obj.is_a? Array - obj.each { |o| val = is_field_value_nested o, field_value_type; return val if val } + obj.each do |o| + val = field_value_nested? o, field_value_type + return val if val + end elsif obj.is_a? Hash - obj.each { |_k, v| val = is_field_value_nested v, field_value_type; return val if val } + obj.each do |_k, v| + val = field_value_nested? v, field_value_type + return val if val + end end nil end @@ -406,35 +396,33 @@ def remove_field_value_from obj, field_value_type = nil if value.is_a?(FieldValue) && (field_value_type.nil? || value.type == field_value_type) paths << [FieldPath.new(*key), value] nil # will be removed by calling compact - else - if value.is_a? Hash - unless value.empty? - nested_hash, nested_paths = remove_field_value_from value, field_value_type - if nested_paths.any? - nested_paths.each do |nested_field_path, nested_field_value| - updated_field_paths = ([key] + nested_field_path.fields).flatten - updated_field_path = FieldPath.new *updated_field_paths - paths << [updated_field_path, nested_field_value] - end - end - if nested_hash.empty? - nil # will be removed by calling compact - else - [String(key), nested_hash] + elsif value.is_a? Hash + if value.empty? + [String(key), value] + else + nested_hash, nested_paths = remove_field_value_from value, field_value_type + if nested_paths.any? + nested_paths.each do |nested_field_path, nested_field_value| + updated_field_paths = ([key] + nested_field_path.fields).flatten + updated_field_path = FieldPath.new(*updated_field_paths) + paths << [updated_field_path, nested_field_value] end + end + if nested_hash.empty? + nil # will be removed by calling compact else - [String(key), value] + [String(key), nested_hash] end - else - if value.is_a? Array - nested_field_value = is_field_value_nested value, field_value_type - if nested_field_value - raise ArgumentError, "cannot nest #{nested_field_value.type} under arrays" - end + end + else + if value.is_a? Array + nested_field_value = field_value_nested? value, field_value_type + if nested_field_value + raise ArgumentError, "cannot nest #{nested_field_value.type} under arrays" end - - [String(key), value] end + + [String(key), value] end end @@ -449,14 +437,14 @@ def identify_leaf_nodes hash if value.is_a? Hash nested_paths = identify_leaf_nodes value nested_paths.each do |nested_path| - paths << (([key] + nested_path.fields).flatten) + paths << ([key] + nested_path.fields).flatten end else paths << [key] end end - paths.map { |path| FieldPath.new *path } + paths.map { |path| FieldPath.new(*path) } end def identify_all_file_paths hash @@ -465,15 +453,14 @@ def identify_all_file_paths hash hash.map do |key, value| paths << [key] - if value.is_a? Hash - nested_paths = identify_all_file_paths value - nested_paths.each do |nested_path| - paths << (([key] + nested_path.fields).flatten) - end + next unless value.is_a? Hash + nested_paths = identify_all_file_paths value + nested_paths.each do |nested_path| + paths << ([key] + nested_path.fields).flatten end end - paths.map { |path| FieldPath.new *path } + paths.map { |path| FieldPath.new(*path) } end def select_by_field_paths hash, field_paths @@ -533,19 +520,19 @@ def deep_merge_hashes left_hash, right_hash right_hash.each_pair do |key, right_value| left_value = left_hash[key] - if left_value.is_a?(Hash) && right_value.is_a?(Hash) - left_hash[key] = deep_merge_hashes left_value, right_value - else - left_hash[key] = right_value - end + left_hash[key] = if left_value.is_a?(Hash) && right_value.is_a?(Hash) + deep_merge_hashes left_value, right_value + else + right_value + end end left_hash end - START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/ - INVALID_FIELD_PATH_CHARS = /[\~\*\/\[\]]/ - ESCAPED_FIELD_PATH = /\A\`(.*)\`\z/ + START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/.freeze + INVALID_FIELD_PATH_CHARS = %r{[\~\*/\[\]]}.freeze + ESCAPED_FIELD_PATH = /\A\`(.*)\`\z/.freeze def build_hash_from_field_paths_and_values pairs pairs.each do |field_path, _value| @@ -579,59 +566,52 @@ def escape_field_path str "`#{str}`" end - def transform_write doc_path, paths - field_transforms = paths.map do |field_path, field_value| - to_field_transform field_path, field_value - end - - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: doc_path, - field_transforms: field_transforms - ) - ) - end - def to_field_transform field_path, field_value if field_value.type == :server_time Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: field_path.formatted_string, + field_path: field_path.formatted_string, set_to_server_value: :REQUEST_TIME ) elsif field_value.type == :array_union Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: field_path.formatted_string, + field_path: field_path.formatted_string, append_missing_elements: raw_to_value(Array(field_value.value)).array_value ) elsif field_value.type == :array_delete Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: field_path.formatted_string, + field_path: field_path.formatted_string, remove_all_from_array: raw_to_value(Array(field_value.value)).array_value ) elsif field_value.type == :increment Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( field_path: field_path.formatted_string, - increment: raw_to_value(field_value.value) + increment: raw_to_value(field_value.value) ) elsif field_value.type == :maximum Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( field_path: field_path.formatted_string, - maximum: raw_to_value(field_value.value) + maximum: raw_to_value(field_value.value) ) elsif field_value.type == :minimum Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( field_path: field_path.formatted_string, - minimum: raw_to_value(field_value.value) + minimum: raw_to_value(field_value.value) ) else raise ArgumentError, "unknown field transform #{field_value.type}" end end end - # rubocop:enable all extend ClassMethods end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/BlockLength + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/ModuleLength + # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Style/CaseEquality end end end diff --git a/google-cloud-firestore/lib/google/cloud/firestore/transaction.rb b/google-cloud-firestore/lib/google/cloud/firestore/transaction.rb index aa0a1a1ce4be..a072d63f2187 100644 --- a/google-cloud-firestore/lib/google/cloud/firestore/transaction.rb +++ b/google-cloud-firestore/lib/google/cloud/firestore/transaction.rb @@ -321,7 +321,7 @@ def create doc, data doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_create(doc_path, data) + @writes << Convert.write_for_create(doc_path, data) nil end @@ -422,7 +422,7 @@ def set doc, data, merge: nil doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_set(doc_path, data, merge: merge) + @writes << Convert.write_for_set(doc_path, data, merge: merge) nil end @@ -526,8 +526,8 @@ def update doc, data, update_time: nil doc_path = coalesce_doc_path_argument doc - @writes << Convert.writes_for_update(doc_path, data, - update_time: update_time) + @writes << Convert.write_for_update(doc_path, data, + update_time: update_time) nil end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/is_field_value_nested_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/is_field_value_nested_test.rb index ebcccf2c6acc..a28968623674 100644 --- a/google-cloud-firestore/test/google/cloud/firestore/convert/is_field_value_nested_test.rb +++ b/google-cloud-firestore/test/google/cloud/firestore/convert/is_field_value_nested_test.rb @@ -14,7 +14,7 @@ require "helper" -describe Google::Cloud::Firestore::Convert, :is_field_value_nested do +describe Google::Cloud::Firestore::Convert, :field_value_nested? do # These tests are a sanity check on the implementation of the conversion methods. # These tests are testing private methods and this is generally not a great idea. # But these conversions are so important that it was decided to do it anyway. @@ -24,112 +24,112 @@ it "finds values belonging to a hash" do obj = { foo: "FOO", bar: hello_field_value } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds values belonging to an array" do obj = ["FOO", hello_field_value] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds values belonging to a nested hash" do obj = { foo: "FOO", bar: { baz: hello_field_value } } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds values belonging to a hash nested under an array" do obj = [:ZOMG, { foo: "FOO", bar: hello_field_value }] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds values belonging to a nested array" do obj = ["FOO", ["BAR", hello_field_value]] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds values belonging to an array nested under a hash" do obj = { foo: ["FOO", hello_field_value] } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "finds value that is the object" do obj = hello_field_value - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_equal hello_field_value end it "does not find value on nil" do obj = nil - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on a hash" do obj = { foo: "BAR", baz: "BIF" } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on an array" do obj = ["BAZ", "BIF"] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on a nested hash" do obj = { foo: { bar: :BAZ } } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on a hash nested under an array" do obj = ["BAZ", "BIF", { foo: :BAR }] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on a nested array" do obj = [:foo, :bar, ["BAZ", "BIF"]] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on an array nested under a hash" do obj = { foo: { bar: ["BAZ", "BIF"] } } - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on empty hash" do obj = {} - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end it "does not find value on empty array" do obj = [] - resp = Google::Cloud::Firestore::Convert.is_field_value_nested obj, :hello + resp = Google::Cloud::Firestore::Convert.field_value_nested? obj, :hello _(resp).must_be :nil? end end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_create_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_create_test.rb new file mode 100644 index 000000000000..c6d47deeb8c7 --- /dev/null +++ b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_create_test.rb @@ -0,0 +1,928 @@ +# Copyright 2017 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" + +describe Google::Cloud::Firestore::Convert, :write_for_create do + # These tests are a sanity check on the implementation of the conversion methods. + # These tests are testing private methods and this is generally not a great idea. + # But these conversions are so important that it was decided to do it anyway. + + let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } + let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } + let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } + + it "basic create" do + data = { a: 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "complex create" do + data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) + ])), + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(string_value: "three"), + Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) + })) + ])) + })) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "creating empty data" do + data = {} + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new(name: document_path), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "don't split on dots" do + data = { "a.b" => { "c.d" => 1 }, "e" => 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a.b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c.d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })), + "e" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "non-alpha characters in map keys" do + data = { "*" => { "." => 1 }, "~" => 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "." => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })), + "~" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + describe :field_delete do + it "DELETE cannot appear in data" do + data = { a: 1, b: field_delete } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "DELETE not allowed on create" + end + end + + describe :field_server_time do + it "SERVER_TIME alone" do + data = { a: field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "SERVER_TIME with data" do + data = { a: 1, b: field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple SERVER_TIME fields" do + data = { a: 1, b: field_server_time, c: { d: field_server_time } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + set_to_server_value: :REQUEST_TIME + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested SERVER_TIME field" do + data = { a: 1, b: { c: field_server_time } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "SERVER_TIME cannot be anywhere inside an array value" do + data = { a: [1, { b: field_server_time }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest server_time under arrays" + end + + it "SERVER_TIME cannot be in an array value" do + data = { a: [1, 2, field_server_time] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest server_time under arrays" + end + end + + describe :field_array_union do + let(:field_array_union) { Google::Cloud::Firestore::FieldValue.array_union 1, 2, 3 } + + it "ARRAY_UNION alone" do + data = { a: field_array_union } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_UNION with data" do + data = { a: 1, b: field_array_union } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple ARRAY_UNION fields" do + data = { a: 1, b: field_array_union, c: { d: field_array_union } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested ARRAY_UNION field" do + data = { a: 1, b: { c: field_array_union } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_UNION cannot be anywhere inside an array value" do + data = { a: [1, { b: field_array_union }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_union under arrays" + end + + it "ARRAY_UNION cannot be in an array value" do + data = { a: [1, 2, field_array_union] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_union under arrays" + end + end + + describe :field_array_delete do + let(:field_array_delete) { Google::Cloud::Firestore::FieldValue.array_delete 7, 8, 9 } + + it "ARRAY_DELETE alone" do + data = { a: field_array_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_DELETE with data" do + data = { a: 1, b: field_array_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple ARRAY_DELETE fields" do + data = { a: 1, b: field_array_delete, c: { d: field_array_delete } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested ARRAY_DELETE field" do + data = { a: 1, b: { c: field_array_delete } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_DELETE cannot be anywhere inside an array value" do + data = { a: [1, { b: field_array_delete }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_delete under arrays" + end + + it "ARRAY_DELETE cannot be in an array value" do + data = { a: [1, 2, field_array_delete] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_delete under arrays" + end + end + + describe :field_increment do + let(:field_increment) { Google::Cloud::Firestore::FieldValue.increment 1 } + + it "INCREMENT alone" do + data = { a: field_increment } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "INCREMENT with data" do + data = { a: 1, b: field_increment } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple INCREMENT fields" do + data = { a: 1, b: field_increment, c: { d: field_increment } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested INCREMENT field" do + data = { a: 1, b: { c: field_increment } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "INCREMENT cannot be anywhere inside an array value" do + data = { a: [1, { b: field_increment }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest increment under arrays" + end + + it "INCREMENT cannot be in an array value" do + data = { a: [1, 2, field_increment] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest increment under arrays" + end + end + + describe :field_maximum do + let(:field_maximum) { Google::Cloud::Firestore::FieldValue.maximum 1 } + + it "MAXIMUM alone" do + data = { a: field_maximum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "MAXIMUM with data" do + data = { a: 1, b: field_maximum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + exists: false + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple MAXIMUM fields" do + data = { a: 1, b: field_maximum, c: { d: field_maximum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested MAXIMUM field" do + data = { a: 1, b: { c: field_maximum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "MAXIMUM cannot be anywhere inside an array value" do + data = { a: [1, { b: field_maximum }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest maximum under arrays" + end + + it "MAXIMUM cannot be in an array value" do + data = { a: [1, 2, field_maximum] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest maximum under arrays" + end + end + + describe :field_minimum do + let(:field_minimum) { Google::Cloud::Firestore::FieldValue.minimum 1 } + + it "MINIMUM alone" do + data = { a: field_minimum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "MINIMUM with data" do + data = { a: 1, b: field_minimum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple MINIMUM fields" do + data = { a: 1, b: field_minimum, c: { d: field_minimum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested MINIMUM field" do + data = { a: 1, b: { c: field_minimum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_create document_path, data + + _(actual_write).must_equal expected_write + end + + it "MINIMUM cannot be anywhere inside an array value" do + data = { a: [1, { b: field_minimum }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest minimum under arrays" + end + + it "MINIMUM cannot be in an array value" do + data = { a: [1, 2, field_minimum] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_create document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest minimum under arrays" + end + end +end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_set_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_set_test.rb new file mode 100644 index 000000000000..4dc1672aacfe --- /dev/null +++ b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_set_test.rb @@ -0,0 +1,357 @@ +# Copyright 2017 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" + +describe Google::Cloud::Firestore::Convert, :write_for_set do + # These tests are a sanity check on the implementation of the conversion methods. + # These tests are testing private methods and this is generally not a great idea. + # But these conversions are so important that it was decided to do it anyway. + + let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } + let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } + let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } + + it "basic set" do + data = { a: 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data + + _(actual_write).must_equal expected_write + end + + it "complex set" do + data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) + ])), + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(string_value: "three"), + Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) + })) + ])) + })) + } + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data + + _(actual_write).must_equal expected_write + end + + it "setting empty data" do + data = {} + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new(name: document_path) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data + + _(actual_write).must_equal expected_write + end + + it "don't split on dots" do + data = { "a.b" => { "c.d" => 1 }, "e" => 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a.b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c.d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + })), + "e" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) + } + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data + + _(actual_write).must_equal expected_write + end + + it "DELETE cannot be anywhere inside an array value" do + data = { a: [1, { b: field_delete }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest delete under arrays" + end + + it "DELETE cannot be in an array value" do + data = { a: [1, 2, field_delete] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest delete under arrays" + end + + it "DELETE cannot appear in data" do + data = { a: 1, b: field_delete } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "DELETE not allowed on set" + end + + describe "merge: []" do + it "merges with a field" do + data = { a: 1, b: 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["a"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: "a" + + _(actual_write).must_equal expected_write + end + + it "merges with FieldPaths (array)" do + data = { "*" => { "~" => true } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "~" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["`*`.`~`"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: [["*", "~"]] + + _(actual_write).must_equal expected_write + end + + it "merges with FieldPaths (FieldPath)" do + data = { "*" => { "~" => true } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "~" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["`*`.`~`"] + ) + ) + + merge_field_path = Google::Cloud::Firestore::FieldPath.new "*", "~" + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: merge_field_path + + _(actual_write).must_equal expected_write + end + + it "merges a nested field (array)" do + data = { h: { g: 4, f: 5 } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["h.g"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: [["h", "g"]] + + _(actual_write).must_equal expected_write + end + + it "merges a nested field (string)" do + data = { h: { g: 4, f: 5 } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["h.g"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: ["h.g"] + + _(actual_write).must_equal expected_write + end + + it "merges field when not a leaf" do + data = { h: { g: 5, f: 6 }, e: 7 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 5), + "f" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["h"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: [:h] + + _(actual_write).must_equal expected_write + end + + it "does not write data when field is not provided" do + data = { a: 1, b: field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: :b + + _(actual_write).must_equal expected_write + end + + it "fields must all be present in data" do + data = { a: 1 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: ["b", "a"] + end.must_raise ArgumentError + _(error.message).must_equal "all fields must be in data" + end + + it "DELETE cannot appear in an unmerged field" do + data = { a: 1, b: field_delete } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: [:a] + end.must_raise ArgumentError + _(error.message).must_equal "deleted field not included in merge" + end + end + + describe "merge: true" do + it "merges all" do + data = { a: 1, b: 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + "b" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["a", "b"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: true + + _(actual_write).must_equal expected_write + end + + it "merges with nested fields" do + data = { h: { g: 3, f: 4 } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 3), + "f" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( + field_paths: ["h.f", "h.g"] + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: true + + _(actual_write).must_equal expected_write + end + + it "cannot be specified with empty data" do + data = {} + + error = expect do + Google::Cloud::Firestore::Convert.write_for_set document_path, data, merge: [] + end.must_raise ArgumentError + _(error.message).must_equal "data required for set with merge" + end + end +end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_update_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_update_test.rb new file mode 100644 index 000000000000..8b3e4a62019f --- /dev/null +++ b/google-cloud-firestore/test/google/cloud/firestore/convert/write_for_update_test.rb @@ -0,0 +1,1409 @@ +# Copyright 2017 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" + +describe Google::Cloud::Firestore::Convert, :write_for_update do + # These tests are a sanity check on the implementation of the conversion methods. + # These tests are testing private methods and this is generally not a great idea. + # But these conversions are so important that it was decided to do it anyway. + + let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } + let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } + let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } + + it "basic update" do + data = { a: 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested empty hashes create writes" do + data = { "i.j" => { l: {} } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "i" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "j" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "l" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: {})) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["i.j"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "complex update" do + data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: document_path, + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) + ])), + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ + Google::Cloud::Firestore::V1::Value.new(string_value: "three"), + Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) + })) + ])) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "invalid character" do + data = { "a~b" => 1 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "invalid character, use FieldPath instead" + end + + it "empty field path component" do + data = { "a..b" => 1 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "empty paths not allowed" + end + + it "no paths" do + data = {} + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "data is required" + end + + it "prefix #1" do + data = { "a.b" => 1, a: 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "prefix #2" do + data = { "a" => 1, "a.b" => 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "prefix #3" do + data = { a: { b: 1 }, "a.d".to_sym => 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "quotes paths starting with non-letter starting chars, except underscore" do + data = { "_0.1.+2" => 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "_0" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "1" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "+2" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["_0.`1`.`+2`"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "splits on dots" do + data = { "a.b.c" => 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a.b.c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "splits on dots for top-level keys only" do + data = { "h.g" => { "j.k" => 6 } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "j.k" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["h.g"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "sends update_time as precondition" do + last_updated_at = Time.now - 42 #42 seconds ago + data = { a: 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new( + update_time: Google::Cloud::Firestore::Convert.time_to_timestamp(last_updated_at) + ) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data, update_time: last_updated_at + + _(actual_write).must_equal expected_write + end + + describe "data using field paths" do + it "empty field path component" do + data = { ["a", "", "b"] => 1 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "empty paths not allowed" + end + + it "prefix #1" do + data = { [:a, :b] => 1, [:a] => 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "prefix #2" do + data = { ["a"] => 1, ["a", "b"] => 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "prefix #3" do + data = { a: { b: 1 }, ["a", "d"] => 2 } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "one field cannot be a prefix of another" + end + + it "quotes paths starting with non-letter starting chars, except underscore" do + data = { ["_0", 1, "+2"] => 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "_0" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "1" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "+2" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["_0.`1`.`+2`"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "uses field paths" do + data = { ["a", "b", "c"] => 1 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "c" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a.b.c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "uses field paths for top-level keys only" do + data = { [:h, :g] => { "j.k" => 6 } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "g" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "j.k" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) + })) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["h.g"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + end + + describe :field_delete do + it "with data" do + data = { a: 1, b: field_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "alone" do + data = { a: field_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "with a dotted field" do + data = { a: 1, "b.c" => field_delete, "b.d" => 2 } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { + "d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) + })) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b.c", "b.d"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "DELETE cannot be nested" do + data = { a: { b: field_delete } } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "DELETE cannot be nested" + end + + it "DELETE cannot be anywhere inside an array value" do + data = { a: [1, { b: field_delete }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest delete under arrays" + end + + it "DELETE cannot be in an array value" do + data = { a: [1, 2, field_delete] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest delete under arrays" + end + end + + describe :field_server_time do + it "SERVER_TIME alone" do + data = { a: field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + set_to_server_value: :REQUEST_TIME + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "SERVER_TIME with data" do + data = { a: 1, b: field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "SERVER_TIME with dotted field" do + data = { "a.b.c" => field_server_time } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple SERVER_TIME nested without data" do + data = { + a: field_server_time, + b: { c: field_server_time }, + "e.f" => field_server_time + } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + set_to_server_value: :REQUEST_TIME + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "e.f", + set_to_server_value: :REQUEST_TIME + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + set_to_server_value: :REQUEST_TIME + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple SERVER_TIME with data" do + data = { a: 1, b: field_server_time, c: { d: field_server_time } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + set_to_server_value: :REQUEST_TIME + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested SERVER_TIME with data" do + data = { a: 1, b: { c: field_server_time } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + set_to_server_value: :REQUEST_TIME + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "SERVER_TIME cannot be anywhere inside an array value" do + data = { a: [1, { b: field_server_time }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest server_time under arrays" + end + + it "SERVER_TIME cannot be in an array value" do + data = { a: [1, 2, field_server_time] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest server_time under arrays" + end + end + + describe :field_array_union do + let(:field_array_union) { Google::Cloud::Firestore::FieldValue.array_union 1, 2, 3 } + + it "ARRAY_UNION alone" do + data = { a: field_array_union } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_UNION with data" do + data = { a: 1, b: field_array_union } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_UNION with dotted field" do + data = { "a.b.c" => field_array_union } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple ARRAY_UNION fields" do + data = { a: 1, b: field_array_union, c: { d: field_array_union } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested ARRAY_UNION field" do + data = { a: 1, b: { c: field_array_union } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 1), + Google::Cloud::Firestore::V1::Value.new(integer_value: 2), + Google::Cloud::Firestore::V1::Value.new(integer_value: 3) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_UNION cannot be anywhere inside an array value" do + data = { a: [1, { b: field_array_union }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_union under arrays" + end + + it "ARRAY_UNION cannot be in an array value" do + data = { a: [1, 2, field_array_union] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_union under arrays" + end + end + + describe :field_array_delete do + let(:field_array_delete) { Google::Cloud::Firestore::FieldValue.array_delete 7, 8, 9 } + + it "ARRAY_DELETE alone" do + data = { a: field_array_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_DELETE with data" do + data = { a: 1, b: field_array_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_DELETE with dotted field" do + data = { "a.b.c" => field_array_delete } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple ARRAY_DELETE fields" do + data = { a: 1, b: field_array_delete, c: { d: field_array_delete } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested ARRAY_DELETE field" do + data = { a: 1, b: { c: field_array_delete } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( + values: [ + Google::Cloud::Firestore::V1::Value.new(integer_value: 7), + Google::Cloud::Firestore::V1::Value.new(integer_value: 8), + Google::Cloud::Firestore::V1::Value.new(integer_value: 9) + ] + ) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "ARRAY_DELETE cannot be anywhere inside an array value" do + data = { a: [1, { b: field_array_delete }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_delete under arrays" + end + + it "ARRAY_DELETE cannot be in an array value" do + data = { a: [1, 2, field_array_delete] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest array_delete under arrays" + end + end + + describe :field_increment do + let(:field_increment) { Google::Cloud::Firestore::FieldValue.increment 1 } + + it "INCREMENT alone" do + data = { a: field_increment } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "INCREMENT with data" do + data = { a: 1, b: field_increment } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "INCREMENT with dotted field" do + data = { "a.b.c" => field_increment } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple INCREMENT fields" do + data = { a: 1, b: field_increment, c: { d: field_increment } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested INCREMENT field" do + data = { a: 1, b: { c: field_increment } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "INCREMENT cannot be anywhere inside an array value" do + data = { a: [1, { b: field_increment }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest increment under arrays" + end + + it "INCREMENT cannot be in an array value" do + data = { a: [1, 2, field_increment] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest increment under arrays" + end + end + + describe :field_maximum do + let(:field_maximum) { Google::Cloud::Firestore::FieldValue.maximum 1 } + + it "MAXIMUM alone" do + data = { a: field_maximum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MAXIMUM with data" do + data = { a: 1, b: field_maximum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MAXIMUM with dotted field" do + data = { "a.b.c" => field_maximum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple MAXIMUM fields" do + data = { a: 1, b: field_maximum, c: { d: field_maximum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested MAXIMUM field" do + data = { a: 1, b: { c: field_maximum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MAXIMUM cannot be anywhere inside an array value" do + data = { a: [1, { b: field_maximum }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest maximum under arrays" + end + + it "MAXIMUM cannot be in an array value" do + data = { a: [1, 2, field_maximum] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest maximum under arrays" + end + end + + describe :field_minimum do + let(:field_minimum) { Google::Cloud::Firestore::FieldValue.minimum 1 } + + it "MINIMUM alone" do + data = { a: field_minimum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MINIMUM with data" do + data = { a: 1, b: field_minimum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MINIMUM with dotted field" do + data = { "a.b.c" => field_minimum } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d" + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new, + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "a.b.c", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ], + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "multiple MINIMUM fields" do + data = { a: 1, b: field_minimum, c: { d: field_minimum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ), + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "c.d", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "nested MINIMUM field" do + data = { a: 1, b: { c: field_minimum } } + + expected_write = Google::Cloud::Firestore::V1::Write.new( + update: Google::Cloud::Firestore::V1::Document.new( + name: "projects/projectID/databases/(default)/documents/C/d", + fields: { + "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + } + ), + update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), + current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true), + update_transforms: [ + Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( + field_path: "b.c", + minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) + ) + ] + ) + + actual_write = Google::Cloud::Firestore::Convert.write_for_update document_path, data + + _(actual_write).must_equal expected_write + end + + it "MINIMUM cannot be anywhere inside an array value" do + data = { a: [1, { b: field_minimum }] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest minimum under arrays" + end + + it "MINIMUM cannot be in an array value" do + data = { a: [1, 2, field_minimum] } + + error = expect do + Google::Cloud::Firestore::Convert.write_for_update document_path, data + end.must_raise ArgumentError + _(error.message).must_equal "cannot nest minimum under arrays" + end + end +end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_create_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_create_test.rb deleted file mode 100644 index d589c8e023d7..000000000000 --- a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_create_test.rb +++ /dev/null @@ -1,1070 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -require "helper" - -describe Google::Cloud::Firestore::Convert, :writes_for_create do - # These tests are a sanity check on the implementation of the conversion methods. - # These tests are testing private methods and this is generally not a great idea. - # But these conversions are so important that it was decided to do it anyway. - - let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } - let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } - let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } - - it "basic create" do - data = { a: 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "complex create" do - data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) - ])), - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(string_value: "three"), - Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) - })) - ])) - })) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "creating empty data" do - data = {} - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new(name: document_path), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "don't split on dots" do - data = { "a.b" => { "c.d" => 1 }, "e" => 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a.b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c.d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })), - "e" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "non-alpha characters in map keys" do - data = { "*" => { "." => 1 }, "~" => 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "." => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })), - "~" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - describe :field_delete do - it "DELETE cannot appear in data" do - data = { a: 1, b: field_delete } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "DELETE not allowed on create" - end - end - - describe :field_server_time do - it "SERVER_TIME alone" do - data = { a: field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - set_to_server_value: :REQUEST_TIME - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "SERVER_TIME with data" do - data = { a: 1, b: field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple SERVER_TIME fields" do - data = { a: 1, b: field_server_time, c: { d: field_server_time } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - set_to_server_value: :REQUEST_TIME - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested SERVER_TIME field" do - data = { a: 1, b: { c: field_server_time } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "SERVER_TIME cannot be anywhere inside an array value" do - data = { a: [1, { b: field_server_time }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest server_time under arrays" - end - - it "SERVER_TIME cannot be in an array value" do - data = { a: [1, 2, field_server_time] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest server_time under arrays" - end - end - - describe :field_array_union do - let(:field_array_union) { Google::Cloud::Firestore::FieldValue.array_union 1, 2, 3 } - - it "ARRAY_UNION alone" do - data = { a: field_array_union } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_UNION with data" do - data = { a: 1, b: field_array_union } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple ARRAY_UNION fields" do - data = { a: 1, b: field_array_union, c: { d: field_array_union } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested ARRAY_UNION field" do - data = { a: 1, b: { c: field_array_union } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_UNION cannot be anywhere inside an array value" do - data = { a: [1, { b: field_array_union }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_union under arrays" - end - - it "ARRAY_UNION cannot be in an array value" do - data = { a: [1, 2, field_array_union] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_union under arrays" - end - end - - describe :field_array_delete do - let(:field_array_delete) { Google::Cloud::Firestore::FieldValue.array_delete 7, 8, 9 } - - it "ARRAY_DELETE alone" do - data = { a: field_array_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_DELETE with data" do - data = { a: 1, b: field_array_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple ARRAY_DELETE fields" do - data = { a: 1, b: field_array_delete, c: { d: field_array_delete } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested ARRAY_DELETE field" do - data = { a: 1, b: { c: field_array_delete } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_DELETE cannot be anywhere inside an array value" do - data = { a: [1, { b: field_array_delete }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_delete under arrays" - end - - it "ARRAY_DELETE cannot be in an array value" do - data = { a: [1, 2, field_array_delete] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_delete under arrays" - end - end - - describe :field_increment do - let(:field_increment) { Google::Cloud::Firestore::FieldValue.increment 1 } - - it "INCREMENT alone" do - data = { a: field_increment } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "INCREMENT with data" do - data = { a: 1, b: field_increment } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple INCREMENT fields" do - data = { a: 1, b: field_increment, c: { d: field_increment } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested INCREMENT field" do - data = { a: 1, b: { c: field_increment } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "INCREMENT cannot be anywhere inside an array value" do - data = { a: [1, { b: field_increment }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest increment under arrays" - end - - it "INCREMENT cannot be in an array value" do - data = { a: [1, 2, field_increment] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest increment under arrays" - end - end - - describe :field_maximum do - let(:field_maximum) { Google::Cloud::Firestore::FieldValue.maximum 1 } - - it "MAXIMUM alone" do - data = { a: field_maximum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MAXIMUM with data" do - data = { a: 1, b: field_maximum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple MAXIMUM fields" do - data = { a: 1, b: field_maximum, c: { d: field_maximum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested MAXIMUM field" do - data = { a: 1, b: { c: field_maximum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MAXIMUM cannot be anywhere inside an array value" do - data = { a: [1, { b: field_maximum }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest maximum under arrays" - end - - it "MAXIMUM cannot be in an array value" do - data = { a: [1, 2, field_maximum] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest maximum under arrays" - end - end - - describe :field_minimum do - let(:field_minimum) { Google::Cloud::Firestore::FieldValue.minimum 1 } - - it "MINIMUM alone" do - data = { a: field_minimum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MINIMUM with data" do - data = { a: 1, b: field_minimum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple MINIMUM fields" do - data = { a: 1, b: field_minimum, c: { d: field_minimum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested MINIMUM field" do - data = { a: 1, b: { c: field_minimum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - exists: false) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_create document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MINIMUM cannot be anywhere inside an array value" do - data = { a: [1, { b: field_minimum }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest minimum under arrays" - end - - it "MINIMUM cannot be in an array value" do - data = { a: [1, 2, field_minimum] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_create document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest minimum under arrays" - end - end -end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_set_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_set_test.rb deleted file mode 100644 index 1f30b0b7494c..000000000000 --- a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_set_test.rb +++ /dev/null @@ -1,382 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -require "helper" - -describe Google::Cloud::Firestore::Convert, :writes_for_set do - # These tests are a sanity check on the implementation of the conversion methods. - # These tests are testing private methods and this is generally not a great idea. - # But these conversions are so important that it was decided to do it anyway. - - let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } - let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } - let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } - - it "basic set" do - data = { a: 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "complex set" do - data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) - ])), - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(string_value: "three"), - Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) - })) - ])) - })) - } - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "setting empty data" do - data = {} - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new(name: document_path) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "don't split on dots" do - data = { "a.b" => { "c.d" => 1 }, "e" => 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a.b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c.d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - })), - "e" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) - } - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "DELETE cannot be anywhere inside an array value" do - data = { a: [1, { b: field_delete }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest delete under arrays" - end - - it "DELETE cannot be in an array value" do - data = { a: [1, 2, field_delete] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest delete under arrays" - end - - it "DELETE cannot appear in data" do - data = { a: 1, b: field_delete } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "DELETE not allowed on set" - end - - describe "merge: []" do - it "merges with a field" do - data = { a: 1, b: 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["a"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: "a" - - _(actual_writes).must_equal expected_writes - end - - it "merges with FieldPaths (array)" do - data = { "*" => { "~" => true } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "~" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["`*`.`~`"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: [["*", "~"]] - - _(actual_writes).must_equal expected_writes - end - - it "merges with FieldPaths (FieldPath)" do - data = { "*" => { "~" => true } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "*" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "~" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["`*`.`~`"] - ) - ) - ] - - merge_field_path = Google::Cloud::Firestore::FieldPath.new "*", "~" - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: merge_field_path - - _(actual_writes).must_equal expected_writes - end - - it "merges a nested field (array)" do - data = { h: { g: 4, f: 5 } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["h.g"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: [["h", "g"]] - - _(actual_writes).must_equal expected_writes - end - - it "merges a nested field (string)" do - data = { h: { g: 4, f: 5 } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["h.g"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: ["h.g"] - - _(actual_writes).must_equal expected_writes - end - - it "merges field when not a leaf" do - data = { h: { g: 5, f: 6 }, e: 7 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 5), - "f" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["h"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: [:h] - - _(actual_writes).must_equal expected_writes - end - - it "does not write data when field is not provided" do - data = { a: 1, b: field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: :b - - _(actual_writes).must_equal expected_writes - end - - it "fields must all be present in data" do - data = { a: 1 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: ["b", "a"] - end.must_raise ArgumentError - _(error.message).must_equal "all fields must be in data" - end - - it "DELETE cannot appear in an unmerged field" do - data = { a: 1, b: field_delete } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: [:a] - end.must_raise ArgumentError - _(error.message).must_equal "deleted field not included in merge" - end - end - - describe "merge: true" do - it "merges all" do - data = { a: 1, b: 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - "b" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["a", "b"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: true - - _(actual_writes).must_equal expected_writes - end - - it "merges with nested fields" do - data = { h: { g: 3, f: 4 } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(integer_value: 3), - "f" => Google::Cloud::Firestore::V1::Value.new(integer_value: 4) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new( - field_paths: ["h.f", "h.g"] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: true - - _(actual_writes).must_equal expected_writes - end - - it "cannot be specified with empty data" do - data = {} - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_set document_path, data, merge: [] - end.must_raise ArgumentError - _(error.message).must_equal "data required for set with merge" - end - end -end diff --git a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_update_test.rb b/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_update_test.rb deleted file mode 100644 index 4c118f02028e..000000000000 --- a/google-cloud-firestore/test/google/cloud/firestore/convert/writes_for_update_test.rb +++ /dev/null @@ -1,1539 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -require "helper" - -describe Google::Cloud::Firestore::Convert, :writes_for_update do - # These tests are a sanity check on the implementation of the conversion methods. - # These tests are testing private methods and this is generally not a great idea. - # But these conversions are so important that it was decided to do it anyway. - - let(:document_path) { "projects/projectID/databases/(default)/documents/C/d" } - let(:field_delete) { Google::Cloud::Firestore::FieldValue.delete } - let(:field_server_time) { Google::Cloud::Firestore::FieldValue.server_time } - - it "basic update" do - data = { a: 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested empty hashes create writes" do - data = { "i.j" => { l: {} } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "i" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "j" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "l" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: {})) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["i.j"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "complex update" do - data = { a: [1, 2.5], b: { c: ["three", { d: true }] } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: document_path, - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(double_value: 2.5) - ])), - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c" => Google::Cloud::Firestore::V1::Value.new(array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: [ - Google::Cloud::Firestore::V1::Value.new(string_value: "three"), - Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "d" => Google::Cloud::Firestore::V1::Value.new(boolean_value: true) - })) - ])) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "invalid character" do - data = { "a~b" => 1 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "invalid character, use FieldPath instead" - end - - it "empty field path component" do - data = { "a..b" => 1 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "empty paths not allowed" - end - - it "no paths" do - data = {} - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "data is required" - end - - it "prefix #1" do - data = { "a.b" => 1, a: 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "prefix #2" do - data = { "a" => 1, "a.b" => 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "prefix #3" do - data = { a: { b: 1 }, "a.d".to_sym => 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "quotes paths starting with non-letter starting chars, except underscore" do - data = { "_0.1.+2" => 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "_0" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "1" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "+2" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["_0.`1`.`+2`"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "splits on dots" do - data = { "a.b.c" => 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a.b.c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "splits on dots for top-level keys only" do - data = { "h.g" => { "j.k" => 6 } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "j.k" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["h.g"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "sends update_time as precondition" do - last_updated_at = Time.now - 42 #42 seconds ago - data = { a: 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new( - update_time: Google::Cloud::Firestore::Convert.time_to_timestamp(last_updated_at) - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data, update_time: last_updated_at - - _(actual_writes).must_equal expected_writes - end - - describe "data using field paths" do - it "empty field path component" do - data = { ["a", "", "b"] => 1 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "empty paths not allowed" - end - - it "prefix #1" do - data = { [:a, :b] => 1, [:a] => 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "prefix #2" do - data = { ["a"] => 1, ["a", "b"] => 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "prefix #3" do - data = { a: { b: 1 }, ["a", "d"] => 2 } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "one field cannot be a prefix of another" - end - - it "quotes paths starting with non-letter starting chars, except underscore" do - data = { ["_0", 1, "+2"] => 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "_0" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "1" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "+2" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["_0.`1`.`+2`"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "uses field paths" do - data = { ["a", "b", "c"] => 1 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "c" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a.b.c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "uses field paths for top-level keys only" do - data = { [:h, :g] => { "j.k" => 6 } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "h" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "g" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "j.k" => Google::Cloud::Firestore::V1::Value.new(integer_value: 6) - })) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["h.g"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - end - - describe :field_delete do - it "with data" do - data = { a: 1, b: field_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "alone" do - data = { a: field_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d" - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "with a dotted field" do - data = { a: 1, "b.c" => field_delete, "b.d" => 2 } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - "b" => Google::Cloud::Firestore::V1::Value.new(map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: { - "d" => Google::Cloud::Firestore::V1::Value.new(integer_value: 2) - })) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b.c", "b.d"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "DELETE cannot be nested" do - data = { a: { b: field_delete } } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "DELETE cannot be nested" - end - - it "DELETE cannot be anywhere inside an array value" do - data = { a: [1, { b: field_delete }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest delete under arrays" - end - - it "DELETE cannot be in an array value" do - data = { a: [1, 2, field_delete] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest delete under arrays" - end - end - - describe :field_server_time do - it "SERVER_TIME alone" do - data = { a: field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - set_to_server_value: :REQUEST_TIME - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "SERVER_TIME with data" do - data = { a: 1, b: field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "SERVER_TIME with dotted field" do - data = { "a.b.c" => field_server_time } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - set_to_server_value: :REQUEST_TIME - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple SERVER_TIME fields" do - data = { a: 1, b: field_server_time, c: { d: field_server_time } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - set_to_server_value: :REQUEST_TIME - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested SERVER_TIME field" do - data = { a: 1, b: { c: field_server_time } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - set_to_server_value: :REQUEST_TIME - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "SERVER_TIME cannot be anywhere inside an array value" do - data = { a: [1, { b: field_server_time }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest server_time under arrays" - end - - it "SERVER_TIME cannot be in an array value" do - data = { a: [1, 2, field_server_time] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest server_time under arrays" - end - end - - describe :field_array_union do - let(:field_array_union) { Google::Cloud::Firestore::FieldValue.array_union 1, 2, 3 } - - it "ARRAY_UNION alone" do - data = { a: field_array_union } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_UNION with data" do - data = { a: 1, b: field_array_union } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_UNION with dotted field" do - data = { "a.b.c" => field_array_union } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple ARRAY_UNION fields" do - data = { a: 1, b: field_array_union, c: { d: field_array_union } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested ARRAY_UNION field" do - data = { a: 1, b: { c: field_array_union } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - append_missing_elements: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 1), - Google::Cloud::Firestore::V1::Value.new(integer_value: 2), - Google::Cloud::Firestore::V1::Value.new(integer_value: 3) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_UNION cannot be anywhere inside an array value" do - data = { a: [1, { b: field_array_union }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_union under arrays" - end - - it "ARRAY_UNION cannot be in an array value" do - data = { a: [1, 2, field_array_union] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_union under arrays" - end - end - - describe :field_array_delete do - let(:field_array_delete) { Google::Cloud::Firestore::FieldValue.array_delete 7, 8, 9 } - - it "ARRAY_DELETE alone" do - data = { a: field_array_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_DELETE with data" do - data = { a: 1, b: field_array_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_DELETE with dotted field" do - data = { "a.b.c" => field_array_delete } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple ARRAY_DELETE fields" do - data = { a: 1, b: field_array_delete, c: { d: field_array_delete } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested ARRAY_DELETE field" do - data = { a: 1, b: { c: field_array_delete } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - remove_all_from_array: Google::Cloud::Firestore::V1::ArrayValue.new( - values: [ - Google::Cloud::Firestore::V1::Value.new(integer_value: 7), - Google::Cloud::Firestore::V1::Value.new(integer_value: 8), - Google::Cloud::Firestore::V1::Value.new(integer_value: 9) - ] - ) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "ARRAY_DELETE cannot be anywhere inside an array value" do - data = { a: [1, { b: field_array_delete }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_delete under arrays" - end - - it "ARRAY_DELETE cannot be in an array value" do - data = { a: [1, 2, field_array_delete] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest array_delete under arrays" - end - end - - describe :field_increment do - let(:field_increment) { Google::Cloud::Firestore::FieldValue.increment 1 } - - it "INCREMENT alone" do - data = { a: field_increment } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "INCREMENT with data" do - data = { a: 1, b: field_increment } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "INCREMENT with dotted field" do - data = { "a.b.c" => field_increment } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple INCREMENT fields" do - data = { a: 1, b: field_increment, c: { d: field_increment } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested INCREMENT field" do - data = { a: 1, b: { c: field_increment } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - increment: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "INCREMENT cannot be anywhere inside an array value" do - data = { a: [1, { b: field_increment }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest increment under arrays" - end - - it "INCREMENT cannot be in an array value" do - data = { a: [1, 2, field_increment] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest increment under arrays" - end - end - - describe :field_maximum do - let(:field_maximum) { Google::Cloud::Firestore::FieldValue.maximum 1 } - - it "MAXIMUM alone" do - data = { a: field_maximum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MAXIMUM with data" do - data = { a: 1, b: field_maximum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MAXIMUM with dotted field" do - data = { "a.b.c" => field_maximum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple MAXIMUM fields" do - data = { a: 1, b: field_maximum, c: { d: field_maximum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested MAXIMUM field" do - data = { a: 1, b: { c: field_maximum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - maximum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MAXIMUM cannot be anywhere inside an array value" do - data = { a: [1, { b: field_maximum }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest maximum under arrays" - end - - it "MAXIMUM cannot be in an array value" do - data = { a: [1, 2, field_maximum] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest maximum under arrays" - end - end - - describe :field_minimum do - let(:field_minimum) { Google::Cloud::Firestore::FieldValue.minimum 1 } - - it "MINIMUM alone" do - data = { a: field_minimum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MINIMUM with data" do - data = { a: 1, b: field_minimum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MINIMUM with dotted field" do - data = { "a.b.c" => field_minimum } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "a.b.c", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "multiple MINIMUM fields" do - data = { a: 1, b: field_minimum, c: { d: field_minimum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "c"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ), - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "c.d", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "nested MINIMUM field" do - data = { a: 1, b: { c: field_minimum } } - - expected_writes = [ - Google::Cloud::Firestore::V1::Write.new( - update: Google::Cloud::Firestore::V1::Document.new( - name: "projects/projectID/databases/(default)/documents/C/d", - fields: { - "a" => Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - } - ), - update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(field_paths: ["a", "b"]), - current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true) - ), - Google::Cloud::Firestore::V1::Write.new( - transform: Google::Cloud::Firestore::V1::DocumentTransform.new( - document: "projects/projectID/databases/(default)/documents/C/d", - field_transforms: [ - Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new( - field_path: "b.c", - minimum: Google::Cloud::Firestore::V1::Value.new(integer_value: 1) - ) - ] - ) - ) - ] - - actual_writes = Google::Cloud::Firestore::Convert.writes_for_update document_path, data - - _(actual_writes).must_equal expected_writes - end - - it "MINIMUM cannot be anywhere inside an array value" do - data = { a: [1, { b: field_minimum }] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest minimum under arrays" - end - - it "MINIMUM cannot be in an array value" do - data = { a: [1, 2, field_minimum] } - - error = expect do - Google::Cloud::Firestore::Convert.writes_for_update document_path, data - end.must_raise ArgumentError - _(error.message).must_equal "cannot nest minimum under arrays" - end - end -end