From f8b98e4179a687694af941310acb94cfdb82fff7 Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Wed, 22 Sep 2021 21:45:00 +0200 Subject: [PATCH] chore: upgrade firebase to latest version (compat mode) --- package-lock.json | 528 +++++++++++++----- package.json | 8 +- src/__test-utils__/firestore.ts | 2 +- src/collection/__tests__/add-document.test.ts | 62 +- src/collection/__tests__/constructor.test.ts | 25 +- .../__tests__/delete-documents.test.ts | 64 ++- src/collection/__tests__/fetch-mode.test.ts | 400 ++++++------- .../__tests__/get-documents.test.ts | 164 +++--- src/collection/__tests__/new-id.test.ts | 48 +- src/collection/__tests__/query.test.ts | 67 ++- .../__tests__/realtime-mode.test.ts | 282 +++++----- .../__tests__/update-documents.test.ts | 73 ++- src/collection/collection.ts | 2 +- src/document/__tests__/watch.test.ts | 51 +- src/document/document.ts | 2 +- src/stores/auth-store/auth-store.test.ts | 50 +- src/stores/auth-store/auth-store.ts | 2 +- src/stores/crud-store/crud-store.test.ts | 47 +- src/stores/crud-store/crud-store.ts | 2 +- utils/test-firestore/index.ts | 1 - utils/test-firestore/test-firestore.test.ts | 41 -- utils/test-firestore/test-firestore.ts | 83 --- 22 files changed, 1133 insertions(+), 871 deletions(-) delete mode 100644 utils/test-firestore/index.ts delete mode 100644 utils/test-firestore/test-firestore.test.ts delete mode 100644 utils/test-firestore/test-firestore.ts diff --git a/package-lock.json b/package-lock.json index fa5efef..e3dfd2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -381,48 +381,68 @@ } }, "@firebase/analytics": { - "version": "0.6.18", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.18.tgz", - "integrity": "sha512-FXNtYDxbs9ynPbzUVuG94BjFPOPpgJ7156660uvCBuKgoBCIVcNqKkJQQ7TH8384fqvGjbjdcgARY9jgAHbtog==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.7.0.tgz", + "integrity": "sha512-YEPyeW6CV8xbIvWaJMvfRdWUPKe/xchJ1bjV6GpLfkYRX+ZE1/YSNU14pX292M4bZ6Qg+bbu2DuWp8fEpa/YQg==", "dev": true, "requires": { - "@firebase/analytics-types": "0.6.0", "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", + "@firebase/installations": "0.5.0", "@firebase/logger": "0.2.6", "@firebase/util": "1.3.0", "tslib": "^2.1.0" } }, + "@firebase/analytics-compat": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.1.1.tgz", + "integrity": "sha512-pMTrA8cxMXFRv7bwZEXXz0NCepnyH2Jay/32RZ7xAufij2VJhF5S1BtfCO0wuri3FB94rlM8SmSEbwxxHcAtVg==", + "dev": true, + "requires": { + "@firebase/analytics": "0.7.0", + "@firebase/analytics-types": "0.7.0", + "@firebase/component": "0.5.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, "@firebase/analytics-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.6.0.tgz", - "integrity": "sha512-kbMawY0WRPyL/lbknBkme4CNLl+Gw+E9G4OpNeXAauqoQiNkBgpIvZYy7BRT4sNGhZbxdxXxXbruqUwDzLmvTw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.7.0.tgz", + "integrity": "sha512-DNE2Waiwy5+zZnCfintkDtBfaW6MjIG883474v6Z0K1XZIvl76cLND4iv0YUb48leyF+PJK1KO2XrgHb/KpmhQ==", "dev": true }, "@firebase/app": { - "version": "0.6.30", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.30.tgz", - "integrity": "sha512-uAYEDXyK0mmpZ8hWQj5TNd7WVvfsU8PgsqKpGljbFBG/HhsH8KbcykWAAA+c1PqL7dt/dbt0Reh1y9zEdYzMhg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.0.tgz", + "integrity": "sha512-l4Pd69re6JyjumQrl719dnY5JSKROSYda/0N2wzOhSzqg8DsZOIErr8+xj6QAE6BtNsoIEk7ma9WMS/2r02MhA==", "dev": true, "requires": { - "@firebase/app-types": "0.6.3", "@firebase/component": "0.5.6", "@firebase/logger": "0.2.6", "@firebase/util": "1.3.0", - "dom-storage": "2.1.0", - "tslib": "^2.1.0", - "xmlhttprequest": "1.8.0" + "tslib": "^2.1.0" } }, "@firebase/app-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.3.2.tgz", - "integrity": "sha512-YjpsnV1xVTO1B836IKijRcDeceLgHQNJ/DWa+Vky9UHkm1Mi4qosddX8LZzldaWRTWKX7BN1MbZOLY8r7M/MZQ==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.4.0.tgz", + "integrity": "sha512-KQ/k8cukzZbH/LC9Iu5/Dbhr7w6byu8bYjfCA38B6v8aISgASYfP/nirxRD+hSuDoxXtAnPGEuv+v0YU3D1R2w==", "dev": true, "requires": { - "@firebase/app-check-interop-types": "0.1.0", - "@firebase/app-check-types": "0.3.1", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "@firebase/app-check-compat": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.1.1.tgz", + "integrity": "sha512-XTV5Ns0Lpwn5GgXV5T0soOkoOGACaw9xiNvAXcISQYFBIse0k7fKo8V5J9VUS1ppzGpyTRCg0m9efz4CNrwPyQ==", + "dev": true, + "requires": { + "@firebase/app-check": "0.4.0", "@firebase/component": "0.5.6", "@firebase/logger": "0.2.6", "@firebase/util": "1.3.0", @@ -435,11 +455,18 @@ "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==", "dev": true }, - "@firebase/app-check-types": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.3.1.tgz", - "integrity": "sha512-KJ+BqJbdNsx4QT/JIT1yDj5p6D+QN97iJs3GuHnORrqL+DU3RWc9nSYQsrY6Tv9jVWcOkMENXAgDT484vzsm2w==", - "dev": true + "@firebase/app-compat": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.1.tgz", + "integrity": "sha512-AoUO7PnQlDPyMAvAE972kBhrwXRZRLGdHM8obyIeTzPNqIiEoULD4Rdq5TBB4UmV2HYAlYdrS+dk4nuWx67w6A==", + "dev": true, + "requires": { + "@firebase/app": "0.7.0", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } }, "@firebase/app-types": { "version": "0.6.3", @@ -448,12 +475,46 @@ "dev": true }, "@firebase/auth": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", - "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.17.2.tgz", + "integrity": "sha512-t1iHB5Eg7vAbyOEzMMarsyJNGiO2xP8Zag0hLRVXWVaWymXZnyVKp62sXqyonvz4eVT8+iGBjDySB9zKIb5Pqg==", "dev": true, "requires": { - "@firebase/auth-types": "0.10.3" + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "node-fetch": "2.6.1", + "selenium-webdriver": "4.0.0-beta.1", + "tslib": "^2.1.0" + } + }, + "@firebase/auth-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.1.2.tgz", + "integrity": "sha512-0eqWSV4XoyOltT4HVJUzh8hBFNO5f78ZGDplRQImQ97/6wR45x6Q/9R19KTWOd109+3Axw6Orfq2cSNY0opgEA==", + "dev": true, + "requires": { + "@firebase/auth": "0.17.2", + "@firebase/auth-types": "0.11.0", + "@firebase/component": "0.5.6", + "@firebase/util": "1.3.0", + "node-fetch": "2.6.1", + "selenium-webdriver": "^4.0.0-beta.2", + "tslib": "^2.1.0" + }, + "dependencies": { + "selenium-webdriver": { + "version": "4.0.0-rc-1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-rc-1.tgz", + "integrity": "sha512-bcrwFPRax8fifRP60p7xkWDGSJJoMkPAzufMlk5K2NyLPht/YZzR2WcIk1+3gR8VOCLlst1P2PI+MXACaFzpIw==", + "dev": true, + "requires": { + "jszip": "^3.6.0", + "rimraf": "^3.0.2", + "tmp": "^0.2.1", + "ws": ">=7.4.6" + } + } } }, "@firebase/auth-interop-types": { @@ -463,9 +524,9 @@ "dev": true }, "@firebase/auth-types": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", - "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.11.0.tgz", + "integrity": "sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==", "dev": true }, "@firebase/component": { @@ -479,38 +540,58 @@ } }, "@firebase/database": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.11.0.tgz", - "integrity": "sha512-b/kwvCubr6G9coPlo48PbieBDln7ViFBHOGeVt/bt82yuv5jYZBEYAac/mtOVSxpf14aMo/tAN+Edl6SWqXApw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.0.tgz", + "integrity": "sha512-/gl6z6fAxAAFAdDllzidzweGpuXJu0b9AusSLrdW4LpP6KCuxJbhonMJuSGpHLzAHzx6Q9uitbvqHqBb17sttQ==", "dev": true, "requires": { "@firebase/auth-interop-types": "0.1.6", "@firebase/component": "0.5.6", - "@firebase/database-types": "0.8.0", "@firebase/logger": "0.2.6", "@firebase/util": "1.3.0", "faye-websocket": "0.11.3", "tslib": "^2.1.0" } }, + "@firebase/database-compat": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.0.tgz", + "integrity": "sha512-jLN0JMYnYijg8f3QFtSuPGNuKAt3yYVRsHHlR8sADgx8MptByRRwVmMOk7QPc/DY7qscZIJow3hXFwvbeApFLA==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/database": "0.12.0", + "@firebase/database-types": "0.9.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, "@firebase/database-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.8.0.tgz", - "integrity": "sha512-7IdjAFRfPWyG3b4wcXyghb3Y1CLCSJFZIg1xl5GbTVMttSQFT4B5NYdhsfA34JwAsv5pMzPpjOaS3/K9XJ2KiA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.0.tgz", + "integrity": "sha512-x2TeTVnMZGPvT3y4Nayio4WprQA/zGwqMrPMQwSdF+PFnaFJAhA/eLgUB6cmWFzFYO9VvmuRkFzDzo6ezTo1Zw==", "dev": true, "requires": { - "@firebase/app-types": "0.6.3", + "@firebase/app-types": "0.7.0", "@firebase/util": "1.3.0" + }, + "dependencies": { + "@firebase/app-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz", + "integrity": "sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==", + "dev": true + } } }, "@firebase/firestore": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.4.0.tgz", - "integrity": "sha512-PQ6+lWNrvh74GvFTHT4gCutFipDmtu8D1tNNawKe+/SyL6XFgeuMYgZIpKQgkTSezVDogC7EGQTJBFnewF9pOg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.0.2.tgz", + "integrity": "sha512-AWh1pugDifwCXHaQalZHp+Hr/3o+cxYvlbgQrPB35bh1A3do4I1xim/8Pba7gtpTzlClDryd5pK/XbK0TC/2kg==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/firestore-types": "2.4.0", "@firebase/logger": "0.2.6", "@firebase/util": "1.3.0", "@firebase/webchannel-wrapper": "0.5.1", @@ -520,50 +601,71 @@ "tslib": "^2.1.0" } }, + "@firebase/firestore-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.1.2.tgz", + "integrity": "sha512-xtjj2qOBN0+S5KlXmWa5UozGmYJ1OAGBNT0qkCSvzQitHED5/B2fNwKnpy7Em+Zu3Yc3r/eM94OGx93USFXifg==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/firestore": "3.0.2", + "@firebase/firestore-types": "2.5.0", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, "@firebase/firestore-types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.4.0.tgz", - "integrity": "sha512-0dgwfuNP7EN6/OlK2HSNSQiQNGLGaRBH0gvgr1ngtKKJuJFuq0Z48RBMeJX9CGjV4TP9h2KaB+KrUKJ5kh1hMg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.0.tgz", + "integrity": "sha512-I6c2m1zUhZ5SH0cWPmINabDyH5w0PPFHk2UHsjBpKdZllzJZ2TwTkXbDtpHUZNmnc/zAa0WNMNMvcvbb/xJLKA==", "dev": true }, "@firebase/functions": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.15.tgz", - "integrity": "sha512-b7RpLwFXi0N+HgkfK8cmkarSOoBeSrc1jNdadkCacQt+vIePkKM3E9EJXF4roWSa8GwTruodpBsvH+lK9iCAKQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.7.1.tgz", + "integrity": "sha512-F6XZVVBpqupCX7/YXpdzyXKYCeLVmHO/jxAKbN9I4B+c8doDqVtGkO23DPzf4ppzR4FuXDiKEEU9ZZ85kqZ1QA==", "dev": true, "requires": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/auth-interop-types": "0.1.6", "@firebase/component": "0.5.6", - "@firebase/functions-types": "0.4.0", - "@firebase/messaging-types": "0.5.0", + "@firebase/messaging-interop-types": "0.1.0", + "@firebase/util": "1.3.0", "node-fetch": "2.6.1", "tslib": "^2.1.0" } }, + "@firebase/functions-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.1.2.tgz", + "integrity": "sha512-eisJazUrqOL/pAZJPqamYiaAyV3ch6GQMx8Sso792tvRr8SFsNCFbN9eVun0U0ubWAON5qdLoruoc6npXg6FIg==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/functions": "0.7.1", + "@firebase/functions-types": "0.5.0", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, "@firebase/functions-types": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", - "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.5.0.tgz", + "integrity": "sha512-qza0M5EwX+Ocrl1cYI14zoipUX4gI/Shwqv0C1nB864INAD42Dgv4v94BCyxGHBg2kzlWy8PNafdP7zPO8aJQA==", "dev": true }, "@firebase/installations": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", - "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.5.0.tgz", + "integrity": "sha512-wF1CKIx+SoiEbtNdutulxW4z80B5lGXW+8JdAtcKQwgKxF0VtlCaDFsd9AEB3aTtzIve5UkGak8hQOMvvOpydg==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/installations-types": "0.3.4", "@firebase/util": "1.3.0", "idb": "3.0.2", "tslib": "^2.1.0" } }, - "@firebase/installations-types": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", - "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", - "dev": true - }, "@firebase/logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", @@ -571,43 +673,68 @@ "dev": true }, "@firebase/messaging": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.8.0.tgz", - "integrity": "sha512-hkFHDyVe1kMcY9KEG+prjCbvS6MtLUgVFUbbQqq7JQfiv58E07YCzRUcMrJolbNi/1QHH6Jv16DxNWjJB9+/qA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.9.0.tgz", + "integrity": "sha512-NTUB+gVJsgL/f6wqwUlgadaNuLZvyk1IlTcRvR3391t8jDSWOT2efwzNqcI7Xv4nhzaiPhzAQ4ncH/m8kfUUXQ==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", - "@firebase/messaging-types": "0.5.0", + "@firebase/installations": "0.5.0", + "@firebase/messaging-interop-types": "0.1.0", "@firebase/util": "1.3.0", "idb": "3.0.2", "tslib": "^2.1.0" } }, - "@firebase/messaging-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", - "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "@firebase/messaging-compat": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.1.0.tgz", + "integrity": "sha512-58qQmKwOiXhxZwrRwwjQDbjlRx1uMVVuV/DNbDzqilDJDdoYXMdK6RBTF9Bs51qy/Z1BI2Q9B1JX01QYlgZpxQ==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/messaging": "0.9.0", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "@firebase/messaging-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.1.0.tgz", + "integrity": "sha512-DbvUl/rXAZpQeKBnwz0NYY5OCqr2nFA0Bj28Fmr3NXGqR4PAkfTOHuQlVtLO1Nudo3q0HxAYLa68ZDAcuv2uKQ==", "dev": true }, "@firebase/performance": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.18.tgz", - "integrity": "sha512-lvZW/TVDne2TyOpWbv++zjRn277HZpbjxbIPfwtnmKjVY1gJ+H77Qi1c2avVIc9hg80uGX/5tNf4pOApNDJLVg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.5.0.tgz", + "integrity": "sha512-E+L18eJKshr/ijnWZMexEEddwkp2T4Ye2dJSK4TcOKRYfrmfZJ95RRZ+MPNp1ES7RH2JYiyym1NIQKPcNNvhug==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.5.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "@firebase/performance-compat": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.1.0.tgz", + "integrity": "sha512-H+/A5+y/15hFn5FHRP8lcogDzO6qm9YoACNEXn71UN4PiGQ+/BbHkQafDEXxD6wLfqfqR8u8oclHPFIYxMBF7Q==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", "@firebase/logger": "0.2.6", - "@firebase/performance-types": "0.0.13", + "@firebase/performance": "0.5.0", + "@firebase/performance-types": "0.1.0", "@firebase/util": "1.3.0", "tslib": "^2.1.0" } }, "@firebase/performance-types": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", - "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.1.0.tgz", + "integrity": "sha512-6p1HxrH0mpx+622Ql6fcxFxfkYSBpE3LSuwM7iTtYU2nw91Hj6THC8Bc8z4nboIq7WvgsT/kOTYVVZzCSlXl8w==", "dev": true }, "@firebase/polyfill": { @@ -622,55 +749,76 @@ } }, "@firebase/remote-config": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.43.tgz", - "integrity": "sha512-laNM4MN0CfeSp7XCVNjYOC4DdV6mj0l2rzUh42x4v2wLTweCoJ/kc1i4oWMX9TI7Jw8Am5Wl71Awn1J2pVe5xA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.2.0.tgz", + "integrity": "sha512-hNZ+BqsTmfe8ogpeow95NSwQmKIeetKdPxKpyC6RZBeFUae782+2HrUx4/Quep6OZjOHQF6xZ5d3VOxu2ZKEfg==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.5.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "@firebase/remote-config-compat": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.1.0.tgz", + "integrity": "sha512-PpCh5f5hUUaDCmiJsuu/u9a0g0G5WH3YSbfH1jPejVOaJ1lS82615E7WOzco4zMllLYfX62VaUYD2vvcLyXE/w==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", "@firebase/logger": "0.2.6", - "@firebase/remote-config-types": "0.1.9", + "@firebase/remote-config": "0.2.0", + "@firebase/remote-config-types": "0.2.0", "@firebase/util": "1.3.0", "tslib": "^2.1.0" } }, "@firebase/remote-config-types": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", - "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.2.0.tgz", + "integrity": "sha512-hqK5sCPeZvcHQ1D6VjJZdW6EexLTXNMJfPdTwbD8NrXUw6UjWC4KWhLK/TSlL0QPsQtcKRkaaoP+9QCgKfMFPw==", "dev": true }, "@firebase/rules-unit-testing": { - "version": "1.3.15", - "resolved": "https://registry.npmjs.org/@firebase/rules-unit-testing/-/rules-unit-testing-1.3.15.tgz", - "integrity": "sha512-OQOoME4FDkKbXduWYaKOYrV13tOWepH267vC4dhrLUBrQ0zOyvZuvmtM07F/aQSSuAmrdbBVSoM4BqcJiGzDeg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@firebase/rules-unit-testing/-/rules-unit-testing-2.0.0.tgz", + "integrity": "sha512-fvXXQy4iDV5978U2WFcAVqq2DaLq7myCg8rFX6NqKogfd80iynHsMYSZ0k8G7nP3FroEPxnGBUalDFKs/UYp5A==", "dev": true, "requires": { - "@firebase/component": "0.5.6", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", - "firebase": "8.10.0", - "request": "2.88.2" + "node-fetch": "2.6.1" } }, "@firebase/storage": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.7.0.tgz", - "integrity": "sha512-ebDFKJbM5HOxVtZV+RhVEBVtlWHK+Z5L3kA5uDBA2jMYcn+8NV/crozJnEE+iRsGEco6dLK5JS+Er4qtKLpH5A==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.8.2.tgz", + "integrity": "sha512-I9mVYhQ/DkWI1MKHhYvI4dnguXdXC50S5ryehOcR/JmSwyYjh1+T+IFQp0hHb1VWTixShzWoSGo1PhbrolFmIA==", "dev": true, "requires": { "@firebase/component": "0.5.6", - "@firebase/storage-types": "0.5.0", "@firebase/util": "1.3.0", "node-fetch": "2.6.1", "tslib": "^2.1.0" } }, + "@firebase/storage-compat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.1.2.tgz", + "integrity": "sha512-eff0e2qcDX188mqr7aKrqr4TIS25/cE6E7Xo9WRLe3c17nqGgmrYM4DDS3VDttNbf1j5XaoEnZVZafE9/BR3Rg==", + "dev": true, + "requires": { + "@firebase/component": "0.5.6", + "@firebase/storage": "0.8.2", + "@firebase/storage-types": "0.6.0", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, "@firebase/storage-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.5.0.tgz", - "integrity": "sha512-6Wv3Lu7s18hsgW7HG4BFwycTquZ3m/C8bjBoOsmPu0TD6M1GKwCzOC7qBdN7L6tRYPh8ipTj5+rPFrmhGfUVKA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.6.0.tgz", + "integrity": "sha512-1LpWhcCb1ftpkP/akhzjzeFxgVefs6eMD2QeKiJJUGH1qOiows2w5o0sKCUSQrvrRQS1lz3SFGvNR1Ck/gqxeA==", "dev": true }, "@firebase/util": { @@ -3625,12 +3773,6 @@ "integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==", "dev": true }, - "dom-storage": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", - "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==", - "dev": true - }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -4242,26 +4384,45 @@ } }, "firebase": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.10.0.tgz", - "integrity": "sha512-GCABTbJdo88QgzX5OH/vsfKBWvTRbLUylGlYXtO7uYo1VErfGd2BWW9ATlJP5Gxx+ClDfyvVTvcs2rcNWn3uUA==", - "dev": true, - "requires": { - "@firebase/analytics": "0.6.18", - "@firebase/app": "0.6.30", - "@firebase/app-check": "0.3.2", - "@firebase/app-types": "0.6.3", - "@firebase/auth": "0.16.8", - "@firebase/database": "0.11.0", - "@firebase/firestore": "2.4.0", - "@firebase/functions": "0.6.15", - "@firebase/installations": "0.4.32", - "@firebase/messaging": "0.8.0", - "@firebase/performance": "0.4.18", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-9.0.2.tgz", + "integrity": "sha512-+wdsD3Sk3fOgplzv4yzBmJ3Pdr01QiFF38Zq+8hzd+Dv6ZKMrgiq5CRljCaWenhZ/j8nuvHlq82u64ZARaXC+w==", + "dev": true, + "requires": { + "@firebase/analytics": "0.7.0", + "@firebase/analytics-compat": "0.1.1", + "@firebase/app": "0.7.0", + "@firebase/app-check": "0.4.0", + "@firebase/app-check-compat": "0.1.1", + "@firebase/app-compat": "0.1.1", + "@firebase/app-types": "0.7.0", + "@firebase/auth": "0.17.2", + "@firebase/auth-compat": "0.1.2", + "@firebase/database": "0.12.0", + "@firebase/database-compat": "0.1.0", + "@firebase/firestore": "3.0.2", + "@firebase/firestore-compat": "0.1.2", + "@firebase/functions": "0.7.1", + "@firebase/functions-compat": "0.1.2", + "@firebase/installations": "0.5.0", + "@firebase/messaging": "0.9.0", + "@firebase/messaging-compat": "0.1.0", + "@firebase/performance": "0.5.0", + "@firebase/performance-compat": "0.1.0", "@firebase/polyfill": "0.3.36", - "@firebase/remote-config": "0.1.43", - "@firebase/storage": "0.7.0", + "@firebase/remote-config": "0.2.0", + "@firebase/remote-config-compat": "0.1.0", + "@firebase/storage": "0.8.2", + "@firebase/storage-compat": "0.1.2", "@firebase/util": "1.3.0" + }, + "dependencies": { + "@firebase/app-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz", + "integrity": "sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==", + "dev": true + } } }, "firebase-admin": { @@ -4325,9 +4486,9 @@ } }, "@types/node": { - "version": "16.9.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.4.tgz", - "integrity": "sha512-KDazLNYAGIuJugdbULwFZULF9qQ13yNWEBFnfVpqlpgAAo6H/qnM9RjBgh0A0kmHf3XxAKLdN5mTIng9iUvVLA==", + "version": "16.9.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.6.tgz", + "integrity": "sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ==", "dev": true } } @@ -4853,6 +5014,12 @@ "integrity": "sha512-zfNREywMuf0NzDo9mVsL0yegjsirJxHpKHvWcyRozIqQy89g0a3U+oBPOCN4cc0oCiOuYgZHimzaW/R46G1Mpg==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "import-local": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", @@ -7897,6 +8064,44 @@ "verror": "1.10.0" } }, + "jszip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "jwa": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", @@ -8223,6 +8428,15 @@ "type-check": "~0.3.2" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -8849,6 +9063,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parse-asn1": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", @@ -9594,6 +9814,29 @@ "xmlchars": "^2.2.0" } }, + "selenium-webdriver": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-beta.1.tgz", + "integrity": "sha512-DJ10z6Yk+ZBaLrt1CLElytQ/FOayx29ANKDtmtyW1A6kCJx3+dsc5fFMOZxwzukDniyYsC3OObT5pUAsgkjpxQ==", + "dev": true, + "requires": { + "jszip": "^3.5.0", + "rimraf": "^2.7.1", + "tmp": "^0.2.1", + "ws": "^7.3.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -9606,6 +9849,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -10180,6 +10429,15 @@ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "dev": true }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -10831,12 +11089,6 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", - "dev": true - }, "xtend": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", diff --git a/package.json b/package.json index 2567200..4133287 100644 --- a/package.json +++ b/package.json @@ -42,19 +42,19 @@ "peerDependencies": { "mobx": ">= 6", "firebase": ">= 8", - "@firebase/rules-unit-testing": "^1.1.4", - "firebase-admin": "^9.2.0" + "@firebase/rules-unit-testing": "^2", + "firebase-admin": "^9" }, "dependencies": {}, "devDependencies": { - "@firebase/rules-unit-testing": "^1.1.4", + "@firebase/rules-unit-testing": "^2.0.0", "@rollup/plugin-commonjs": "^16.0.0", "@rollup/plugin-node-resolve": "^10.0.0", "@rollup/plugin-typescript": "^6.1.0", "@testing-library/dom": "^7.28.1", "@types/jest": "^24.0.23", "coveralls": "^3.1.0", - "firebase": "^8.10.0", + "firebase": "^9.0.2", "firebase-admin": "^9.11.1", "jest": "^26.6.3", "mobx": "^6.3.3", diff --git a/src/__test-utils__/firestore.ts b/src/__test-utils__/firestore.ts index e6a4376..a883775 100644 --- a/src/__test-utils__/firestore.ts +++ b/src/__test-utils__/firestore.ts @@ -1,4 +1,4 @@ -import type firebase from "firebase"; +import type firebase from "firebase/compat"; export const addAsync = ( collectionRef: firebase.firestore.CollectionReference, diff --git a/src/collection/__tests__/add-document.test.ts b/src/collection/__tests__/add-document.test.ts index f117013..cabc235 100644 --- a/src/collection/__tests__/add-document.test.ts +++ b/src/collection/__tests__/add-document.test.ts @@ -1,19 +1,8 @@ -import { firestore as firestoreNamespace } from "firebase-admin"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { ICollectionOptions, Collection } from "../.."; -import { initTestFirestore } from "../../../utils/test-firestore"; import { logger } from "../../__test-utils__"; -const firebase = require("firebase-admin"); - -const { - firestore, - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, -} = initTestFirestore( - "test-add-documents", - ["books"], -); +import firebase from "firebase/compat"; interface IBook { name: string; @@ -22,24 +11,39 @@ interface IBook { isDeleted?: boolean; } -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger - } - ); -} +describe("Collection.addAsync", () => { + let testEnv: RulesTestEnvironment; + let collection: Collection; + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; -let collection: Collection; + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger + } + ); + } -beforeEach(() => clearFirestoreData()); + beforeEach(() => testEnv.clearFirestore()); -afterAll(deleteFirebaseApp); + afterAll(() => testEnv.cleanup()); + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-add-documents", + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }); -describe("Collection.addAsync", () => { beforeEach(() => { collection = createCollection({ serialize: data => { @@ -69,7 +73,7 @@ describe("Collection.addAsync", () => { }) .then(id => { return collectionRef.doc(id).get() - .then((snapshot: firestoreNamespace.DocumentSnapshot) => { + .then(snapshot => { expect(snapshot.exists).toBe(true); }); }); @@ -88,7 +92,7 @@ describe("Collection.addAsync", () => { ) .then(() => { return collectionRef.doc("given-id").get() - .then((snapshot: firestoreNamespace.DocumentSnapshot) => { + .then(snapshot => { expect(snapshot.exists).toBe(true); }); }); diff --git a/src/collection/__tests__/constructor.test.ts b/src/collection/__tests__/constructor.test.ts index 95eefcb..850cefc 100644 --- a/src/collection/__tests__/constructor.test.ts +++ b/src/collection/__tests__/constructor.test.ts @@ -1,15 +1,26 @@ +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { Collection } from "../.."; -import { initTestFirestore } from "../../../utils/test-firestore"; +import type firebase from "firebase/compat"; -const { - firestore, -} = initTestFirestore( - "test-constructor-collection", - ["books"], -); +const projectId = "test-constructor-collection"; describe("Collection.constructor", () => { + let firestore: firebase.firestore.Firestore; + let testEnv: RulesTestEnvironment; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + }); + test("it should create a Collection instance with a string as collectionRef", () => { const collection = new Collection(firestore, "books"); diff --git a/src/collection/__tests__/delete-documents.test.ts b/src/collection/__tests__/delete-documents.test.ts index 7d5f91c..0667131 100644 --- a/src/collection/__tests__/delete-documents.test.ts +++ b/src/collection/__tests__/delete-documents.test.ts @@ -1,36 +1,44 @@ -import { firestore } from "firebase-admin"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { Collection, ICollectionOptions, RealtimeMode } from "../.."; -import { initTestFirestore } from "../../../utils/test-firestore"; import { logger } from "../../__test-utils__"; -const { - firestore: firestoreDb, - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, -} = initTestFirestore( - "test-delete-documents", - ["books"] -); +import type firebase from "firebase/compat"; -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestoreDb, - collectionRef, - options, - { - logger: logger - } - ); -} +const projectId = "test-delete-documents"; +describe("Collection.deleteAsync", () => { + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + let testEnv: RulesTestEnvironment; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); -beforeEach(() => clearFirestoreData()); + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }); -afterAll(deleteFirebaseApp); -describe("Collection.deleteAsync", () => { + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger: logger + } + ); + } + + afterAll(() => testEnv.cleanup()); - beforeEach(() => { + beforeEach(async () => { + await testEnv.clearFirestore() // Add initial data return Promise.all([ collectionRef.doc("id1").set({ total: 1, name: "A" }), @@ -41,19 +49,19 @@ describe("Collection.deleteAsync", () => { }); describe("when collection is not filtered with a query", () => { - test("it should delete the document with the given id", () => { + it("should delete the document with the given id", () => { const collection = createCollection({ realtimeMode: RealtimeMode.off }); return collection.deleteAsync("id2") .then(() => { return collectionRef.doc("id2").get() - .then((doc: firestore.DocumentSnapshot) => { + .then(doc => { expect(doc.exists).toBe(false); }); }); }); - test("it should delete multiple documents", () => { + it("should delete multiple documents", () => { const collection = createCollection(); return collection.deleteAsync("id2", "id3") diff --git a/src/collection/__tests__/fetch-mode.test.ts b/src/collection/__tests__/fetch-mode.test.ts index 04e6136..063284c 100644 --- a/src/collection/__tests__/fetch-mode.test.ts +++ b/src/collection/__tests__/fetch-mode.test.ts @@ -2,262 +2,274 @@ import { Collection, ICollectionOptions, FetchMode } from '../..'; import { autorun, when, reaction } from 'mobx'; import { logger, waitAsync, addItemInBatch } from "../../__test-utils__"; import { waitFor } from '@testing-library/dom'; -import { initTestFirestore } from '../../../utils/test-firestore'; - -const { - firestore, - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, -} = initTestFirestore( - "test-auto-fetch", - ["books"], -); - -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger - } - ); -} - -let collection: Collection<{ value: string }>; - -beforeEach(() => clearFirestoreData()); - -afterEach(() => collection.dispose()); - -afterAll(deleteFirebaseApp); - -describe("With fetch mode = auto:", () => { - beforeEach(() => { - collection = createCollection(); - - // Add initial data - return collectionRef.add({ value: "A" }); + +import type firebase from "firebase/compat"; +import { initializeTestEnvironment, RulesTestEnvironment } from '@firebase/rules-unit-testing'; + +describe("fetch mode", () => { + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + let testEnv: RulesTestEnvironment; + + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger + } + ); + } + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-auto-fetch", + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); }); - describe("when collection.docs becomes observed", () => { - test('it should fetch documents', () => { - // When no observers, the collection should not be fetched - expect(collection.isFetched).toBe(false); + beforeEach(() => testEnv.clearFirestore()); - // Add a dummy observer - reaction(() => collection.docs, () => { - // console.log(collection.docs.length); - }); + describe("With fetch mode = auto:", () => { + let collection: Collection<{ value: string }>; + afterEach(() => collection.dispose()); - // Collection should start loading the documents when it becomes observed - expect(collection.isLoading).toBe(true); + beforeEach(() => { + collection = createCollection(); - // When loading is finished, the documents must be present in the collection - return when(() => !collection.isLoading) - .then(() => { - expect(collection.docs.length).toBe(1); - }); + // Add initial data + return collectionRef.add({ value: "A" }); }); - }); - describe("when collection.docs becomes unobserved", () => { + describe("when collection.docs becomes observed", () => { + test('it should fetch documents', () => { + // When no observers, the collection should not be fetched + expect(collection.isFetched).toBe(false); + + // Add a dummy observer + reaction(() => collection.docs, () => { + // console.log(collection.docs.length); + }); - test('it should stop listening for document changes', () => { - // When no observers, the collection should not be fetched - expect(collection.isFetched).toBe(false); + // Collection should start loading the documents when it becomes observed + expect(collection.isLoading).toBe(true); - // Add a dummy observer - const stopAutorun = autorun(() => { - jest.fn()(collection.docs); + // When loading is finished, the documents must be present in the collection + return when(() => !collection.isLoading) + .then(() => { + expect(collection.docs.length).toBe(1); + }); }); + }); - // Collection should be listening for changes when it become observed - expect(collection.isActive).toBe(true); + describe("when collection.docs becomes unobserved", () => { - // Collection should start loading the documents when it becomes observed - expect(collection.isLoading).toBe(true); + test('it should stop listening for document changes', () => { + // When no observers, the collection should not be fetched + expect(collection.isFetched).toBe(false); - return when(() => !collection.isLoading) - .then(async () => { - // Remove the observer - stopAutorun(); + // Add a dummy observer + const stopAutorun = autorun(() => { + jest.fn()(collection.docs); + }); - // Collection should stop listening for changes - await waitFor(() => expect(collection.isActive).toBe(false)); + // Collection should be listening for changes when it become observed + expect(collection.isActive).toBe(true); - // Add a new document to the collection - await collectionRef.add({ value: "B" }); + // Collection should start loading the documents when it becomes observed + expect(collection.isLoading).toBe(true); - await waitAsync(50); + return when(() => !collection.isLoading) + .then(async () => { + // Remove the observer + stopAutorun(); - // The new document should not show up in the docs as we are not listening for changes - await waitFor( - () => expect(collection.docs.length).toBe(1), - ); - }); - }); - }); + // Collection should stop listening for changes + await waitFor(() => expect(collection.isActive).toBe(false)); + + // Add a new document to the collection + await collectionRef.add({ value: "B" }); - describe("when collection.isFetched becomes observed", () => { - test('it should fetch documents', () => { - // When no observers, the collection should not be fetched - expect(collection.isFetched).toBe(false); + await waitAsync(50); - // Add a dummy observer - reaction(() => collection.isFetched, () => { - // console.log(collection.docs.length); + // The new document should not show up in the docs as we are not listening for changes + await waitFor( + () => expect(collection.docs.length).toBe(1), + ); + }); }); + }); - // Collection should start loading the documents when it becomes observed - expect(collection.isLoading).toBe(true); + describe("when collection.isFetched becomes observed", () => { + test('it should fetch documents', () => { + // When no observers, the collection should not be fetched + expect(collection.isFetched).toBe(false); - // When loading is finished, the documents must be present in the collection - return when(() => !collection.isLoading) - .then(() => { - expect(collection.docs.length).toBe(1); + // Add a dummy observer + reaction(() => collection.isFetched, () => { + // console.log(collection.docs.length); }); + + // Collection should start loading the documents when it becomes observed + expect(collection.isLoading).toBe(true); + + // When loading is finished, the documents must be present in the collection + return when(() => !collection.isLoading) + .then(() => { + expect(collection.docs.length).toBe(1); + }); + }); }); - }); - describe("when collection.isFetched becomes unobserved", () => { + describe("when collection.isFetched becomes unobserved", () => { - test('it should stop listening for document changes', () => { - // When no observers, the collection should not be fetched - expect(collection.isFetched).toBe(false); + test('it should stop listening for document changes', () => { + // When no observers, the collection should not be fetched + expect(collection.isFetched).toBe(false); + + // Add a dummy observer + const stopAutorun = autorun(() => { + jest.fn()(collection.isFetched); + }); + + // Collection should be listening for changes when it become observed + expect(collection.isActive).toBe(true); + + // Collection should start loading the documents when it becomes observed + expect(collection.isLoading).toBe(true); + + return when(() => !collection.isLoading) + .then(() => { + // Remove the observer + stopAutorun(); + + return waitAsync(1000).then(() => { + // Collection should stop listening for changes + expect(collection.isActive).toBe(false); + + // Add a new document to the collection + return collectionRef.add({ value: "B" }) + .then(() => { + // The new document should not show up in the docs as we are not listening for changes + expect(collection.docs.length).toBe(1); + }); + }); + + }); + }); + }); - // Add a dummy observer - const stopAutorun = autorun(() => { - jest.fn()(collection.isFetched); + describe("when query of collection changes", () => { + beforeEach(() => { + // Add extra document to initial data + const batch = firestore.batch(); + addItemInBatch(batch, { value: "B" }, collectionRef); + return batch.commit(); }); - // Collection should be listening for changes when it become observed - expect(collection.isActive).toBe(true); + describe("when the collection has active listeners", () => { + test("it should fetch filtered documents", () => { + autorun(() => { + jest.fn()(collection.docs); + }); - // Collection should start loading the documents when it becomes observed - expect(collection.isLoading).toBe(true); + return when(() => collection.isFetched).then(() => { + // Verify initial state + expect(collection.docs.length).toBe(2); - return when(() => !collection.isLoading) - .then(() => { - // Remove the observer - stopAutorun(); + collection.query = ref => ref.where("value", "==", "B"); - return waitAsync(1000).then(() => { - // Collection should stop listening for changes - expect(collection.isActive).toBe(false); + expect(collection.isFetched).toBe(false); - // Add a new document to the collection - return collectionRef.add({ value: "B" }) + return when(() => collection.isFetched) .then(() => { - // The new document should not show up in the docs as we are not listening for changes expect(collection.docs.length).toBe(1); + expect(collection.docs[0].data!.value).toBe("B") }); }); }); - }); - }); - - describe("when query of collection changes", () => { - beforeEach(() => { - // Add extra document to initial data - const batch = firestore.batch(); - addItemInBatch(batch, { value: "B" }, collectionRef); - return batch.commit(); - }); - - describe("when the collection has active listeners", () => { - test("it should fetch filtered documents", () => { - autorun(() => { - jest.fn()(collection.docs); - }); - - return when(() => collection.isFetched).then(() => { - // Verify initial state - expect(collection.docs.length).toBe(2); + }); + describe("when the collection has no active listeners", () => { + test("it should not fetch documents", () => { + const collection = createCollection(); collection.query = ref => ref.where("value", "==", "B"); expect(collection.isFetched).toBe(false); - - return when(() => collection.isFetched) - .then(() => { - expect(collection.docs.length).toBe(1); - expect(collection.docs[0].data!.value).toBe("B") - }); + expect(collection.isLoading).toBe(false); }); - }); }); - describe("when the collection has no active listeners", () => { - test("it should not fetch documents", () => { - const collection = createCollection(); - collection.query = ref => ref.where("value", "==", "B"); - - expect(collection.isFetched).toBe(false); - expect(collection.isLoading).toBe(false); + describe("when calling fetchAsync on the collection", () => { + test("it should reject", () => { + expect(collection.fetchAsync()).rejects.toBeDefined(); }); }); }); - describe("when calling fetchAsync on the collection", () => { - test("it should reject", () => { - expect(collection.fetchAsync()).rejects.toBeDefined(); - }); - }); -}); + describe("With fetch mode = manual:", () => { + let collection: Collection<{ value: string }>; + beforeEach(() => { + collection = createCollection({ + fetchMode: FetchMode.manual + }); -describe("With fetch mode = manual:", () => { - beforeEach(() => { - collection = createCollection({ - fetchMode: FetchMode.manual + // Add initial data + const batch = firestore.batch(); + addItemInBatch(batch, { value: "A" }, collectionRef); + return batch.commit(); }); - // Add initial data - const batch = firestore.batch(); - addItemInBatch(batch, { value: "A" }, collectionRef); - return batch.commit(); - }); + describe("when collection becomes observed", () => { + test('it should not fetch documents', () => { + // When no observers, the collection should not be fetched + expect(collection.isFetched).toBe(false); - describe("when collection becomes observed", () => { - test('it should not fetch documents', () => { - // When no observers, the collection should not be fetched - expect(collection.isFetched).toBe(false); + // Add a dummy observer + autorun(() => { + jest.fn()(collection.docs.length); + }); - // Add a dummy observer - autorun(() => { - jest.fn()(collection.docs.length); + // Collection should not start loading the documents when it becomes observed + expect(collection.isLoading).toBe(false); + expect(collection.isFetched).toBe(false); }); - - // Collection should not start loading the documents when it becomes observed - expect(collection.isLoading).toBe(false); - expect(collection.isFetched).toBe(false); }); }); -}); -describe("With fetch mode = once:", () => { - beforeEach(() => { + describe("With fetch mode = once:", () => { - // Add initial data - return collectionRef.add( - { - value: "A", - } - ).then(() => { - collection = createCollection({ - fetchMode: FetchMode.once, - }); - }); - }); + describe("when collection is created", () => { + let collection: Collection<{ value: string }>; - describe("when collection is created", () => { - test('it should immediately fetch documents', () => { - return when(() => !collection.isLoading).then(() => { - expect(collection.isFetched).toBe(true); + test('it should immediately fetch documents', async () => { + // Add initial data + await collectionRef.add( + { + value: "A", + } + ).then(() => { + collection = createCollection({ + fetchMode: FetchMode.once, + }); + console.log({ + collection + }) + }); + expect(collection).toBeDefined(); + return when(() => !collection.isLoading).then(() => { + expect(collection.isFetched).toBe(true); + }); }); }); }); -}); +}); \ No newline at end of file diff --git a/src/collection/__tests__/get-documents.test.ts b/src/collection/__tests__/get-documents.test.ts index 76af030..fc49db2 100644 --- a/src/collection/__tests__/get-documents.test.ts +++ b/src/collection/__tests__/get-documents.test.ts @@ -1,104 +1,116 @@ import { Collection, ICollectionOptions, Doc } from "../.."; import { logger, IBook, addItemInBatch } from "../../__test-utils__"; -import { clearFirestoreData, initializeTestApp } from "@firebase/rules-unit-testing"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; +import type firebase from "firebase/compat"; const projectId = "test-get-documents"; -const app = initializeTestApp({ - projectId, -}); - -const firestore = app.firestore(); -const collectionRef = firestore.collection("books"); - -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger - } - ); -} - -beforeEach(() => clearFirestoreData({projectId})); -afterAll(() => app.delete()); +describe("get-documemts", () => { + let testEnv: RulesTestEnvironment; + let firestore: firebase.firestore.Firestore; + let collectionRef: firebase.firestore.CollectionReference; + + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger + } + ); + } + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); -describe("Collection.getAsync", () => { + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }) + beforeEach(() => testEnv.clearFirestore()); - beforeEach(() => { - // Add initial data - const batch = firestore.batch(); - addItemInBatch(batch, { total: 1, name: "A" }, collectionRef, "id1"); - addItemInBatch(batch, { total: 2, name: "B" }, collectionRef, "id2"); - addItemInBatch(batch, { total: 3, name: "C" }, collectionRef, "id3"); + afterAll(() => testEnv.cleanup()); - return batch.commit(); - }); + describe("Collection.getAsync", () => { + beforeEach(() => { + // Add initial data + const batch = firestore.batch(); + addItemInBatch(batch, { total: 1, name: "A" }, collectionRef, "id1"); + addItemInBatch(batch, { total: 2, name: "B" }, collectionRef, "id2"); + addItemInBatch(batch, { total: 3, name: "C" }, collectionRef, "id3"); - describe("when the requested document exists", () => { - test("it should get the document with the given id", () => { - const collection = createCollection(); + return batch.commit(); + }); - return collection.getAsync("id2") - .then(doc => { - expect(doc.id).toBe("id2"); - expect(doc.data).toBeDefined(); - expect(doc.data!).toMatchObject({ - name: "B" + describe("when the requested document exists", () => { + test("it should get the document with the given id", () => { + const collection = createCollection(); + + return collection.getAsync("id2") + .then(doc => { + expect(doc.id).toBe("id2"); + expect(doc.data).toBeDefined(); + expect(doc.data!).toMatchObject({ + name: "B" + }); }); - }); + }); }); - }); - describe("when the requested document does not exist", () => { - test("it should throw", () => { - const collection = createCollection(); + describe("when the requested document does not exist", () => { + test("it should throw", () => { + const collection = createCollection(); - return expect(collection.getAsync("id-0")).rejects.toBeDefined(); + return expect(collection.getAsync("id-0")).rejects.toBeDefined(); + }); }); }); -}); -describe("Collection.getManyAsync", () => { + describe("Collection.getManyAsync", () => { - beforeEach(() => { - // Add initial data - const batch = firestore.batch(); - addItemInBatch(batch, { total: 1, name: "A" }, collectionRef, "id1"); - addItemInBatch(batch, { total: 2, name: "B" }, collectionRef, "id2"); - addItemInBatch(batch, { total: 3, name: "C" }, collectionRef, "id3"); - addItemInBatch(batch, { total: 4, name: "D" }, collectionRef, "id4"); + beforeEach(() => { + // Add initial data + const batch = firestore.batch(); + addItemInBatch(batch, { total: 1, name: "A" }, collectionRef, "id1"); + addItemInBatch(batch, { total: 2, name: "B" }, collectionRef, "id2"); + addItemInBatch(batch, { total: 3, name: "C" }, collectionRef, "id3"); + addItemInBatch(batch, { total: 4, name: "D" }, collectionRef, "id4"); - return batch.commit(); - }); + return batch.commit(); + }); - describe("when the requested documents exist", () => { - test("it should get the documenst with the given ids", () => { - const collection = createCollection(); + describe("when the requested documents exist", () => { + test("it should get the documenst with the given ids", () => { + const collection = createCollection(); - return collection.getManyAsync(["id2", "id4"]) - .then(results => { - expect(results.length).toBe(2); + return collection.getManyAsync(["id2", "id4"]) + .then(results => { + expect(results.length).toBe(2); - const book1 = results[0] as Doc; - expect(book1.id).toBe("id2"); - expect(book1.data).toMatchObject({ total: 2, name: "B" }); - }); + const book1 = results[0] as Doc; + expect(book1.id).toBe("id2"); + expect(book1.data).toMatchObject({ total: 2, name: "B" }); + }); + }); }); - }); - describe("when some of the requested documents do not exist", () => { - test("it should get the documents with the given ids and the id of documents that were not found", () => { - const collection = createCollection(); + describe("when some of the requested documents do not exist", () => { + test("it should get the documents with the given ids and the id of documents that were not found", () => { + const collection = createCollection(); - return collection.getManyAsync(["id2", "id0", "id4"]) - .then(results => { - expect(results.length).toBe(3); + return collection.getManyAsync(["id2", "id0", "id4"]) + .then(results => { + expect(results.length).toBe(3); - expect(results[1]).toBe("id0"); - }); + expect(results[1]).toBe("id0"); + }); + }); }); }); -}); \ No newline at end of file +}); diff --git a/src/collection/__tests__/new-id.test.ts b/src/collection/__tests__/new-id.test.ts index bc4f8be..96024de 100644 --- a/src/collection/__tests__/new-id.test.ts +++ b/src/collection/__tests__/new-id.test.ts @@ -1,24 +1,40 @@ +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { Collection, ICollectionOptions } from "../.."; -import { initTestFirestore } from "../../../utils/test-firestore"; import { logger } from "../../__test-utils__"; -const { firestore, refs: [collectionRef] } = initTestFirestore( - "test-new-id", - ["books"], -); - -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger, - }, - ); -} +import type firebase from "firebase/compat"; describe("Collection.newId", () => { + + let testEnv: RulesTestEnvironment; + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-new-id", + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }); + + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger, + }, + ); + } + + it("should return a string", () => { const collection = createCollection(); expect(typeof collection.newId()).toBe("string"); diff --git a/src/collection/__tests__/query.test.ts b/src/collection/__tests__/query.test.ts index b309696..88433ac 100644 --- a/src/collection/__tests__/query.test.ts +++ b/src/collection/__tests__/query.test.ts @@ -1,45 +1,56 @@ import { Collection, ICollectionOptions } from "../.."; import { logger } from "../../__test-utils__"; import { when, autorun } from "mobx"; -import { initTestFirestore } from "../../../utils/test-firestore"; -const { - clearFirestoreData, - refs: [collectionRef], - firestore, - deleteFirebaseApp, -} = initTestFirestore( - "test-query", - ["books"], -); -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger: logger - } - ); -} +import type firebase from "firebase/compat" +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; +const projectId = "test-query"; -let collection: Collection<{ value: string }>; -beforeEach(() => clearFirestoreData()); - -afterEach(() => collection.dispose()); - -afterAll(deleteFirebaseApp); describe("Collection.query", () => { + let firestore: firebase.firestore.Firestore; + let testEnv: RulesTestEnvironment; + let collectionRef: firebase.firestore.CollectionReference; + let collection: Collection<{ value: string }>; + + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger: logger + } + ); + } + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); - beforeEach(() => { - collection = createCollection(); + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }); + + afterAll(() => testEnv.cleanup()); + + beforeEach(async () => { + await testEnv.clearFirestore() + collection = createCollection(); + return collection.addAsync({ value: "A" }); }); + afterEach(() => collection.dispose()); + test("it should clear the documents when set to null", () => { // Add a dummy observer to documents will get fetched autorun(() => { diff --git a/src/collection/__tests__/realtime-mode.test.ts b/src/collection/__tests__/realtime-mode.test.ts index 96be5f7..a7c17cb 100644 --- a/src/collection/__tests__/realtime-mode.test.ts +++ b/src/collection/__tests__/realtime-mode.test.ts @@ -1,64 +1,92 @@ +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { Collection, ICollectionOptions, FetchMode, RealtimeMode } from "../.."; -import { initTestFirestore } from "../../../utils/test-firestore"; import { logger, addItemInBatch } from "../../__test-utils__"; -let collection: Collection<{ value: string }>; -const { - firestore, - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, -} = initTestFirestore( - "test-realtime-mode", - ["books"], -); - -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger - } - ); -} - -beforeEach(() => clearFirestoreData()); - -afterAll(deleteFirebaseApp); - -describe("With realtime mode = on:", () => { - beforeEach(() => { - collection = createCollection({ fetchMode: FetchMode.manual }); - - // Add initial data - const batch = firestore.batch(); - addItemInBatch(batch, { value: "A" }, collectionRef, "id1"); - return batch.commit().then(() => collection.fetchAsync()); +import type firebase from "firebase/compat"; + +describe("realtime mode", () => { + let collection: Collection<{ value: string }>; + let testEnv: RulesTestEnvironment; + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-real-time-mode", + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); }); - afterEach(() => collection.dispose()); + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger + } + ); + } - describe("when documents are changed while watching the collection", () => { - test('it should update documents in local docs', () => { + beforeEach(() => testEnv.clearFirestore()); - return collectionRef.doc("id1").set({ - value: "B" - }).then(() => { - const doc = collection.get("id1"); - expect(doc).toBeDefined(); + afterAll(() => testEnv.cleanup()); + + + describe("With realtime mode = on:", () => { + + + beforeEach(() => { + collection = createCollection({ fetchMode: FetchMode.manual }); + + // Add initial data + const batch = firestore.batch(); + addItemInBatch(batch, { value: "A" }, collectionRef, "id1"); + return batch.commit().then(() => collection.fetchAsync()); + }); + + afterEach(() => collection.dispose()); + + describe("when documents are changed while watching the collection", () => { + test('it should update documents in local docs', () => { - expect(doc!.data!.value).toBe("B"); + return collectionRef.doc("id1").set({ + value: "B" + }).then(() => { + const doc = collection.get("id1"); + expect(doc).toBeDefined(); + + expect(doc!.data!.value).toBe("B"); + }); }); }); - }); - describe("when documents are deleted while watching the collection", () => { - describe("when the collection is not filtered", () => { - test('it should delete document in local docs', () => { - // Add one more document so we are not removing the last one (see next test) - return collectionRef.add({ value: "foo" }).then(() => { + describe("when documents are deleted while watching the collection", () => { + describe("when the collection is not filtered", () => { + test('it should delete document in local docs', () => { + // Add one more document so we are not removing the last one (see next test) + return collectionRef.add({ value: "foo" }).then(() => { + // Verify document to be deleted exists + const doc = collection.get("id1"); + expect(doc).toBeDefined(); + + return collectionRef.doc("id1").delete() + .then(() => { + // Verify if document has been deleted in local dictionary + const doc = collection.get("id1"); + expect(doc).toBeUndefined(); + }); + }); + }); + + /** When deleting last document of collection, an emtpy snapshot is received instead of a snapshot with type = deleted */ + test('it should delete document in local docs even if its the last one', () => { // Verify document to be deleted exists const doc = collection.get("id1"); expect(doc).toBeDefined(); @@ -72,36 +100,36 @@ describe("With realtime mode = on:", () => { }); }); - /** When deleting last document of collection, an emtpy snapshot is received instead of a snapshot with type = deleted */ - test('it should delete document in local docs even if its the last one', () => { - // Verify document to be deleted exists - const doc = collection.get("id1"); - expect(doc).toBeDefined(); + describe("when the collection is filtered", () => { + beforeEach(() => { + collection.dispose(); - return collectionRef.doc("id1").delete() - .then(() => { - // Verify if document has been deleted in local dictionary - const doc = collection.get("id1"); - expect(doc).toBeUndefined(); + collection = createCollection({ + fetchMode: FetchMode.manual, + query: ref => ref.where("value", "==", "A"), }); - }); - }); - describe("when the collection is filtered", () => { - beforeEach(() => { - collection.dispose(); - - collection = createCollection({ - fetchMode: FetchMode.manual, - query: ref => ref.where("value", "==", "A"), + return collection.fetchAsync(); }); - return collection.fetchAsync(); - }); + test('it should delete document in local docs', () => { + // Add one more document so we are not removing the last one (see next test) + return collectionRef.add({ value: "A" }).then(() => { + // Verify document to be deleted exists + const doc = collection.get("id1"); + expect(doc).toBeDefined(); + + return collectionRef.doc("id1").delete() + .then(() => { + // Verify if document has been deleted in local dictionary + const doc = collection.get("id1"); + expect(doc).toBeUndefined(); + }); + }); + }); - test('it should delete document in local docs', () => { - // Add one more document so we are not removing the last one (see next test) - return collectionRef.add({ value: "A" }).then(() => { + /** When deleting last document of collection, an emtpy snapshot is received instead of a snapshot with type = deleted */ + test('it should delete document in local docs even if its the last one', () => { // Verify document to be deleted exists const doc = collection.get("id1"); expect(doc).toBeDefined(); @@ -115,83 +143,69 @@ describe("With realtime mode = on:", () => { }); }); - /** When deleting last document of collection, an emtpy snapshot is received instead of a snapshot with type = deleted */ - test('it should delete document in local docs even if its the last one', () => { - // Verify document to be deleted exists - const doc = collection.get("id1"); - expect(doc).toBeDefined(); + }); - return collectionRef.doc("id1").delete() + describe("when documents are added while watching the collection", () => { + test('it should add documents in local docs', () => { + return collectionRef.doc("id3").set({ value: "C" }) .then(() => { - // Verify if document has been deleted in local dictionary - const doc = collection.get("id1"); - expect(doc).toBeUndefined(); + // Verify if document has been added to local dictionary + const doc = collection.get("id3"); + expect(doc).toBeDefined(); }); }); }); - }); - describe("when documents are added while watching the collection", () => { - test('it should add documents in local docs', () => { - return collectionRef.doc("id3").set({ value: "C" }) - .then(() => { - // Verify if document has been added to local dictionary - const doc = collection.get("id3"); - expect(doc).toBeDefined(); - }); + describe("With realtime mode = off:", () => { + beforeEach(() => { + collection = createCollection({ realtimeMode: RealtimeMode.off, fetchMode: FetchMode.manual }); + + // Add initial data + const batch = firestore.batch(); + addItemInBatch(batch, { value: "A" }, collectionRef, "id1"); + return batch.commit().then(() => collection.fetchAsync()); }); - }); -}); -describe("With realtime mode = off:", () => { - beforeEach(() => { - collection = createCollection({ realtimeMode: RealtimeMode.off, fetchMode: FetchMode.manual }); + afterEach(() => collection.dispose()); - // Add initial data - const batch = firestore.batch(); - addItemInBatch(batch, { value: "A" }, collectionRef, "id1"); - return batch.commit().then(() => collection.fetchAsync()); - }); + describe("when documents are changed while collection is not being watched", () => { + test('it should not update documents in local docs', () => { + return collectionRef.doc("id1").set({ + value: "B" + }).then(() => { + const doc = collection.get("id1"); + expect(doc).toBeDefined(); - afterEach(() => collection.dispose()); + expect(doc!.data!.value).toBe("A"); + }); + }); + }); - describe("when documents are changed while collection is not being watched", () => { - test('it should not update documents in local docs', () => { - return collectionRef.doc("id1").set({ - value: "B" - }).then(() => { + describe("when documents are deleted while collection is not being watched", () => { + test('it should not delete document in local docs', () => { + // Verify document to be deleted exists const doc = collection.get("id1"); expect(doc).toBeDefined(); - expect(doc!.data!.value).toBe("A"); + return collectionRef.doc("id1").delete() + .then(() => { + // Verify if document has not been deleted in local dictionary + const doc = collection.get("id1"); + expect(doc).toBeDefined(); + }); }); }); - }); - describe("when documents are deleted while collection is not being watched", () => { - test('it should not delete document in local docs', () => { - // Verify document to be deleted exists - const doc = collection.get("id1"); - expect(doc).toBeDefined(); - - return collectionRef.doc("id1").delete() - .then(() => { - // Verify if document has not been deleted in local dictionary - const doc = collection.get("id1"); - expect(doc).toBeDefined(); - }); - }); - }); - - describe("when documents are added while collection is not being watched", () => { - test('it should not add documents in local docs', () => { - return collectionRef.doc("id3").set({ value: "C" }) - .then(() => { - // Verify if document has been added to local dictionary - const doc = collection.get("id3"); - expect(doc).toBeUndefined(); - }); + describe("when documents are added while collection is not being watched", () => { + test('it should not add documents in local docs', () => { + return collectionRef.doc("id3").set({ value: "C" }) + .then(() => { + // Verify if document has been added to local dictionary + const doc = collection.get("id3"); + expect(doc).toBeUndefined(); + }); + }); }); }); -}); +}); \ No newline at end of file diff --git a/src/collection/__tests__/update-documents.test.ts b/src/collection/__tests__/update-documents.test.ts index 187f010..fbeec58 100644 --- a/src/collection/__tests__/update-documents.test.ts +++ b/src/collection/__tests__/update-documents.test.ts @@ -1,34 +1,41 @@ import { Collection, ICollectionOptions } from "../.."; import { logger, IBook, addItemInBatch } from "../../__test-utils__"; -import { initTestFirestore } from "../../../utils/test-firestore"; -import { firestore as firestoreNamespace } from "firebase-admin"; - -const { - firestore, - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, -} = initTestFirestore( - "test-update-documents", - ["books"], -); - -export function createCollection(options?: ICollectionOptions) { - return new Collection( - firestore, - collectionRef, - options, - { - logger - } - ); -} - -beforeEach(() => clearFirestoreData()); - -afterAll(deleteFirebaseApp); +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; + +import type firebase from "firebase/compat"; describe("Collection.updateAsync", () => { + let testEnv: RulesTestEnvironment; + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + + function createCollection(options?: ICollectionOptions) { + return new Collection( + firestore, + collectionRef, + options, + { + logger + } + ); + } + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-update-documents", + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("books"); + }); + + beforeEach(() => testEnv.clearFirestore()); + + afterAll(() => testEnv.cleanup()); describe("when the original documents exist in the collection", () => { let collection: Collection; @@ -60,7 +67,7 @@ describe("Collection.updateAsync", () => { return collection.updateAsync({ total: 10 }, "id2") .then(() => { return collectionRef.doc("id2").get() - .then((snapshot: firestoreNamespace.DocumentSnapshot) => { + .then(snapshot => { expect(snapshot.data()!.total).toBe(10); }) }); @@ -90,7 +97,7 @@ describe("Collection.updateAsync", () => { test("it should allow null value", () => { return collection.updateAsync(null, "id2") .then(() => collectionRef.doc("id2").get() - .then((snapshot: firestoreNamespace.DocumentSnapshot) => { + .then(snapshot => { expect(snapshot.data()!.isDeleted).toBe(true); expect(snapshot.data()!.name).toBe("B"); }) @@ -99,7 +106,11 @@ describe("Collection.updateAsync", () => { }); describe("when the original documents do not exist in the collection", () => { - const collection = createCollection(); + let collection: Collection; + + beforeEach(() => { + collection = createCollection(); + }); afterEach(() => collection.dispose()); @@ -117,7 +128,7 @@ describe("Collection.updateAsync", () => { return collection.updateAsync({ total: 10 }, id) .then(() => { return collectionRef.doc(id).get() - .then((snapshot: firestoreNamespace.DocumentSnapshot) => { + .then(snapshot => { // Verify the document still does not exist expect(snapshot.exists).toBe(false); }); diff --git a/src/collection/collection.ts b/src/collection/collection.ts index 654b989..ab26781 100644 --- a/src/collection/collection.ts +++ b/src/collection/collection.ts @@ -1,4 +1,4 @@ -import type firebase from "firebase"; +import type firebase from "firebase/compat"; import { addAsync, getAsync } from '../__test-utils__/firestore'; import { diff --git a/src/document/__tests__/watch.test.ts b/src/document/__tests__/watch.test.ts index f8ff8f7..fa93f94 100644 --- a/src/document/__tests__/watch.test.ts +++ b/src/document/__tests__/watch.test.ts @@ -1,9 +1,11 @@ -import { clearFirestoreData, initializeTestApp } from "@firebase/rules-unit-testing"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; import { waitFor } from "@testing-library/dom"; import { Doc } from "../.."; import { IBook, IBookData } from "../../__test-utils__"; +import type firebase from "firebase/compat"; + function deserializeBook(book: IBookData): IBook { const { award, ...otherProps } = book; const newValue = award === null || award === undefined @@ -15,13 +17,6 @@ function deserializeBook(book: IBookData): IBook { const projectId = "test-document-watch"; -const app = initializeTestApp({ - projectId, -}); - -const firestore = app.firestore(); - -const collectionRef = firestore.collection("books"); const dummyBook = { total: 5, @@ -29,19 +24,35 @@ const dummyBook = { award: null, }; -const createDoc = (watch: boolean, id?: string) => { - return new Doc(collectionRef, dummyBook, { - deserialize: deserializeBook, - watch, - }, id); -}; - -beforeEach(() => clearFirestoreData({ projectId })); - -afterAll(() => app.delete()); - describe("Document.watch", () => { - beforeEach(() => { + let testEnv: RulesTestEnvironment; + let firestore: firebase.firestore.Firestore; + let collectionRef: firebase.firestore.CollectionReference; + + const createDoc = (watch: boolean, id?: string) => { + return new Doc(collectionRef, dummyBook, { + deserialize: deserializeBook, + watch, + }, id); + }; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + + collectionRef = firestore.collection("books"); + }); + + afterAll(() => testEnv.cleanup()); + beforeEach(async () => { + await testEnv.clearFirestore(); return collectionRef.doc("id-A").set(dummyBook); }); diff --git a/src/document/document.ts b/src/document/document.ts index 7f4fd8b..ce91e79 100644 --- a/src/document/document.ts +++ b/src/document/document.ts @@ -1,4 +1,4 @@ -import type firebase from "firebase"; +import type firebase from "firebase/compat"; import { observable, computed, action, IObservableValue, makeObservable } from "mobx"; diff --git a/src/stores/auth-store/auth-store.test.ts b/src/stores/auth-store/auth-store.test.ts index bcfc6be..9611970 100644 --- a/src/stores/auth-store/auth-store.test.ts +++ b/src/stores/auth-store/auth-store.test.ts @@ -1,16 +1,12 @@ import { waitFor } from "@testing-library/dom"; import { AuthStore, AuthStoreUser } from "./auth-store"; -import type firebase from "firebase"; +import type firebase from "firebase/compat"; import { FetchMode } from "../../collection"; -import { clearFirestoreData, initializeTestApp } from "@firebase/rules-unit-testing"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; -const projectId = "auth-store-test"; -const app = initializeTestApp({ - projectId, -}); -const collectionRef = app.firestore().collection("users"); +const projectId = "auth-store-test"; class FakeAuth { public signOut() { @@ -28,10 +24,10 @@ class FakeAuth { } const onSignOut = jest.fn(); -const createAuthStore = (auth: any) => { +const createAuthStore = (auth: any, firestore: firebase.firestore.Firestore) => { return new AuthStore( { - firestore: app.firestore(), + firestore, auth: auth as unknown as firebase.auth.Auth, }, { @@ -44,17 +40,33 @@ const createAuthStore = (auth: any) => { } describe("AuthStore", () => { + let testEnv: RulesTestEnvironment; + let firestore: firebase.firestore.Firestore; + let collectionRef: any; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection("users"); + }); + afterEach(() => { jest.clearAllMocks(); - return clearFirestoreData({ projectId }); + return testEnv.clearFirestore(); }); - afterAll(() => app.delete()); + afterAll(() => testEnv.cleanup()); describe("when user authenticates for the first time", () => { it("should add a new user on first login", async () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); await waitFor(() => expect(() => authStore.isAuthInitialised).toBeTruthy()); @@ -86,7 +98,7 @@ describe("AuthStore", () => { it("should add a new user on first login: only uid", async () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); fakeAuth.authenticate({ uid: "id-1", @@ -125,7 +137,7 @@ describe("AuthStore", () => { it("should set the activeDocument with data for the user", async () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); await waitFor(() => expect(authStore.collection.isFetched).toBeTruthy()); @@ -151,7 +163,7 @@ describe("AuthStore", () => { const fakeAuth = new FakeAuth(); const authStore = new AuthStore( { - firestore: app.firestore(), + firestore: firestore, auth: fakeAuth as unknown as firebase.auth.Auth, }, undefined, @@ -194,7 +206,7 @@ describe("AuthStore", () => { const fakeAuth = new FakeAuth(); const authStore = new AuthStore( { - firestore: app.firestore(), + firestore: firestore, auth: fakeAuth as unknown as firebase.auth.Auth, }, undefined, @@ -210,7 +222,7 @@ describe("AuthStore", () => { it("should reset activeDocument and activeDocumentId", async () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); fakeAuth.authenticate({ uid: "id-1", @@ -227,7 +239,7 @@ describe("AuthStore", () => { describe("getLoggedInUser", () => { it("should resolve with user when authenticated", () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); const promise = authStore.getLoggedInUser(); @@ -242,7 +254,7 @@ describe("AuthStore", () => { it("should reject when user is not authenticated", () => { const fakeAuth = new FakeAuth(); - const authStore = createAuthStore(fakeAuth); + const authStore = createAuthStore(fakeAuth, firestore); const promise = authStore.getLoggedInUser(); diff --git a/src/stores/auth-store/auth-store.ts b/src/stores/auth-store/auth-store.ts index c5db016..112b5ef 100644 --- a/src/stores/auth-store/auth-store.ts +++ b/src/stores/auth-store/auth-store.ts @@ -1,4 +1,4 @@ -import type firebase from "firebase"; +import type firebase from "firebase/compat"; import { action, transaction, observable, makeObservable } from "mobx"; import { Collection } from "../../collection"; diff --git a/src/stores/crud-store/crud-store.test.ts b/src/stores/crud-store/crud-store.test.ts index 55dd193..d6be716 100644 --- a/src/stores/crud-store/crud-store.test.ts +++ b/src/stores/crud-store/crud-store.test.ts @@ -2,17 +2,13 @@ import { CrudStore, StoreOptions } from "./index"; import { waitFor } from "@testing-library/dom"; import { FetchMode } from "../../collection"; import { reaction } from "mobx"; -import { clearFirestoreData, initializeTestApp } from "@firebase/rules-unit-testing"; +import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing"; +import type firebase from "firebase/compat"; const collection = "books"; const projectId = "crud-store-test"; -const app = initializeTestApp({ - projectId, -}); - -const collectionRef = app.firestore().collection(collection); -const createCrudStore = async (options: Partial = {}, preFetch = true) => { +const createCrudStore = async (firestore: firebase.firestore.Firestore, options: Partial = {}, preFetch = true) => { const crud = new CrudStore({ collection, collectionOptions: { @@ -21,7 +17,7 @@ const createCrudStore = async (options: Partial = {}, preFetch = t ...options, }, { - firestore: app.firestore(), + firestore, }, ); @@ -32,17 +28,34 @@ const createCrudStore = async (options: Partial = {}, preFetch = t } describe("CrudStore", () => { + let testEnv: RulesTestEnvironment; + let collectionRef: firebase.firestore.CollectionReference; + let firestore: firebase.firestore.Firestore; + + beforeAll(async () => { + testEnv = await initializeTestEnvironment({ + projectId, + firestore: { + host: "localhost", + port: 8080, + } + }); + + firestore = testEnv.unauthenticatedContext().firestore(); + collectionRef = firestore.collection(collection); + }); + let crud: CrudStore; beforeEach(async () => { - crud = await createCrudStore(); + crud = await createCrudStore(testEnv.unauthenticatedContext().firestore()); }); afterEach(async () => { crud.dispose(); - await clearFirestoreData({ projectId }); + await testEnv.clearFirestore(); }); - afterAll(() => app.delete()); + afterAll(() => testEnv.cleanup()); describe("addDocument & deleteDocument", () => { it("should add/delete a document to/from the collection", async () => { @@ -176,8 +189,8 @@ describe("CrudStore", () => { it("should set the activeDocument with default values", async () => { await waitFor(() => expect(crud.activeDocumentId).toBeUndefined()); - crud = await createCrudStore({ - createNewDocumentDefaults: () => ({ bar: "default value" }), + crud = await createCrudStore(firestore, { + createNewDocumentDefaults: () => ( { bar: "default value" }), }); if (crud.activeDocumentId) { @@ -199,7 +212,7 @@ describe("CrudStore", () => { describe("activeDocument", () => { it("should return the data of the document when activeDocumentId is set", async () => { await collectionRef.doc("id-1").set({ foo: "bar" }); - const crud = await createCrudStore(); + const crud = await createCrudStore(firestore); await waitFor(() => expect(crud.collection.isFetched).toBeTruthy()); @@ -215,7 +228,7 @@ describe("CrudStore", () => { it("should eventually return the data of the document when activeDocumentId is set", async () => { await collectionRef.doc("id-1").set({ foo: "bar" }); - const crud = await createCrudStore(undefined, false); + const crud = await createCrudStore(firestore, undefined, false); expect(crud.collection.isFetched).toBeFalsy(); crud.setActiveDocumentId("id-1"); @@ -229,7 +242,7 @@ describe("CrudStore", () => { it("should watch the data of the document when it's changed in the database", async () => { await collectionRef.doc("id-1").set({foo:"bar"}); - const crud = await createCrudStore(); + const crud = await createCrudStore(firestore); await waitFor(() => expect(crud.collection.isFetched).toBeTruthy()); @@ -252,7 +265,7 @@ describe("CrudStore", () => { it("should be undefined when activeDocumentId is set to invalid document id", async () => { await collectionRef.doc("id-1").set({foo:"bar"}); - const crud = await createCrudStore(); + const crud = await createCrudStore(firestore); await waitFor(() => expect(crud.collection.isFetched).toBeTruthy()); diff --git a/src/stores/crud-store/crud-store.ts b/src/stores/crud-store/crud-store.ts index f70e532..e19e996 100644 --- a/src/stores/crud-store/crud-store.ts +++ b/src/stores/crud-store/crud-store.ts @@ -1,4 +1,4 @@ -import type firebase from "firebase"; +import type firebase from "firebase/compat"; import { observable, action, transaction, computed, reaction, makeObservable } from "mobx"; diff --git a/utils/test-firestore/index.ts b/utils/test-firestore/index.ts deleted file mode 100644 index 0343dec..0000000 --- a/utils/test-firestore/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./test-firestore"; diff --git a/utils/test-firestore/test-firestore.test.ts b/utils/test-firestore/test-firestore.test.ts deleted file mode 100644 index 9a73000..0000000 --- a/utils/test-firestore/test-firestore.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { initTestFirestore } from "../test-firestore"; -import path from "path"; - -describe("test-firestore: initTestFirestore", () => { - const { - refs: [collectionRef], - clearFirestoreData, - deleteFirebaseApp, - } = initTestFirestore( - "test-firestore", - ["books"], - ); - - afterEach(clearFirestoreData); - beforeAll(async () => { - await collectionRef.doc("book-1").set({ title: "Book 1" }); - }); - - afterAll(deleteFirebaseApp); - it("should load firestore security rules from specified path", async () => { - const { - refs: [collectionRef], - deleteFirebaseApp, - clearFirestoreData, - } = await initTestFirestore( - "test-firestore", - ["books"], - { - uid: "user-id-1", - email: "user1@team-timesheets.com", - }, - path.resolve(__dirname, "firestore.rules.test"), - ); - - await expect(collectionRef.doc("book-1").get()).rejects.toBeDefined(); - - await clearFirestoreData(); - - deleteFirebaseApp(); - }); -}); diff --git a/utils/test-firestore/test-firestore.ts b/utils/test-firestore/test-firestore.ts deleted file mode 100644 index c7d67d8..0000000 --- a/utils/test-firestore/test-firestore.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { - initializeAdminApp, - clearFirestoreData as clearFirestoreDataFn, - initializeTestApp, - loadFirestoreRules, -} from "@firebase/rules-unit-testing"; - -import fs from "fs"; - -import { app, firestore } from "firebase-admin"; - -type InitTestFirestoreResult = { - refs: firestore.CollectionReference[]; - clearFirestoreData(): Promise; - deleteFirebaseApp(): void; - app: app.App; - firestore: firestore.Firestore; -} - -type AuthUser = { uid: string, email: string }; - -const initAuthApp = async ( - projectId: string, - collectionNames: string[], - pathToRules: string, - authUser: AuthUser, -): Promise => { - await loadFirestoreRules({ - projectId, - rules: fs.readFileSync(pathToRules, "utf8") - }); - - const app = initializeTestApp({ - projectId, - auth: authUser, - }); - - const firestore = app.firestore(); - - return { - refs: collectionNames.map(collectionName => firestore.collection(collectionName)), - firestore, - app, - clearFirestoreData: () => clearFirestoreData(projectId), - deleteFirebaseApp: () => app.delete(), - } as any; // todo -} -export function initTestFirestore(projectId: string, collectionNames: string[]): any // InitTestFirestoreResult; -export function initTestFirestore( - projectId: string, - collectionNames: string[], - auth: { uid: string, email: string }, - pathToRules: string, -): Promise -export function initTestFirestore( - projectId: string, - collectionNames: string[], - auth?: { uid: string, email: string }, - pathToRules?: string, -): InitTestFirestoreResult | Promise { - - if (pathToRules && auth) { - return initAuthApp(projectId, collectionNames, pathToRules, auth); - } - - const app = initializeAdminApp({ - projectId, - }); - - const firestore = app.firestore(); - - return { - refs: collectionNames.map(collectionName => firestore.collection(collectionName)), - firestore, - app, - clearFirestoreData: () => clearFirestoreData(projectId), - deleteFirebaseApp: () => app.delete(), - }; -}; - -export const clearFirestoreData = (projectId: string) => { - return clearFirestoreDataFn({ projectId }); -};