def test_encode_embedded_dict(self):
        @pymongo
        @jsonclass
        class SimpleEncodeScalarTypesDict:
            id: str = types.readonly.str.primary.mongoid.required
            str_values: Dict[str, str]

        simple_object = SimpleEncodeScalarTypesDict(str_values={
            '0': 'zero',
            '1': 'one'
        })
        batch_command = Encoder().encode_root(simple_object)
        insert_command = cast(InsertOneCommand, batch_command.commands[0])
        serialized = insert_command.object
        self.assertEqual(set(serialized.keys()), set(['_id', 'strValues']))
        self.assertIsInstance(serialized['_id'], ObjectId)
        self.assertEqual(serialized['strValues'], {'0': 'zero', '1': 'one'})
    def test_encode_date_into_datetime(self):
        @pymongo
        @jsonclass
        class SimpleEncodeDate:
            id: str = types.readonly.str.primary.mongoid.required
            d1: date = date(2012, 9, 15)
            d2: date = date(2020, 9, 14)

        simple_object = SimpleEncodeDate()
        batch_command = Encoder().encode_root(simple_object)
        insert_command = cast(InsertOneCommand, batch_command.commands[0])
        serialized = insert_command.object
        self.assertEqual(set(serialized.keys()), set(['_id', 'd1', 'd2']))
        self.assertIsInstance(serialized['_id'], ObjectId)
        self.assertEqual(serialized['d1'],
                         datetime(2012, 9, 15, 0, 0, 0, tzinfo=timezone.utc))
        self.assertEqual(serialized['d2'],
                         datetime(2020, 9, 14, 0, 0, 0, tzinfo=timezone.utc))
    def test_encode_dict_keep_keys(self):
        @pymongo
        @jsonclass
        class MediumEncodeCamelizeDictKeys:
            id: str = types.readonly.str.primary.mongoid.required
            val: Dict[str, str] = types.dictof(types.str)

        simple_object = MediumEncodeCamelizeDictKeys(val={
            'keyOne': 'val_one',
            'keyTwo': 'val_two'
        })
        batch_command = Encoder().encode_root(simple_object)
        commands = batch_command.commands
        encoded_val = commands[0].object['val']
        self.assertEqual(encoded_val, {
            'keyOne': 'val_one',
            'keyTwo': 'val_two'
        })
    def test_encode_embedded_list(self):
        @pymongo
        @jsonclass
        class SimpleEncodeScalarTypesList:
            id: str = types.readonly.str.primary.mongoid.required
            str_values: List[str]
            int_values: List[int]
            bool_values: List[bool]

        simple_object = SimpleEncodeScalarTypesList(str_values=['0', '1'],
                                                    int_values=[0, 1],
                                                    bool_values=[False, True])
        batch_command = Encoder().encode_root(simple_object)
        insert_command = cast(InsertOneCommand, batch_command.commands[0])
        serialized = insert_command.object
        self.assertEqual(set(serialized.keys()),
                         set(['_id', 'strValues', 'intValues', 'boolValues']))
        self.assertIsInstance(serialized['_id'], ObjectId)
        self.assertEqual(serialized['strValues'], ['0', '1'])
        self.assertEqual(serialized['intValues'], [0, 1])
        self.assertEqual(serialized['boolValues'], [False, True])
    def test_encode_local_key_instance(self):
        @pymongo
        @jsonclass
        class SimpleEncodeLocalKeyInstanceAddress:
            id: str = types.readonly.str.primary.mongoid.required
            line1: str
            owner: SimpleEncodeLocalKeyInstance = types.objof(
                'SimpleEncodeLocalKeyInstance').linkedby('address')

        @pymongo
        @jsonclass
        class SimpleEncodeLocalKeyInstance:
            id: str = types.readonly.str.primary.mongoid.required
            address: SimpleEncodeLocalKeyInstanceAddress = types.linkto.objof(
                SimpleEncodeLocalKeyInstanceAddress)

        simple_object = SimpleEncodeLocalKeyInstance(
            address={'line1': 'Flam Road'})
        batch_command = Encoder().encode_root(simple_object)
        commands = batch_command.commands
        self.assertEqual(len(commands), 2)
        address_data = commands[0].object
        owner_data = commands[1].object
        self.assertEqual(owner_data['addressId'], address_data['_id'])