Skip to content

Commit 5e5245d

Browse files
committed
Updated code examples and add unit tests
1 parent f9c25c7 commit 5e5245d

19 files changed

+980
-30
lines changed

examples/react-native/__tests__/js/Models/Business.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ class Business extends Realm.Object {
88
properties: {
99
_id: "objectId",
1010
name: "string",
11-
addresses: { type: "list", objectType: "Address" }, // Embed an array of objects
11+
addresses: { type: "list?", objectType: "Address" }, // Embed an array of objects
1212
},
1313
};
1414
}
1515
// :snippet-end:
16-
export default Business;
16+
export default Business;

examples/react-native/__tests__/js/Models/Contact.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ class Contact extends Realm.Object {
1313
};
1414
}
1515
// :snippet-end:
16-
export default Contact;
16+
export default Contact;
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
import React, {useState} from 'react';
2+
import {Button, TextInput, View, Text} from 'react-native';
3+
import {render, fireEvent, waitFor, act} from '@testing-library/react-native';
4+
import Realm from 'realm';
5+
import {createRealmContext} from '@realm/react';
6+
import Address from '../../Models/Address';
7+
import Contact from '../../Models/Contact';
8+
9+
const realmConfig = {
10+
schema: [Address, Contact],
11+
deleteRealmIfMigrationNeeded: true,
12+
};
13+
14+
const {RealmProvider, useQuery, useRealm} = createRealmContext(realmConfig);
15+
16+
let assertionRealm;
17+
18+
// test describe block for the embedded objects page
19+
describe('embedded objects tests', () => {
20+
beforeEach(async () => {
21+
// we will use this Realm for assertions to access Realm Objects outside of a Functional Component (like required by @realm/react)
22+
assertionRealm = await Realm.open(realmConfig);
23+
24+
// // delete every object in the realmConfig in the Realm to make test idempotent
25+
assertionRealm.write(() => {
26+
assertionRealm.delete(assertionRealm.objects(Contact));
27+
28+
new Contact(assertionRealm, {
29+
name: 'John Smith',
30+
_id: new Realm.BSON.ObjectID(),
31+
address: {
32+
street: '1 Home Street',
33+
city: 'New York City',
34+
country: 'USA',
35+
postalCode: '12345',
36+
},
37+
});
38+
39+
new Contact(assertionRealm, {
40+
name: 'Jane Doe',
41+
_id: new Realm.BSON.ObjectID(),
42+
address: {
43+
street: '2 Home Street',
44+
city: 'Kansas City',
45+
country: 'USA',
46+
postalCode: '54321',
47+
},
48+
});
49+
});
50+
});
51+
afterAll(() => {
52+
// close realm
53+
if (!assertionRealm.isClosed) {
54+
assertionRealm.close();
55+
}
56+
});
57+
it("should create and read an embedded object", async () => {
58+
// :snippet-start: create-embedded-object
59+
// :replace-start: {
60+
// "terms": {
61+
// "LeBron James": "",
62+
// "1 Goat Drive": "",
63+
// "Cleveland": "",
64+
// "USA": "",
65+
// "12345": "",
66+
// " testID='submitContactBtn'": ""
67+
// }
68+
// }
69+
70+
const CreateContact = () => {
71+
const [name, setContactName] = useState('LeBron James');
72+
const [street, setStreet] = useState('1 Goat Drive');
73+
const [city, setCity] = useState('Cleveland');
74+
const [country, setCountry] = useState('USA');
75+
const [postalCode, setPostalCode] = useState('12345');
76+
const realm = useRealm();
77+
78+
const submitContact = () => {
79+
// Create a Contact within a write transaction
80+
realm.write(() => {
81+
// Create an embedded Address object
82+
const address = {
83+
street,
84+
city,
85+
country,
86+
postalCode,
87+
};
88+
new Contact(realm, {
89+
_id: new Realm.BSON.ObjectID(),
90+
name,
91+
address, // Embed the address in the Contact object
92+
});
93+
});
94+
};
95+
return (
96+
<View>
97+
<TextInput value={name} onChangeText={text => setContactName(text)} />
98+
<TextInput value={street} onChangeText={text => setStreet(text)} />
99+
<TextInput value={city} onChangeText={text => setCity(text)} />
100+
<TextInput value={country} onChangeText={text => setCountry(text)} />
101+
<TextInput value={postalCode} onChangeText={text => setPostalCode(text)} />
102+
<Button title='Submit Contact' testID='submitContactBtn' onPress={submitContact} />
103+
</View>
104+
);
105+
};
106+
// :replace-end:
107+
// :snippet-end:
108+
const App = () => (
109+
<RealmProvider>
110+
<CreateContact/>
111+
</RealmProvider>
112+
);
113+
const {findByTestId} = render(<App />);
114+
const submitContactBtn = await waitFor(() => findByTestId('submitContactBtn'), {
115+
timeout: 5000,
116+
});
117+
await act(async () => {
118+
fireEvent.press(submitContactBtn);
119+
});
120+
// check if the new Contact object has been created
121+
const contact = assertionRealm.objects(Contact).filtered("name == 'LeBron James'")[0];
122+
expect(contact.name).toBe('LeBron James');
123+
expect(contact.address.street).toBe('1 Goat Drive');
124+
expect(contact.address.city).toBe('Cleveland');
125+
expect(contact.address.country).toBe('USA');
126+
expect(contact.address.postalCode).toBe('12345');
127+
});
128+
it('should query for an embedded object', async () => {
129+
// :snippet-start: query-embedded-object
130+
// :replace-start: {
131+
// "terms": {
132+
// " testID = 'addressText'": ""
133+
// }
134+
// }
135+
const ContactList = () => {
136+
// Query for all Contact objects
137+
const contacts = useQuery(Contact);
138+
139+
// Run the `.filtered()` method on all the returned Contacts to find the
140+
// contact with the name "John Smith" and the corresponding street address
141+
const contactAddress = contacts
142+
.filtered("name == 'John Smith'")[0].address.street;
143+
144+
return(
145+
<View>
146+
<Text>John Smith's street address:</Text>
147+
<Text testID = 'addressText'>{contactAddress}</Text>
148+
</View>
149+
);
150+
};
151+
// :replace-end:
152+
// :snippet-end:
153+
const App = () => (
154+
<RealmProvider>
155+
<ContactList />
156+
</RealmProvider>
157+
);
158+
const {getByTestId} = render(<App />);
159+
160+
// test that querying for name works
161+
const contactAddress = await waitFor(() => getByTestId('addressText'));
162+
expect(contactAddress.props.children).toBe('1 Home Street');
163+
});
164+
it('should delete an embedded object', async () => {
165+
// :snippet-start: delete-embedded-object
166+
// :replace-start: {
167+
// "terms": {
168+
// " testID = 'deleteContactBtn'": ""
169+
// }
170+
// }
171+
const ContactInfo = ({contactName}) => {
172+
const contacts = useQuery(Contact);
173+
const realm = useRealm();
174+
175+
const deleteContact = () => {
176+
realm.write(() => {
177+
// Deleting the contact also deletes the embedded address of that contact
178+
realm.delete(
179+
contacts.filtered(`name == '${contactName}'`)[0]
180+
);
181+
});
182+
};
183+
return (
184+
<View>
185+
<Button testID='deleteContactBtn' onPress={deleteContact} title='Delete Contact' />
186+
</View>
187+
);
188+
};
189+
// :replace-end:
190+
// :snippet-end:
191+
const App = () => (
192+
<RealmProvider>
193+
<ContactInfo contactName='John Smith'/>
194+
</RealmProvider>
195+
);
196+
const {findByTestId} = render(<App />);
197+
const deleteContactBtn = await waitFor(() => findByTestId('deleteContactBtn'), {
198+
timeout: 5000,
199+
});
200+
await act(async () => {
201+
fireEvent.press(deleteContactBtn);
202+
});
203+
// check if the new Contact object has been deleted
204+
const contact = assertionRealm.objects(Contact)
205+
expect(contact.length).toBe(1);
206+
});
207+
it("should update an embedded object", async () => {
208+
// :snippet-start: update-embedded-object
209+
// :replace-start: {
210+
// "terms": {
211+
// " testID='updateContactBtn'": "",
212+
// "3 jefferson lane": ""
213+
// }
214+
// }
215+
// Find the contact you want to update
216+
const UpdateContact = ({contactName}) => {
217+
const [street, setStreet] = useState('3 jefferson lane');
218+
const contact = useQuery(Contact).filtered(`name == '${contactName}'`)[0];
219+
const realm = useRealm();
220+
221+
const updateStreet = () => {
222+
// Modify the property of the embedded Address object in a write transaction
223+
realm.write(() => {
224+
// Update the address directly through the contact
225+
contact.address.street = street;
226+
});
227+
};
228+
return (
229+
<View>
230+
<Text>{contact.name}</Text>
231+
<TextInput value={street} onChangeText={setStreet} placeholder='Enter New Street Address' />
232+
<Button testID='updateContactBtn' onPress={updateStreet} title='Update Street Address' />
233+
</View>
234+
);
235+
};
236+
// :replace-end:
237+
// :snippet-end:
238+
const App = () => (
239+
<RealmProvider>
240+
<UpdateContact contactName='John Smith'/>
241+
</RealmProvider>
242+
);
243+
const {findByTestId} = render(<App />);
244+
const updateContactBtn = await waitFor(() => findByTestId('updateContactBtn'), {
245+
timeout: 5000,
246+
});
247+
await act(async () => {
248+
fireEvent.press(updateContactBtn);
249+
});
250+
// check if the new Contact object has been updated
251+
const contact = assertionRealm.objects(Contact).filtered("name == 'John Smith'")[0];
252+
expect(contact.address.street).toBe('3 jefferson lane');
253+
});
254+
it("should overwrite an embedded object", async () => {
255+
// :snippet-start: overwrite-embedded-object
256+
// :replace-start: {
257+
// "terms": {
258+
// " testID='overwriteContactBtn'": "",
259+
// "12 Grimmauld Place": "",
260+
// "London": "",
261+
// "UK": "",
262+
// "E1 7AA": ""
263+
// }
264+
// }
265+
const OverwriteContact = ({contactName}) => {
266+
const [street, setStreet] = useState('12 Grimmauld Place');
267+
const [city, setCity] = useState('London');
268+
const [country, setCountry] = useState('UK');
269+
const [postalCode, setPostalCode] = useState('E1 7AA');
270+
const contact = useQuery(Contact).filtered(`name == '${contactName}'`)[0];
271+
const realm = useRealm();
272+
273+
const updateAddress = () => {
274+
realm.write(() => {
275+
// Within a write transaction, overwrite the embedded object with the new address
276+
const address = {
277+
street,
278+
city,
279+
country,
280+
postalCode,
281+
};
282+
contact.address = address;
283+
});
284+
};
285+
return (
286+
<View>
287+
<Text>{contact.name}</Text>
288+
<Text>Enter the new address:</Text>
289+
<TextInput value={street} onChangeText={setStreet} placeholder='Street' />
290+
<TextInput value={city} onChangeText={setCity} placeholder='City' />
291+
<TextInput value={country} onChangeText={setCountry} placeholder='Country' />
292+
<TextInput value={postalCode} onChangeText={setPostalCode} placeholder='Postal Code' />
293+
<Button testID='overwriteContactBtn' onPress={updateAddress} title='Overwrite Address' />
294+
</View>
295+
);
296+
};
297+
// :replace-end:
298+
// :snippet-end:
299+
const App = () => (
300+
<RealmProvider>
301+
<OverwriteContact contactName='John Smith'/>
302+
</RealmProvider>
303+
);
304+
const {findByTestId} = render(<App />);
305+
const overwriteContactBtn = await waitFor(() => findByTestId('overwriteContactBtn'), {
306+
timeout: 5000,
307+
});
308+
await act(async () => {
309+
fireEvent.press(overwriteContactBtn);
310+
});
311+
// check if the new Contact object has been overwritten
312+
const contact = assertionRealm.objects(Contact).filtered("name == 'John Smith'")[0];
313+
expect(contact.address.street).toBe('12 Grimmauld Place');
314+
expect(contact.address.city).toBe('London');
315+
expect(contact.address.country).toBe('UK');
316+
expect(contact.address.postalCode).toBe('E1 7AA');
317+
});
318+
});

examples/react-native/__tests__/ts/Models/Business.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import Address from './Address';
66
class Business extends Realm.Object {
77
_id!: string;
88
name!: string;
9-
addresses!: Realm.List<Address>;
9+
addresses?: Realm.List<Address>;
1010
static schema = {
1111
name: "Business",
1212
primaryKey: "_id",
1313
properties: {
1414
_id: "objectId",
1515
name: "string",
16-
addresses: { type: "list", objectType: "Address" }, // Embed an array of objects
16+
addresses: { type: "list?", objectType: "Address" }, // Embed an array of objects
1717
},
1818
};
1919
}
2020
// :snippet-end:
21-
export default Business;
21+
export default Business;

examples/react-native/__tests__/ts/Models/Contact.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ class Contact extends Realm.Object {
1919
};
2020
}
2121
// :snippet-end:
22-
export default Contact;
22+
export default Contact;

0 commit comments

Comments
 (0)