| Total Complexity | 30 |
| Total Lines | 246 |
| Duplicated Lines | 13.01 % |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | from __future__ import unicode_literals |
||
| 8 | class ModelAttributeTests(AppTestCase): |
||
| 9 | """ |
||
| 10 | Test model construction |
||
| 11 | """ |
||
| 12 | |||
| 13 | def test_untranslated_get(self): |
||
| 14 | """ |
||
| 15 | Test the metaclass of the model. |
||
| 16 | """ |
||
| 17 | try: |
||
| 18 | value = SimpleModel().tr_title |
||
| 19 | except Exception as e: |
||
| 20 | self.assertIsInstance(e, TranslationDoesNotExist) |
||
| 21 | self.assertIsInstance(e, AttributeError) |
||
| 22 | else: |
||
| 23 | self.fail("Expected exception from reading untranslated title, got {0}.".format(repr(value))) |
||
| 24 | |||
| 25 | # Raising attribute error gives some additional benefits: |
||
| 26 | self.assertEqual(getattr(SimpleModel(), 'tr_title', 'FOO'), 'FOO') |
||
| 27 | self.assertFalse(hasattr(SimpleModel(), 'tr_title')) |
||
| 28 | |||
| 29 | def test_default_language(self): |
||
| 30 | """ |
||
| 31 | Test whether simple language assignments work. |
||
| 32 | """ |
||
| 33 | with translation.override('ca-fr'): |
||
| 34 | x = SimpleModel(id=99) # uses get_language(), ID is to avoid reading cached items for 'en' |
||
| 35 | self.assertEqual(x.get_current_language(), translation.get_language()) |
||
| 36 | self.assertEqual(translation.get_language(), 'ca-fr') |
||
| 37 | |||
| 38 | x.shared = 'SHARED' |
||
| 39 | x.tr_title = 'TRANS_CA' |
||
| 40 | x.save() |
||
| 41 | |||
| 42 | # Refetch |
||
| 43 | with translation.override('en'): |
||
| 44 | x = SimpleModel.objects.get(pk=x.pk) |
||
| 45 | self.assertRaises(TranslationDoesNotExist, lambda: x.tr_title) |
||
| 46 | |||
| 47 | # Switch context |
||
| 48 | x.set_current_language('ca-fr') |
||
| 49 | self.assertEqual(x.tr_title, 'TRANS_CA') |
||
| 50 | |||
| 51 | def test_init_args(self): |
||
| 52 | """ |
||
| 53 | Test whether passing translated attributes to __init__() works. |
||
| 54 | """ |
||
| 55 | x = SimpleModel(tr_title='TRANS_TITLE') |
||
| 56 | self.assertEqual(x.tr_title, "TRANS_TITLE") |
||
| 57 | |||
| 58 | y = SimpleModel(tr_title='TRANS_TITLE', _current_language='nl') |
||
| 59 | self.assertEqual(y.get_current_language(), 'nl') |
||
| 60 | self.assertEqual(y.tr_title, "TRANS_TITLE") |
||
| 61 | |||
| 62 | def test_create_args(self): |
||
| 63 | y = SimpleModel.objects.language('nl').create(tr_title='TRANS_TITLE') |
||
| 64 | self.assertEqual(y.get_current_language(), 'nl') |
||
| 65 | self.assertEqual(y.tr_title, "TRANS_TITLE") |
||
| 66 | |||
| 67 | def test_save_multiple(self): |
||
| 68 | """ |
||
| 69 | Test the save_translations() function to store multiple languages. |
||
| 70 | """ |
||
| 71 | x = SimpleModel() |
||
| 72 | x.set_current_language('en') |
||
| 73 | x.tr_title = "TITLE_EN" |
||
| 74 | x.set_current_language('fr') |
||
| 75 | x.tr_title = "TITLE_FR" |
||
| 76 | x.set_current_language('es') |
||
| 77 | x.tr_title = "TITLE_ES" |
||
| 78 | x.set_current_language('nl') |
||
| 79 | x.tr_title = "TITLE_NL" |
||
| 80 | |||
| 81 | x.save() |
||
| 82 | |||
| 83 | # Check if all translations are saved. |
||
| 84 | self.assertEqual(sorted(x.translations.values_list('tr_title', flat=True)), ['TITLE_EN', 'TITLE_ES', 'TITLE_FR', 'TITLE_NL']) |
||
| 85 | self.assertEqual(sorted(x.get_available_languages()), ['en', 'es', 'fr', 'nl']) |
||
| 86 | self.assertTrue(x.has_translation('en')) |
||
| 87 | self.assertTrue(x.has_translation('es')) |
||
| 88 | self.assertFalse(x.has_translation('fi')) |
||
| 89 | |||
| 90 | # Update 2 translations. |
||
| 91 | # Only those should be updated in the database. |
||
| 92 | x.set_current_language('es') |
||
| 93 | x.tr_title = "TITLE_ES2" |
||
| 94 | x.set_current_language('nl') |
||
| 95 | x.tr_title = "TITLE_NL2" |
||
| 96 | |||
| 97 | self.assertNumQueries(2, x.save_translations()) |
||
| 98 | |||
| 99 | # Any unmodified language is not saved. |
||
| 100 | x.set_current_language('it', initialize=True) |
||
| 101 | self.assertTrue(x.has_translation('it')) # does return true for this object. |
||
| 102 | self.assertNumQueries(0, x.save_translations()) |
||
| 103 | self.assertEqual(sorted(x.get_available_languages()), ['en', 'es', 'fr', 'nl']) |
||
| 104 | |||
| 105 | def test_empty_model(self): |
||
| 106 | """ |
||
| 107 | Test whether a translated model without any fields still works. |
||
| 108 | """ |
||
| 109 | x = EmptyModel() |
||
| 110 | x.set_current_language('en', initialize=True) |
||
| 111 | x.set_current_language('fr', initialize=True) |
||
| 112 | x.set_current_language('es') |
||
| 113 | x.set_current_language('nl', initialize=True) |
||
| 114 | x.save() |
||
| 115 | |||
| 116 | self.assertEqual(sorted(x.get_available_languages()), ['en', 'fr', 'nl']) |
||
| 117 | |||
| 118 | def test_create_translation(self): |
||
| 119 | x = SimpleModel.objects.create() |
||
| 120 | x.create_translation('en', tr_title='TITLE_EN') |
||
| 121 | x.create_translation('fr', tr_title='TITLE_FR') |
||
| 122 | |||
| 123 | self.assertEqual(sorted(x.get_available_languages()), ['en', 'fr']) |
||
| 124 | |||
| 125 | def test_fallback_language(self): |
||
| 126 | """ |
||
| 127 | Test whether the fallback language will be returned. |
||
| 128 | """ |
||
| 129 | x = SimpleModel() |
||
| 130 | x.set_current_language(self.conf_fallback) |
||
| 131 | x.tr_title = "TITLE_FALLBACK" |
||
| 132 | |||
| 133 | x.set_current_language(self.other_lang1) |
||
| 134 | x.tr_title = 'TITLE_XX' |
||
| 135 | x.save() |
||
| 136 | |||
| 137 | with translation.override(self.other_lang2): |
||
| 138 | x = SimpleModel.objects.get(pk=x.pk) |
||
| 139 | self.assertEqual(x.tr_title, 'TITLE_FALLBACK') |
||
| 140 | |||
| 141 | def test_fallback_variant(self): |
||
| 142 | """Test de-us falls back to de""" |
||
| 143 | x = SimpleModel() |
||
| 144 | |||
| 145 | x.set_current_language('de') |
||
| 146 | x.tr_title = "Hallo-de" |
||
| 147 | |||
| 148 | x.set_current_language('en') |
||
| 149 | x.tr_title = "Hello-en" |
||
| 150 | |||
| 151 | x.save() |
||
| 152 | |||
| 153 | with translation.override('de-ch'): |
||
| 154 | x = SimpleModel.objects.get(pk=x.pk) |
||
| 155 | self.assertEqual(x.tr_title, 'Hallo-de') |
||
| 156 | |||
| 157 | def test_fallback_language_no_current(self): |
||
| 158 | """ |
||
| 159 | Test whether the fallback language will be returned, |
||
| 160 | even when the current language does not have a translation. |
||
| 161 | """ |
||
| 162 | x = SimpleModel() |
||
| 163 | x.set_current_language(self.conf_fallback) |
||
| 164 | x.tr_title = "TITLE_FALLBACK" |
||
| 165 | |||
| 166 | self.assertEqual( |
||
| 167 | x.safe_translation_getter('tr_title', language_code=self.other_lang1), |
||
| 168 | 'TITLE_FALLBACK') |
||
| 169 | |||
| 170 | View Code Duplication | def test_any_fallback_model(self): |
|
|
|
|||
| 171 | """ |
||
| 172 | Test whether a failure in the fallback language can return any saved language (if configured for it). |
||
| 173 | """ |
||
| 174 | x = AnyLanguageModel() |
||
| 175 | x.set_current_language(self.other_lang1) |
||
| 176 | x.tr_title = "TITLE_XX" |
||
| 177 | |||
| 178 | x.save() |
||
| 179 | |||
| 180 | with translation.override(self.other_lang2): |
||
| 181 | x = AnyLanguageModel.objects.get(pk=x.pk) |
||
| 182 | self.assertRaises(TranslationDoesNotExist, lambda: x._get_translated_model(use_fallback=True)) |
||
| 183 | self.assertEqual(x.tr_title, 'TITLE_XX') # Even though there is no current language, there is a value. |
||
| 184 | |||
| 185 | self.assertNumQueries(0, lambda: x._get_any_translated_model()) # Can fetch from cache next time. |
||
| 186 | self.assertEqual(x._get_any_translated_model().language_code, self.other_lang1) |
||
| 187 | |||
| 188 | View Code Duplication | def test_any_fallback_function(self): |
|
| 189 | x = SimpleModel() |
||
| 190 | x.set_current_language(self.other_lang1) |
||
| 191 | x.tr_title = "TITLE_XX" |
||
| 192 | |||
| 193 | x.save() |
||
| 194 | |||
| 195 | with translation.override(self.other_lang2): |
||
| 196 | x = SimpleModel.objects.get(pk=x.pk) |
||
| 197 | self.assertRaises(TranslationDoesNotExist, lambda: x._get_translated_model(use_fallback=True)) |
||
| 198 | self.assertIs(x.safe_translation_getter('tr_title', 'DEFAULT'), 'DEFAULT') # No lanuage, gives default |
||
| 199 | self.assertEqual(x.safe_translation_getter('tr_title', any_language=True), 'TITLE_XX') # Even though there is no current language, there is a value. |
||
| 200 | |||
| 201 | self.assertNumQueries(0, lambda: x._get_any_translated_model()) # Can fetch from cache next time. |
||
| 202 | self.assertEqual(x._get_any_translated_model().language_code, self.other_lang1) |
||
| 203 | |||
| 204 | def test_save_ignore_fallback_marker(self): |
||
| 205 | """ |
||
| 206 | Test whether the ``save_translations()`` method skips fallback languages |
||
| 207 | """ |
||
| 208 | x = SimpleModel() |
||
| 209 | x.set_current_language(self.other_lang1) |
||
| 210 | x.tr_title = "TITLE_XX" |
||
| 211 | x.set_current_language(self.other_lang2) |
||
| 212 | # try fetching, causing an fallback marker |
||
| 213 | x.safe_translation_getter('tr_title', any_language=True) |
||
| 214 | # Now save. This should not raise errors |
||
| 215 | x.save() |
||
| 216 | |||
| 217 | def test_model_with_zero_pk(self): |
||
| 218 | """ |
||
| 219 | tests that the translated model is returned also when the pk is 0 |
||
| 220 | """ |
||
| 221 | x = SimpleModel() |
||
| 222 | x.set_current_language(self.other_lang1) |
||
| 223 | x.pk = 0 |
||
| 224 | x.tr_title = "EMPTY_PK" |
||
| 225 | |||
| 226 | x.save() |
||
| 227 | |||
| 228 | # now fetch it from db |
||
| 229 | try: |
||
| 230 | SimpleModel.objects.get(pk=x.pk) |
||
| 231 | except TranslationDoesNotExist: |
||
| 232 | self.fail("zero pk is not supported!") |
||
| 233 | |||
| 234 | def test_translatedfieldsmodel_str(self): |
||
| 235 | """Test converting TranslatedFieldsModel to string""" |
||
| 236 | missing_language_code = 'xx' |
||
| 237 | obj = SimpleModel.objects.create(tr_title='Something') |
||
| 238 | |||
| 239 | # Adjust translation object to use language_code that is not |
||
| 240 | # configured. It is easier because various Django version behave |
||
| 241 | # differently if we try to use not configured language. |
||
| 242 | translation = obj.translations.get() |
||
| 243 | translation.language_code = missing_language_code |
||
| 244 | translation.save() |
||
| 245 | # Try to get str() of the TranslatedFieldsModel instance. |
||
| 246 | try: |
||
| 247 | translation_as_str = str(obj.translations.get()) |
||
| 248 | except KeyError: |
||
| 249 | self.fail("Converting translation to string raises KeyError") |
||
| 250 | |||
| 251 | # Check that we get language code as a fallback, when language is |
||
| 252 | # not configured. |
||
| 253 | self.assertEqual(translation_as_str, missing_language_code) |
||
| 254 |