أثناء قيامك بإنشاء تطبيقك ، قد ترغب في تأمين الوصول إلى قاعدة بيانات Cloud Firestore. ومع ذلك ، قبل بدء التشغيل ، ستحتاج إلى المزيد من قواعد أمان Cloud Firestore الأكثر دقة. باستخدام محاكي Cloud Firestore ، بالإضافة إلى النماذج الأولية واختبار الميزات والسلوك العام لتطبيقك ، يمكنك كتابة اختبارات وحدة تتحقق من سلوك قواعد أمان Cloud Firestore.
بداية سريعة
بالنسبة لعدد قليل من حالات الاختبار الأساسية ذات القواعد البسيطة ، جرب عينة البدء السريع .
فهم قواعد أمان Cloud Firestore
نفِّذ مصادقة Firebase وقواعد أمان Cloud Firestore للمصادقة بدون خادم والتفويض والتحقق من صحة البيانات عند استخدام مكتبات عميل الويب والجوال.
تتضمن قواعد أمان Cloud Firestore قطعتين:
- بيان
match
يحدد المستندات في قاعدة البيانات الخاصة بك. - تعبير
allow
بالتحكم في الوصول إلى تلك المستندات.
تتحقق مصادقة Firebase من بيانات اعتماد المستخدمين وتوفر الأساس لأنظمة الوصول المستندة إلى المستخدم والمستندة إلى الأدوار.
يتم تقييم كل طلب قاعدة بيانات من مكتبة Cloud Firestore للهاتف المحمول / الويب وفقًا لقواعد الأمان الخاصة بك قبل قراءة أو كتابة أي بيانات. إذا كانت القواعد تمنع الوصول إلى أي من مسارات المستند المحددة ، يفشل الطلب بأكمله.
تعرف على المزيد حول قواعد أمان Cloud Firestore في بدء استخدام قواعد أمان Cloud Firestore .
قم بتثبيت المحاكي
لتثبيت محاكي Cloud Firestore ، استخدم Firebase CLI وقم بتشغيل الأمر أدناه:
firebase setup:emulators:firestore
قم بتشغيل المحاكي
ابدأ بتهيئة مشروع Firebase في دليل العمل الخاص بك. هذه خطوة أولى شائعة عند استخدام Firebase CLI .
firebase init
ابدأ المحاكي باستخدام الأمر التالي. سيتم تشغيل المحاكي حتى تقتل العملية:
firebase emulators:start --only firestore
في كثير من الحالات ، تريد بدء تشغيل المحاكي ، وتشغيل مجموعة اختبار ، ثم إيقاف تشغيل المحاكي بعد تشغيل الاختبارات. يمكنك القيام بذلك بسهولة باستخدام emulators:exec
:
firebase emulators:exec --only firestore "./my-test-script.sh"
عند بدء تشغيل المحاكي سيحاول التشغيل على المنفذ الافتراضي (8080). يمكنك تغيير منفذ المحاكي عن طريق تعديل قسم "emulators"
في ملف firebase.json
الخاص بك:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
قبل تشغيل المحاكي
قبل البدء في استخدام المحاكي ، ضع في اعتبارك ما يلي:
- سيقوم المحاكي في البداية بتحميل القواعد المحددة في حقل
firestore.rules
لملفfirebase.json
الخاص بك. تتوقع اسم ملف محلي يحتوي على قواعد أمان Cloud Firestore وتطبق هذه القواعد على جميع المشاريع. إذا لم تقدم مسار الملف المحلي أو تستخدم طريقةloadFirestoreRules
كما هو موضح أدناه ، فإن المحاكي يعامل جميع المشاريع على أنها ذات قواعد مفتوحة. - بينما تعمل معظم حزم Firebase SDK مع المحاكيات مباشرةً ، تدعم مكتبة
@firebase/rules-unit-testing
فقطauth
السخرية في قواعد الأمان ، مما يجعل اختبارات الوحدة أسهل بكثير. بالإضافة إلى ذلك ، تدعم المكتبة بعض الميزات الخاصة بالمحاكي مثل مسح جميع البيانات ، كما هو موضح أدناه. - ستقبل المحاكيات أيضًا رموز Firebase Auth المميزة للإنتاج المقدمة من خلال Client SDKs وتقييم القواعد وفقًا لذلك ، مما يسمح بربط تطبيقك مباشرةً بالمحاكيات في التكامل والاختبارات اليدوية.
قم بإجراء اختبارات الوحدة المحلية
قم بتشغيل اختبارات الوحدة المحلية باستخدام الإصدار 9 من JavaScript SDK
يوزع Firebase مكتبة اختبار وحدة قواعد الأمان مع الإصدار 9 من JavaScript SDK والإصدار 8 SDK. تختلف واجهات برمجة التطبيقات الخاصة بالمكتبة اختلافًا كبيرًا. نوصي بمكتبة اختبار الإصدار 9 ، وهي أكثر انسيابية وتتطلب إعدادًا أقل للاتصال بالمحاكيات وبالتالي تجنب الاستخدام العرضي لموارد الإنتاج بأمان. للتوافق مع الإصدارات السابقة ، نواصل إتاحة مكتبة اختبار الإصدار 8 .
- طرق الاختبار الشائعة ووظائف الأداة المساعدة في الإصدار 9 SDK
- طرق الاختبار الخاصة بالمحاكي في الإصدار 9 SDK
استخدم وحدة @firebase/rules-unit-testing
للتفاعل مع المحاكي الذي يعمل محليًا. إذا حصلت على أخطاء مهلة أو أخطاء ECONNREFUSED
، فتحقق جيدًا من تشغيل المحاكي بالفعل.
نوصي بشدة باستخدام إصدار حديث من Node.js حتى تتمكن من استخدام تدوين async/await
. تتضمن جميع السلوكيات التي قد ترغب في اختبارها تقريبًا وظائف غير متزامنة ، وقد تم تصميم وحدة الاختبار للعمل مع التعليمات البرمجية المستندة إلى Promise.
مكتبة v9 Rules Unit Testing دائمًا على دراية بالمحاكيات ولا تلمس أبدًا موارد الإنتاج الخاصة بك.
يمكنك استيراد المكتبة باستخدام عبارات الاستيراد المعيارية v9. على سبيل المثال:
import {
assertFails,
assertSucceeds,
initializeTestEnvironment,
RulesTestEnvironment,
} from "@firebase/rules-unit-testing"
// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.
بمجرد الاستيراد ، يتضمن تنفيذ اختبارات الوحدة ما يلي:
- إنشاء وتكوين
RulesTestEnvironment
مع استدعاءinitializeTestEnvironment
. - إعداد بيانات الاختبار دون تشغيل القواعد ، باستخدام طريقة ملائمة تسمح لك بتجاوزها مؤقتًا ،
RulesTestEnvironment.withSecurityRulesDisabled
. - إعداد مجموعة الاختبار وكل اختبار قبل / بعد الخطافات مع استدعاءات لتنظيف بيانات الاختبار والبيئة ، مثل
RulesTestEnvironment.cleanup()
أوRulesTestEnvironment.clearFirestore()
. - تنفيذ حالات الاختبار التي تحاكي حالات المصادقة باستخدام
RulesTestEnvironment.authenticatedContext
وRulesTestEnvironment.unauthenticatedContext
.
الطرق الشائعة ووظائف المنفعة
راجع أيضًا طرق الاختبار الخاصة بالمحاكي في الإصدار 9 SDK .
initializeTestEnvironment() => RulesTestEnvironment
تعمل هذه الوظيفة على تهيئة بيئة اختبار لاختبار وحدة القواعد. اتصل بهذه الوظيفة أولاً لإعداد الاختبار. يتطلب التنفيذ الناجح تشغيل المحاكيات.
تقبل الوظيفة كائنًا اختياريًا يحدد TestEnvironmentConfig
، والذي يمكن أن يتكون من معرف المشروع وإعدادات تكوين المحاكي.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
تقوم هذه الطريقة بإنشاء RulesTestContext
، الذي يتصرف مثل مستخدم مصادقة مصدق عليه. الطلبات التي تم إنشاؤها عبر السياق الذي تم إرجاعه سيكون لها رمز مصادقة وهمي مرفق. اختياريًا ، قم بتمرير كائن يحدد المطالبات المخصصة أو يتجاوز حمولات رمز المصادقة.
استخدم كائن سياق الاختبار الذي تم إرجاعه في اختباراتك للوصول إلى أي مثيلات محاكي تم تكوينها ، بما في ذلك تلك التي تم تكوينها باستخدام initializeTestEnvironment
.
// Assuming a Firestore app and the Firestore emulator for this example import { setDoc } from "firebase/firestore"; const alice = testEnv.authenticatedContext("alice", { … }); // Use the Firestore instance associated with this context await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
تنشئ هذه الطريقة RulesTestContext
، والتي تتصرف مثل عميل لم يتم تسجيل دخوله عبر المصادقة. الطلبات التي تم إنشاؤها عبر السياق الذي تم إرجاعه لن يتم إرفاق رموز Firebase Auth المميزة.
استخدم كائن سياق الاختبار الذي تم إرجاعه في اختباراتك للوصول إلى أي مثيلات محاكي تم تكوينها ، بما في ذلك تلك التي تم تكوينها باستخدام initializeTestEnvironment
.
// Assuming a Cloud Storage app and the Storage emulator for this example import { getStorage, ref, deleteObject } from "firebase/storage"; const alice = testEnv.unauthenticatedContext(); // Use the Cloud Storage instance associated with this context const desertRef = ref(alice.storage(), 'images/desert.jpg'); await assertSucceeds(deleteObject(desertRef));
RulesTestEnvironment.withSecurityRulesDisabled()
قم بتشغيل وظيفة إعداد اختبار مع سياق يتصرف كما لو تم تعطيل قواعد الأمان.
تأخذ هذه الطريقة وظيفة رد الاتصال ، والتي تأخذ سياق تجاوز قواعد الأمان وتعيد وعدًا. سيتم تدمير السياق بمجرد أن يحل الوعد / يرفض.
RulesTestEnvironment.cleanup()
تعمل هذه الطريقة على تدمير جميع RulesTestContexts
التي تم إنشاؤها في بيئة الاختبار وتنظيف الموارد الأساسية ، مما يسمح بخروج نظيف.
هذه الطريقة لا تغير حالة المحاكيات بأي شكل من الأشكال. لإعادة تعيين البيانات بين الاختبارات ، استخدم طريقة البيانات الواضحة الخاصة بمحاكي التطبيق.
assertSucceeds(pr: Promise<any>)) => Promise<any>
هذه وظيفة مفيدة لحالة الاختبار.
تؤكد الوظيفة أنه سيتم حل الوعد المقدم الذي يغلف عملية المحاكي بدون انتهاكات لقواعد الأمان.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
هذه وظيفة مفيدة لحالة الاختبار.
تؤكد الوظيفة أن الوعد المقدم الذي يغلف عملية المحاكي سيتم رفضه بانتهاك قواعد الأمان.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
طرق خاصة بالمحاكي
راجع أيضًا طرق الاختبار الشائعة ووظائف الأداة في الإصدار 9 SDK .
RulesTestEnvironment.clearFirestore() => Promise<void>
تعمل هذه الطريقة على مسح البيانات الموجودة في قاعدة بيانات Firestore التي تنتمي إلى projectId
الذي تم تكوينه لمحاكي Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
تحصل هذه الطريقة على مثيل Firestore لسياق الاختبار هذا. يمكن استخدام مثيل Firebase JS Client SDK الذي تم إرجاعه مع واجهات برمجة تطبيقات SDK للعميل (الإصدار 9 المعياري أو الإصدار 9 المتوافق).
تصور تقييمات القواعد
يتيح لك محاكي Cloud Firestore تصور طلبات العميل في واجهة مستخدم Emulator Suite ، بما في ذلك تتبع التقييم لقواعد أمان Firebase.
افتح علامة التبويب Firestore> الطلبات لعرض تسلسل التقييم التفصيلي لكل طلب.
توليد تقارير الاختبار
بعد إجراء مجموعة من الاختبارات ، يمكنك الوصول إلى تقارير التغطية الاختبارية التي توضح كيفية تقييم كل قاعدة من قواعد الأمان الخاصة بك.
للحصول على التقارير ، استعلم عن نقطة نهاية مكشوفة على المحاكي أثناء تشغيله. للحصول على إصدار متوافق مع المتصفح ، استخدم عنوان URL التالي:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
يؤدي هذا إلى تقسيم القواعد إلى تعبيرات وتعبيرات فرعية يمكنك تمرير الماوس فوقها للحصول على مزيد من المعلومات ، بما في ذلك عدد التقييمات والقيم التي تم إرجاعها. للحصول على نسخة JSON الأولية من هذه البيانات ، قم بتضمين عنوان URL التالي في استعلامك:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
الفروق بين المحاكي والإنتاج
- لا يتعين عليك إنشاء مشروع Cloud Firestore بشكل صريح. يقوم المحاكي تلقائيًا بإنشاء أي مثيل يتم الوصول إليه.
- لا يعمل محاكي Cloud Firestore مع تدفق مصادقة Firebase العادي. بدلاً من ذلك ، في Firebase Test SDK ، قدمنا طريقة
initializeTestApp()
في مكتبةrules-unit-testing
، والتي تأخذ حقلauth
. سيعمل مقبض Firebase الذي تم إنشاؤه باستخدام هذه الطريقة كما لو أنه قد تمت مصادقته بنجاح ككيان تقدمه. إذا مررت قيمةnull
، فسوف تتصرف كمستخدم غير مصدق (auth != null
، على سبيل المثال).
استكشاف المشكلات المعروفة وإصلاحها
أثناء استخدامك لمحاكي Cloud Firestore ، قد تواجه المشكلات المعروفة التالية. اتبع الإرشادات أدناه لاستكشاف أي سلوك غير عادي تواجهه وإصلاحه. تمت كتابة هذه الملاحظات مع وضع مكتبة اختبار وحدة قواعد الأمان في الاعتبار ، ولكن الأساليب العامة قابلة للتطبيق على أي Firebase SDK.
سلوك الاختبار غير متسق
إذا كانت اختباراتك تنجح أحيانًا وتفشل ، حتى بدون أي تغييرات على الاختبارات نفسها ، فقد تحتاج إلى التحقق من أنها متسلسلة بشكل صحيح. تكون معظم التفاعلات مع المحاكي غير متزامنة ، لذا تحقق جيدًا من أن جميع التعليمات البرمجية غير المتزامنة متسلسلة بشكل صحيح. يمكنك إصلاح التسلسل إما عن طريق تسلسل الوعود ، أو استخدام تدوين await
بحرية.
على وجه الخصوص ، راجع العمليات غير المتزامنة التالية:
- تحديد قواعد الأمان ، باستخدام ، على سبيل المثال ،
initializeTestEnvironment
. - قراءة وكتابة البيانات ، على سبيل المثال ،
db.collection("users").doc("alice").get()
. - التأكيدات التشغيلية ، بما في ذلك
assertSucceeds
والتأكيدassertFails
.
تجتاز الاختبارات فقط في المرة الأولى التي تقوم فيها بتحميل المحاكي
المحاكي مصطنع. يخزن جميع البيانات المكتوبة إليه في الذاكرة ، لذلك يتم فقد أي بيانات عند إيقاف تشغيل المحاكي. إذا كنت تجري اختبارات متعددة مقابل نفس معرف المشروع ، فيمكن لكل اختبار إنتاج بيانات قد تؤثر على الاختبارات اللاحقة. يمكنك استخدام أي من الطرق التالية لتجاوز هذا السلوك:
- استخدم معرّفات مشروع فريدة لكل اختبار. لاحظ أنه إذا اخترت القيام بذلك ، فستحتاج إلى استدعاء
initializeTestEnvironment
كجزء من كل اختبار ؛ يتم تحميل القواعد تلقائيًا لمعرف المشروع الافتراضي فقط. - أعد هيكلة اختباراتك بحيث لا تتفاعل مع البيانات المكتوبة مسبقًا (على سبيل المثال ، استخدم مجموعة مختلفة لكل اختبار).
- احذف جميع البيانات المكتوبة أثناء الاختبار.
إعداد الاختبار معقد للغاية
عند إعداد اختبارك ، قد ترغب في تعديل البيانات بطريقة لا تسمح بها قواعد أمان Cloud Firestore بالفعل. إذا كانت القواعد الخاصة بك تجعل إعداد الاختبار معقدًا ، فحاول استخدام RulesTestEnvironment.withSecurityRulesDisabled
في خطوات الإعداد ، لذلك لن تؤدي عمليات القراءة والكتابة إلى حدوث أخطاء PERMISSION_DENIED
.
بعد ذلك ، يمكن للاختبار إجراء العمليات كمستخدم مصدق عليه أو غير مصادق باستخدام RulesTestEnvironment.authenticatedContext
و unauthenticatedContext
على التوالي. يتيح لك ذلك التحقق من أن قواعد أمان Cloud Firestore الخاصة بك تسمح / ترفض الحالات المختلفة بشكل صحيح.