|
| 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 HomeOwner from '../../Models/HomeOwner'; |
| 7 | + |
| 8 | +const realmConfig = { |
| 9 | + schema: [HomeOwner], |
| 10 | + deleteRealmIfMigrationNeeded: true, |
| 11 | +}; |
| 12 | + |
| 13 | +const {RealmProvider, useRealm, useQuery} = createRealmContext(realmConfig); |
| 14 | + |
| 15 | +let assertionRealm; |
| 16 | + |
| 17 | +describe('Dictionary Tests', () => { |
| 18 | + beforeEach(async () => { |
| 19 | + // we will use this Realm for assertions to access Realm Objects outside of a Functional Component (like required by @realm/react) |
| 20 | + assertionRealm = await Realm.open(realmConfig); |
| 21 | + // delete every object in the realmConfig in the Realm to make test idempotent |
| 22 | + assertionRealm.write(() => { |
| 23 | + assertionRealm.delete(assertionRealm.objects(HomeOwner)); |
| 24 | + |
| 25 | + new HomeOwner(assertionRealm, { |
| 26 | + name: 'Martin Doe', |
| 27 | + home: {address: 'Summerhill St.', color: 'pink'}, |
| 28 | + }); |
| 29 | + new HomeOwner(assertionRealm, { |
| 30 | + name: 'Tony Henry', |
| 31 | + home: {address: '200 lake street', price: 123000}, |
| 32 | + }); |
| 33 | + new HomeOwner(assertionRealm, { |
| 34 | + name: 'Rob Johnson', |
| 35 | + home: {address: '1 washington street', color: 'red'}, |
| 36 | + }); |
| 37 | + new HomeOwner(assertionRealm, { |
| 38 | + name: 'Anna Smith', |
| 39 | + home: {address: '2 jefferson lane', yearRenovated: 1994, color: 'blue'}, |
| 40 | + }); |
| 41 | + }); |
| 42 | + }); |
| 43 | + it('should create an object with a dictionary value', async () => { |
| 44 | + // :snippet-start: create-object-with-dictionary-value |
| 45 | + // :replace-start: { |
| 46 | + // "terms": { |
| 47 | + // " testID='submitHomeOwnerBtn'": "" |
| 48 | + // } |
| 49 | + // } |
| 50 | + const CreateHomeOwner = () => { |
| 51 | + const [homeOwnerName, setHomeOwnerName] = useState('John Smith'); |
| 52 | + const [address, setAddress] = useState('1 Home Street'); |
| 53 | + const realm = useRealm(); |
| 54 | + |
| 55 | + const submitHomeOwner = () => { |
| 56 | + // Create a HomeOwner within a Write Transaction |
| 57 | + realm.write(() => { |
| 58 | + new HomeOwner(realm, { |
| 59 | + name: homeOwnerName, |
| 60 | + // For the dictionary field, 'home', set the value to a regular javascript object |
| 61 | + home: { |
| 62 | + address, |
| 63 | + }, |
| 64 | + }); |
| 65 | + }); |
| 66 | + }; |
| 67 | + return ( |
| 68 | + <View> |
| 69 | + <TextInput value={homeOwnerName} onChangeText={text => setHomeOwnerName(text)} /> |
| 70 | + <TextInput value={address} onChangeText={text => setAddress(text)} /> |
| 71 | + <Button title='Submit Home Owner' testID='submitHomeOwnerBtn' onPress={submitHomeOwner} /> |
| 72 | + </View> |
| 73 | + ); |
| 74 | + }; |
| 75 | + // :replace-end: |
| 76 | + // :snippet-end: |
| 77 | + const App = () => ( |
| 78 | + <RealmProvider> |
| 79 | + <CreateHomeOwner /> |
| 80 | + </RealmProvider> |
| 81 | + ); |
| 82 | + const {findByTestId} = render(<App />); |
| 83 | + const submitHomeOwnerBtn = await waitFor(() => findByTestId('submitHomeOwnerBtn'), { |
| 84 | + timeout: 5000, |
| 85 | + }); |
| 86 | + await act(async () => { |
| 87 | + fireEvent.press(submitHomeOwnerBtn); |
| 88 | + }); |
| 89 | + // check if the new HomeOwner object has been created |
| 90 | + const homeOwner = assertionRealm.objects(HomeOwner).filtered("name == 'John Smith'")[0]; |
| 91 | + expect(homeOwner.name).toBe('John Smith'); |
| 92 | + expect(homeOwner.home.address).toBe('1 Home Street'); |
| 93 | + }); |
| 94 | + it('should query for objects with a dictionary property', async () => { |
| 95 | + // :snippet-start: query-objects-with-dictionary |
| 96 | + // :replace-start: { |
| 97 | + // "terms": { |
| 98 | + // " testID='homeItem'": "", |
| 99 | + // " testID='homeWithAPriceItem'": "", |
| 100 | + // " testID='summerHillHouseColor'": "", |
| 101 | + // " testID='redHouseAddress'": "" |
| 102 | + // } |
| 103 | + // } |
| 104 | + const HomeList = () => { |
| 105 | + // query for all HomeOwner objects |
| 106 | + const homeOwners = useQuery(HomeOwner); |
| 107 | + |
| 108 | + // run the `.filtered()` method on all the returned homeOwners to |
| 109 | + // find all homeOwners that have a house with a listed price |
| 110 | + const listedPriceHomes = homeOwners.filtered('home.@keys = "price"'); |
| 111 | + |
| 112 | + // run the `.filtered()` method on all the returned homeOwners to |
| 113 | + // find the house with the address "Summerhill St." |
| 114 | + const summerHillHouse = homeOwners.filtered('home["address"] = "Summerhill St."')[0].home; |
| 115 | + |
| 116 | + // run the `.filtered()` method on all the returned homeOwners to |
| 117 | + // find the first house that has any field with a value of 'red' |
| 118 | + const redHouse = homeOwners.filtered('home.@values = "red"')[0].home; |
| 119 | + return ( |
| 120 | + <View> |
| 121 | + <Text>All homes:</Text> |
| 122 | + {homeOwners.map(homeOwner => ( |
| 123 | + <View> |
| 124 | + <Text testID='homeItem'>{homeOwner.home.address}</Text> |
| 125 | + </View> |
| 126 | + ))} |
| 127 | + |
| 128 | + <Text>All homes with a price:</Text> |
| 129 | + {listedPriceHomes.map(homeOwner => ( |
| 130 | + <View> |
| 131 | + <Text testID='homeWithAPriceItem'>{homeOwner.home.address}</Text> |
| 132 | + <Text>{homeOwner.home.price}</Text> |
| 133 | + </View> |
| 134 | + ))} |
| 135 | + |
| 136 | + <Text>Summer Hill House:</Text> |
| 137 | + <Text>{summerHillHouse.address}</Text> |
| 138 | + <Text testID='summerHillHouseColor'>{summerHillHouse.color}</Text> |
| 139 | + |
| 140 | + <Text>Red House:</Text> |
| 141 | + <Text testID='redHouseAddress'>{redHouse.address}</Text> |
| 142 | + </View> |
| 143 | + ); |
| 144 | + }; |
| 145 | + // :replace-end: |
| 146 | + // :snippet-end: |
| 147 | + const App = () => ( |
| 148 | + <RealmProvider> |
| 149 | + <HomeList /> |
| 150 | + </RealmProvider> |
| 151 | + ); |
| 152 | + const {getByTestId, getAllByTestId} = render(<App />); |
| 153 | + |
| 154 | + const homeItem = await waitFor(() => getAllByTestId('homeItem')); |
| 155 | + // test that 4 home items are rendered, since there are 4 HomeOwner realm objects |
| 156 | + expect(homeItem.length).toBe(4); |
| 157 | + |
| 158 | + const homeWithAPriceItem = await waitFor(() => getAllByTestId('homeWithAPriceItem')); |
| 159 | + |
| 160 | + // test that there is only one home with a price that is rendered, and its address is '200 lake street' |
| 161 | + expect(homeWithAPriceItem.length).toBe(1); |
| 162 | + expect(homeWithAPriceItem[0].props.children).toBe('200 lake street'); |
| 163 | + |
| 164 | + const summerHillHouseColor = await waitFor(() => getByTestId('summerHillHouseColor')); |
| 165 | + // test that the summer hill house has rendered properly in the UI by checking its color |
| 166 | + expect(summerHillHouseColor.props.children).toBe('pink'); |
| 167 | + |
| 168 | + const redHouseAddress = await waitFor(() => getByTestId('redHouseAddress')); |
| 169 | + // test that the red house has rendered properly in the UI by checking its address |
| 170 | + expect(redHouseAddress.props.children).toBe('1 washington street'); |
| 171 | + }); |
| 172 | + it('should update a dictionary', async () => { |
| 173 | + // :snippet-start: update-a-dictionary |
| 174 | + // :replace-start: { |
| 175 | + // "terms": { |
| 176 | + // " testID='homeOwnerName'": "", |
| 177 | + // " testID='updateAddressBtn'": "", |
| 178 | + // "3 jefferson lane": "" |
| 179 | + // } |
| 180 | + // } |
| 181 | + const UpdateHome = ({homeOwnerName}) => { |
| 182 | + const [address, setAddress] = useState('3 jefferson lane'); |
| 183 | + const realm = useRealm(); |
| 184 | + const homeOwner = useQuery(HomeOwner).filtered(`name == '${homeOwnerName}'`)[0]; |
| 185 | + |
| 186 | + const updateAddress = () => { |
| 187 | + // Update the home object with the new address |
| 188 | + realm.write(() => { |
| 189 | + // use the `set()` method to update a field of a dictionary |
| 190 | + homeOwner.home.set({address}); |
| 191 | + // alternatively, update a field of a dictionary through dot notation |
| 192 | + homeOwner.home.yearRenovated = 2004; |
| 193 | + }); |
| 194 | + }; |
| 195 | + |
| 196 | + return ( |
| 197 | + <View> |
| 198 | + <Text testID='homeOwnerName'>{homeOwner.name}</Text> |
| 199 | + <TextInput value={address} onChangeText={setAddress} placeholder='Enter new address' /> |
| 200 | + <Button onPress={updateAddress} title='Update Address' testID='updateAddressBtn' /> |
| 201 | + </View> |
| 202 | + ); |
| 203 | + }; |
| 204 | + // :replace-end: |
| 205 | + // :snippet-end: |
| 206 | + const App = () => ( |
| 207 | + <RealmProvider> |
| 208 | + <UpdateHome homeOwnerName='Anna Smith' /> |
| 209 | + </RealmProvider> |
| 210 | + ); |
| 211 | + const {getByTestId} = render(<App />); |
| 212 | + const homeOwnerName = await waitFor(() => getByTestId('homeOwnerName')); |
| 213 | + // Test that the homeOwner object has been found, by checking that 'Anna Smith' has rendered properly |
| 214 | + expect(homeOwnerName.props.children).toBe('Anna Smith'); |
| 215 | + |
| 216 | + const updateAddressBtn = await waitFor(() => getByTestId('updateAddressBtn')); |
| 217 | + // Test that the home owner's home has been updated by checking its address and year renovated before and after the updateAddressBtn has been pressed |
| 218 | + const annaSmithHome = assertionRealm.objects(HomeOwner).filtered('name == "Anna Smith"')[0].home; |
| 219 | + expect(annaSmithHome.address).toBe('2 jefferson lane'); |
| 220 | + expect(annaSmithHome.yearRenovated).toBe(1994); |
| 221 | + await act(async () => { |
| 222 | + fireEvent.press(updateAddressBtn); |
| 223 | + }); |
| 224 | + expect(annaSmithHome.address).toBe('3 jefferson lane'); |
| 225 | + expect(annaSmithHome.yearRenovated).toBe(2004); |
| 226 | + }); |
| 227 | + it('should delete members of a dictionary', async () => { |
| 228 | + // :snippet-start: delete-members-of-a-dictionary |
| 229 | + // :replace-start: { |
| 230 | + // "terms": { |
| 231 | + // " testID='deleteExtraHomeInfoBtn'": "" |
| 232 | + // } |
| 233 | + // } |
| 234 | + const HomeInfo = ({homeOwnerName}) => { |
| 235 | + const realm = useRealm(); |
| 236 | + const homeOwner = useQuery(HomeOwner).filtered(`name == '${homeOwnerName}'`)[0]; |
| 237 | + |
| 238 | + const deleteExtraHomeInfo = () => { |
| 239 | + realm.write(() => { |
| 240 | + // remove the 'yearRenovated' and 'color' field of the house |
| 241 | + homeOwner.home.remove(['yearRenovated', 'color']); |
| 242 | + }); |
| 243 | + }; |
| 244 | + |
| 245 | + return ( |
| 246 | + <View> |
| 247 | + <Text>{homeOwner.name}</Text> |
| 248 | + <Text>{homeOwner.home.address}</Text> |
| 249 | + <Button onPress={deleteExtraHomeInfo} title='Delete extra home info' testID='deleteExtraHomeInfoBtn' /> |
| 250 | + </View> |
| 251 | + ); |
| 252 | + }; |
| 253 | + // :replace-end: |
| 254 | + // :snippet-end: |
| 255 | + |
| 256 | + const App = () => ( |
| 257 | + <RealmProvider> |
| 258 | + <HomeInfo homeOwnerName='Anna Smith' /> |
| 259 | + </RealmProvider> |
| 260 | + ); |
| 261 | + const {getByTestId} = render(<App />); |
| 262 | + |
| 263 | + const deleteExtraHomeInfoBtn = await waitFor(() => getByTestId('deleteExtraHomeInfoBtn')); |
| 264 | + // Test that the home owner's home had her 'yearRenovated' & 'color' removed by checking its address and year renovated before and after the deleteExtraHomeInfoBtn has been pressed |
| 265 | + const annaSmithHome = assertionRealm.objects(HomeOwner).filtered('name == "Anna Smith"')[0].home; |
| 266 | + expect(annaSmithHome.yearRenovated).toBe(1994); |
| 267 | + expect(annaSmithHome.color).toBe('blue'); |
| 268 | + await act(async () => { |
| 269 | + fireEvent.press(deleteExtraHomeInfoBtn); |
| 270 | + }); |
| 271 | + expect(annaSmithHome.yearRenovated).toBeUndefined(); |
| 272 | + expect(annaSmithHome.color).toBeUndefined(); |
| 273 | + }); |
| 274 | +}); |
0 commit comments