### Install Firebase CLI Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Install the Firebase Command Line Interface if you don't have it. This is necessary for running the Firestore emulator. ```bash $ curl -sL https://firebase.tools | bash ``` ```bash $ which firebase ``` -------------------------------- ### Start iOS Simulator Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Use this command to open the iOS Simulator application. Driver tests require a simulator to run. ```bash $ open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app ``` -------------------------------- ### Start Firestore Emulator Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Run the Firestore emulator using the Firebase CLI. This command starts the emulator on the default port 8080. ```bash ~/Documents/fake_cloud_firestore $ firebase emulators:start --only firestore ``` -------------------------------- ### Initialize FakeFirebaseFirestore with Security Rules Source: https://github.com/atn832/fake_cloud_firestore/blob/master/README.md Pass security rules as a string to the FakeFirebaseFirestore constructor. This example shows how to restrict access to user-specific documents based on the authenticated user's UID. Ensure firebase_auth_mocks is used to manage authentication state. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:firebase_auth_mocks/firebase_auth_mocks.dart'; import 'package:test/test.dart'; // https://firebase.google.com/docs/rules/rules-and-auth#leverage_user_information_in_rules final authUidDescription = ''' service cloud.firestore { match /databases/{database}/documents { // Make sure the uid of the requesting user matches name of the user // document. The wildcard expression {userId} makes the userId variable // available in rules. match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; } } }'''; main() async { test('security rules' { final auth = MockFirebaseAuth(); final firestore = FakeFirebaseFirestore( // Pass security rules to restrict `/users/{user}` documents. securityRules: authUidDescription, // Make MockFirebaseAuth inform FakeFirebaseFirestore of sign-in // changes. authObject: auth.authForFakeFirestore); // The user signs-in. FakeFirebaseFirestore knows about it thanks to // `authObject`. await auth.signInWithCustomToken('some token'); final uid = auth.currentUser!.uid; // Now the user can access their user-specific document. expect( () => firestore.doc('users/$uid').set({'name': 'abc'}), returnsNormally); // But not anyone else's. expect(() => firestore.doc('users/abcdef').set({'name': 'abc'}), throwsException); }); } ``` -------------------------------- ### Mocking Exceptions Source: https://github.com/atn832/fake_cloud_firestore/blob/master/README.md Manually mock exceptions for methods like get, set, update, delete, and query.get to simulate network errors or other failure conditions. ```dart final instance = FakeFirebaseFirestore(); final doc = instance.collection('users').doc(uid); whenCalling(Invocation.method(#set, null)) .on(doc) .thenThrow(FirebaseException(plugin: 'firestore')); expect(() => doc.set({'name': 'Bob'}), throwsA(isA())); ``` -------------------------------- ### Access Documents with FakeFirebaseFirestore Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Get a DocumentReference using doc(). Supports setting (create/overwrite), getting snapshots, updating specific fields, merging data, and deleting documents. Nested field updates are supported. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); // Get document reference final userDoc = firestore.doc('users/user123'); // Set document data (creates or overwrites) await userDoc.set({ 'name': 'John', 'email': 'john@example.com', 'profile': {'bio': 'Developer', 'location': 'NYC'}, }); // Get document snapshot final snapshot = await userDoc.get(); print(snapshot.exists); // Output: true print(snapshot.get('name')); // Output: John print(snapshot.get('profile.bio')); // Output: Developer // Update specific fields (document must exist) await userDoc.update({ 'email': 'john.new@example.com', 'profile.location': 'LA', // Nested field update }); // Merge data (partial update without overwriting) await userDoc.set({'age': 30}, SetOptions(merge: true)); // Delete document await userDoc.delete(); final deleted = await userDoc.get(); print(deleted.exists); // Output: false } ``` -------------------------------- ### Type-Safe Data with Collection Converters Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Use `withConverter` to define custom serialization and deserialization logic for your data models. This ensures type safety when adding, getting, and querying documents. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; // Define a model class class User { final String name; final int age; final String? email; User({required this.name, required this.age, this.email}); factory User.fromFirestore(DocumentSnapshot> snapshot, SnapshotOptions? options) { final data = snapshot.data()!; return User( name: data['name'], age: data['age'], email: data['email'], ); } Map toFirestore() => { 'name': name, 'age': age, if (email != null) 'email': email, }; } void main() async { final firestore = FakeFirebaseFirestore(); // Create typed collection reference final usersCollection = firestore.collection('users').withConverter( fromFirestore: User.fromFirestore, toFirestore: (user, _) => user.toFirestore(), ); // Add typed document final docRef = await usersCollection.add(User(name: 'Alice', age: 30, email: 'alice@example.com')); // Get typed document final snapshot = await docRef.get(); final user = snapshot.data()!; print('${user.name}, ${user.age}'); // Output: Alice, 30 // Query with types final adults = await usersCollection.where('age', isGreaterThanOrEqualTo: 18).get(); for (var doc in adults.docs) { final u = doc.data(); print(u.name); // Output: Alice } // Typed document reference final typedDoc = firestore.doc('users/specific').withConverter( fromFirestore: User.fromFirestore, toFirestore: (user, _) => user.toFirestore(), ); await typedDoc.set(User(name: 'Bob', age: 25)); } ``` -------------------------------- ### Instantiate FakeFirebaseFirestore Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Instantiate FakeFirebaseFirestore for basic testing. Supports optional security rules, authentication state, and custom clock for server timestamps. Use dump() for debugging and clearPersistence() to reset. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; void main() async { // Basic instantiation final firestore = FakeFirebaseFirestore(); // With security rules and auth (for testing protected access) final securityRules = ''' service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; } } }'''; final firestoreWithRules = FakeFirebaseFirestore( securityRules: securityRules, authObject: authStream, // Stream?> from firebase_auth_mocks ); // Add and retrieve data await firestore.collection('users').add({'username': 'Bob', 'age': 25}); final snapshot = await firestore.collection('users').get(); print(snapshot.docs.length); // Output: 1 print(snapshot.docs.first.get('username')); // Output: Bob // Debug: dump database contents print(firestore.dump()); // Output: {"users": {"randomId": {"username": "Bob", "age": 25}}} // Clear database await firestore.clearPersistence(); } ``` -------------------------------- ### Run Flutter Drive Test Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Execute the main driver test for Firestore behavior comparison. This command runs tests against Cloud Firestore, Firestore Emulator, and fake_cloud_firestore. ```bash ~/Documents/fake_cloud_firestore $ flutter drive --target=test_driver/cloud_firestore_behaviors.dart ``` -------------------------------- ### Run Flutter Driver Tests Source: https://github.com/atn832/fake_cloud_firestore/blob/master/example/README.md Execute integration tests for the Flutter application using the Flutter driver. Ensure the driver script is correctly specified. ```sh flutter driver --driver=test_driver/cloud_firestore_test.dart ``` -------------------------------- ### Basic Firestore Operations Source: https://github.com/atn832/fake_cloud_firestore/blob/master/README.md Instantiate FakeFirebaseFirestore and perform basic collection and document operations. Use dump() to inspect the in-memory database state. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() { final instance = FakeFirebaseFirestore(); await instance.collection('users').add({ 'username': 'Bob', }); final snapshot = await instance.collection('users').get(); print(snapshot.docs.length); // 1 print(snapshot.docs.first.get('username')); // 'Bob' print(instance.dump()); } ``` -------------------------------- ### Run FieldValue Test for fake_cloud_firestore Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Execute the FieldValue behavior test specifically for the fake_cloud_firestore implementation. Set the FIRESTORE_IMPLEMENTATION environment variable. ```bash ~/Documents/fake_cloud_firestore $ FIRESTORE_IMPLEMENTATION=fake_cloud_firestore flutter drive --target=test_driver/field_value_behaviors.dart ``` -------------------------------- ### Listen to Document and Collection Snapshots Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Subscribe to real-time updates for documents or query results. The listener emits snapshots whenever data changes. Ensure to cancel the subscription when no longer needed. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); // Document snapshots stream final userDoc = firestore.doc('users/user1'); final subscription = userDoc.snapshots().listen((snapshot) { if (snapshot.exists) { print('User data: ${snapshot.data()}'); } else { print('User does not exist'); } }); // Trigger updates await userDoc.set({'name': 'Alice'}); // Output: User data: {name: Alice} await userDoc.update({'age': 25}); // Output: User data: {name: Alice, age: 25} await userDoc.delete(); // Output: User does not exist await subscription.cancel(); // Collection/query snapshots stream final postsCollection = firestore.collection('posts'); postsCollection.orderBy('createdAt', descending: true).snapshots().listen((querySnapshot) { print('Total posts: ${querySnapshot.docs.length}'); for (var doc in querySnapshot.docs) { print('- ${doc.get('title')}'); } }); await postsCollection.add({'title': 'First Post', 'createdAt': 1}); // Output: Total posts: 1, - First Post await postsCollection.add({'title': 'Second Post', 'createdAt': 2}); // Output: Total posts: 2, - Second Post, - First Post } ``` -------------------------------- ### Sort and paginate results with orderBy() and limit() Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Use `orderBy()` to sort documents by one or more fields and `limit()` or `limitToLast()` to control the number of results. Cursor-based pagination is supported with `startAfterDocument()`. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); final users = firestore.collection('users'); // Seed data await users.add({'name': 'Alice', 'age': 30, 'score': 85}); await users.add({'name': 'Bob', 'age': 25, 'score': 92}); await users.add({'name': 'Charlie', 'age': 35, 'score': 78}); await users.add({'name': 'Diana', 'age': 28, 'score': 92}); // Order by single field final byAge = await users.orderBy('age').get(); print(byAge.docs.map((d) => d.get('name')).toList()); // Output: [Bob, Diana, Alice, Charlie] // Order descending final byAgeDesc = await users.orderBy('age', descending: true).get(); print(byAgeDesc.docs.map((d) => d.get('name')).toList()); // Output: [Charlie, Alice, Diana, Bob] // Multiple order-by (secondary sort) final byScoreAndName = await users.orderBy('score', descending: true).orderBy('name').get(); print(byScoreAndName.docs.map((d) => d.get('name')).toList()); // Output: [Bob, Diana, Alice, Charlie] // Limit results final top2 = await users.orderBy('score', descending: true).limit(2).get(); print(top2.docs.map((d) => d.get('name')).toList()); // Output: [Bob, Diana] // Limit to last final bottom2 = await users.orderBy('score', descending: true).limitToLast(2).get(); print(bottom2.docs.map((d) => d.get('name')).toList()); // Output: [Alice, Charlie] // Cursor pagination final firstPage = await users.orderBy('age').limit(2).get(); final lastDoc = firstPage.docs.last; final secondPage = await users.orderBy('age').startAfterDocument(lastDoc).limit(2).get(); print(secondPage.docs.map((d) => d.get('name')).toList()); // Output: [Alice, Charlie] // Start at / end at with values final ageRange = await users.orderBy('age').startAt([28]).endAt([35]).get(); print(ageRange.docs.map((d) => d.get('name')).toList()); // Output: [Diana, Alice, Charlie] } ``` -------------------------------- ### Run FieldValue Test for Cloud Firestore Source: https://github.com/atn832/fake_cloud_firestore/blob/master/test_driver/README.md Execute the FieldValue behavior test for Cloud Firestore and Firestore Emulator backends. Set the FIRESTORE_IMPLEMENTATION environment variable. ```bash ~/Documents/fake_cloud_firestore $ FIRESTORE_IMPLEMENTATION=cloud_firestore flutter drive --target=test_driver/field_value_behaviors.dart ``` -------------------------------- ### Perform Aggregate Queries with Fake Cloud Firestore Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Use this snippet to perform aggregate operations like count, sum, and average on query results. Ensure you have imported the necessary libraries and initialized FakeFirebaseFirestore. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); final orders = firestore.collection('orders'); // Seed data await orders.add({'product': 'Laptop', 'quantity': 2, 'price': 999.99}); await orders.add({'product': 'Mouse', 'quantity': 5, 'price': 29.99}); await orders.add({'product': 'Keyboard', 'quantity': 3, 'price': 79.99}); // Count documents final countQuery = orders.count(); final countSnapshot = await countQuery.get(); print('Total orders: ${countSnapshot.count}'); // Output: Total orders: 3 // Count with filter final expensiveCount = await orders.where('price', isGreaterThan: 50).count().get(); print('Expensive items: ${expensiveCount.count}'); // Output: Expensive items: 2 // Aggregate with sum and average final aggregateQuery = orders.aggregate( sum('quantity'), average('price'), ); final aggregateSnapshot = await aggregateQuery.get(); print('Total quantity: ${aggregateSnapshot.getSum('quantity')}'); // Output: Total quantity: 10 print('Average price: ${aggregateSnapshot.getAverage('price')}'); // Output: Average price: ~369.99 } ``` -------------------------------- ### Mocking Exceptions with `mock_exceptions` Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Simulate Firebase exceptions for testing error handling scenarios. Use `whenCalling` to mock specific method calls on document references. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:mock_exceptions/mock_exceptions.dart'; void main() async { final firestore = FakeFirebaseFirestore(); final doc = firestore.doc('users/user1'); // Mock exception on set whenCalling(Invocation.method(#set, null)) .on(doc) .thenThrow(FirebaseException(plugin: 'firestore', code: 'unavailable', message: 'Network error')); try { await doc.set({'name': 'Test'}); } on FirebaseException catch (e) { print('Caught: ${e.code}'); // Output: Caught: unavailable } // Mock exception on get final doc2 = firestore.doc('users/user2'); whenCalling(Invocation.method(#get, null)) .on(doc2) .thenThrow(FirebaseException(plugin: 'firestore', code: 'permission-denied')); try { await doc2.get(); } on FirebaseException catch (e) { print('Permission denied: ${e.code}'); // Output: Permission denied: permission-denied } // State-based exceptions (automatic) final doc3 = firestore.doc('nonexistent/doc'); try { await doc3.update({'field': 'value'}); // Throws because doc doesn't exist } on FirebaseException catch (e) { print('Error: ${e.code}'); // Output: Error: not-found } } ``` -------------------------------- ### UI Test with Fake Firestore Source: https://github.com/atn832/fake_cloud_firestore/blob/master/README.md Integrate FakeFirebaseFirestore into Flutter UI tests to simulate data fetching and display. Ensure to pump and idle the tester to allow stream updates. ```dart import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:firestore_example/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; const MessagesCollection = 'messages'; void main() { testWidgets('shows messages', (WidgetTester tester) async { // Populate the fake database. final firestore = FakeFirebaseFirestore(); await firestore.collection(MessagesCollection).add({ 'message': 'Hello world!', 'created_at': FieldValue.serverTimestamp(), }); // Render the widget. await tester.pumpWidget(MaterialApp( title: 'Firestore Example', home: MyHomePage(firestore: firestore))); // Let the snapshots stream fire a snapshot. await tester.idle(); // Re-render. await tester.pump(); // // Verify the output. expect(find.text('Hello world!'), findsOneWidget); expect(find.text('Message 1 of 1'), findsOneWidget); }); } ``` -------------------------------- ### Perform Atomic Batch Writes Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Execute multiple write operations (set, update, delete) atomically using a batch. This ensures all operations succeed or fail together. Batches have a maximum limit of 500 operations. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); // Create a batch final batch = firestore.batch(); // Queue multiple operations final user1 = firestore.doc('users/user1'); final user2 = firestore.doc('users/user2'); final user3 = firestore.doc('users/user3'); batch.set(user1, {'name': 'Alice', 'role': 'admin'}); batch.set(user2, {'name': 'Bob', 'role': 'user'}); batch.set(user3, {'name': 'Charlie', 'role': 'user'}); // Update existing document batch.update(user1, {'lastLogin': DateTime.now().toIso8601String()}); // Delete document batch.delete(user3); // Merge data batch.set(user2, {'email': 'bob@example.com'}, SetOptions(merge: true)); // Commit all operations atomically await batch.commit(); // Verify results final snapshot1 = await user1.get(); print(snapshot1.data()); // Output: {name: Alice, role: admin, lastLogin: ...} final snapshot2 = await user2.get(); print(snapshot2.data()); // Output: {name: Bob, role: user, email: bob@example.com} final snapshot3 = await user3.get(); print(snapshot3.exists); // Output: false } ``` -------------------------------- ### Access Collections with FakeFirebaseFirestore Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Access top-level and nested collections using collection(). Supports adding documents, retrieving all documents, and performing collection group queries across subcollections with the same name. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); // Access top-level collection final usersCollection = firestore.collection('users'); // Access nested subcollection final friendsCollection = firestore.collection('users/user123/friends'); // Add documents to collection final docRef = await usersCollection.add({ 'name': 'Alice', 'email': 'alice@example.com', 'createdAt': FieldValue.serverTimestamp(), }); print(docRef.id); // Output: auto-generated ID like "abc123xyz" // Get all documents in collection final querySnapshot = await usersCollection.get(); for (var doc in querySnapshot.docs) { print('${doc.id}: ${doc.data()}'); } // Collection group query (across all subcollections with same name) await firestore.collection('users/user1/posts').add({'title': 'Post 1'}); await firestore.collection('users/user2/posts').add({'title': 'Post 2'}); final allPosts = await firestore.collectionGroup('posts').get(); print(allPosts.docs.length); // Output: 2 } ``` -------------------------------- ### Filter documents with where() Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Use `where()` to filter documents based on equality, comparison, and array operations. Supports compound filters with `Filter.and()` and `Filter.or()`. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); final products = firestore.collection('products'); // Seed test data await products.add({'name': 'Laptop', 'price': 999, 'tags': ['electronics', 'computers'], 'inStock': true}); await products.add({'name': 'Phone', 'price': 699, 'tags': ['electronics', 'mobile'], 'inStock': true}); await products.add({'name': 'Desk', 'price': 299, 'tags': ['furniture'], 'inStock': false}); // Equality filter final inStock = await products.where('inStock', isEqualTo: true).get(); print(inStock.docs.length); // Output: 2 // Comparison filters final expensive = await products.where('price', isGreaterThan: 500).get(); print(expensive.docs.map((d) => d.get('name')).toList()); // Output: [Laptop, Phone] // Array contains final electronics = await products.where('tags', arrayContains: 'electronics').get(); print(electronics.docs.length); // Output: 2 // Array contains any final furnitureOrMobile = await products.where('tags', arrayContainsAny: ['furniture', 'mobile']).get(); print(furnitureOrMobile.docs.length); // Output: 2 // Where in final specific = await products.where('name', whereIn: ['Laptop', 'Desk']).get(); print(specific.docs.length); // Output: 2 // Compound filters with Filter.and / Filter.or final query = products.where( Filter.and( Filter('inStock', isEqualTo: true), Filter.or( Filter('price', isLessThan: 700), Filter('tags', arrayContains: 'computers'), ), ), ); final result = await query.get(); print(result.docs.map((d) => d.get('name')).toList()); // Output: [Laptop, Phone] } ``` -------------------------------- ### Execute Atomic Transactions Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Perform read-then-write operations atomically using transactions. All reads must be completed before any writes occur within the transaction block. This ensures data consistency. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; void main() async { final firestore = FakeFirebaseFirestore(); // Setup initial data final accountDoc = firestore.doc('accounts/account1'); await accountDoc.set({'balance': 100}); // Run transaction final result = await firestore.runTransaction((transaction) async { // Read first final snapshot = await transaction.get(accountDoc); final currentBalance = snapshot.get('balance') as int; // Calculate new value final newBalance = currentBalance + 50; // Write after all reads transaction.update(accountDoc, {'balance': newBalance}); return newBalance; }); print('New balance: $result'); // Output: New balance: 150 // Transfer between accounts example final sender = firestore.doc('accounts/sender'); final receiver = firestore.doc('accounts/receiver'); await sender.set({'balance': 500}); await receiver.set({'balance': 200}); await firestore.runTransaction((transaction) async { final senderSnapshot = await transaction.get(sender); final receiverSnapshot = await transaction.get(receiver); final senderBalance = senderSnapshot.get('balance') as int; final receiverBalance = receiverSnapshot.get('balance') as int; final transferAmount = 100; transaction.update(sender, {'balance': senderBalance - transferAmount}); transaction.update(receiver, {'balance': receiverBalance + transferAmount}); }); print((await sender.get()).get('balance')); // Output: 400 print((await receiver.get()).get('balance')); // Output: 300 } ``` -------------------------------- ### Field Value Operations Source: https://context7.com/atn832/fake_cloud_firestore/llms.txt Perform atomic operations on fields, including setting server timestamps, incrementing numbers, adding/removing elements from arrays, and deleting fields. ```dart import 'package:fake_cloud_firestore/fake_cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:clock/clock.dart'; void main() async { // With custom clock for predictable timestamps in tests final fakeClock = Clock.fixed(DateTime(2024, 1, 15, 10, 30)); final firestore = FakeFirebaseFirestore(clock: fakeClock); final doc = firestore.doc('posts/post1'); // Server timestamp await doc.set({ 'title': 'Hello World', 'createdAt': FieldValue.serverTimestamp(), 'views': 0, 'tags': ['intro'], }); var snapshot = await doc.get(); print(snapshot.get('createdAt')); // Output: Timestamp for 2024-01-15 10:30 // Increment numeric field await doc.update({'views': FieldValue.increment(1)}); snapshot = await doc.get(); print(snapshot.get('views')); // Output: 1 await doc.update({'views': FieldValue.increment(5)}); snapshot = await doc.get(); print(snapshot.get('views')); // Output: 6 // Array union (add elements) await doc.update({'tags': FieldValue.arrayUnion(['tutorial', 'beginner'])}); snapshot = await doc.get(); print(snapshot.get('tags')); // Output: [intro, tutorial, beginner] // Array remove await doc.update({'tags': FieldValue.arrayRemove(['intro'])}); snapshot = await doc.get(); print(snapshot.get('tags')); // Output: [tutorial, beginner] // Delete field await doc.update({'views': FieldValue.delete()}); snapshot = await doc.get(); print(snapshot.data()?.containsKey('views')); // Output: false } ``` -------------------------------- ### Simulating State Errors Source: https://github.com/atn832/fake_cloud_firestore/blob/master/README.md Fake Cloud Firestore automatically throws StateError for operations like accessing missing fields. This behavior can be tested directly. ```dart final firestore = FakeFirebaseFirestore(); final collection = firestore.collection('test'); final doc = collection.doc('test'); await doc.set({ 'nested': {'field': 3} }); final snapshot = await doc.get(); expect(() => snapshot.get('foo'), throwsA(isA())); expect(() => snapshot.get('nested.foo'), throwsA(isA())); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.