1 # -*- encoding: utf-8 -*-
3 from openerp.tests.common import TransactionCase
7 ID_FIELD = {'id': 'id', 'name': 'id', 'string': "External ID", 'required': False, 'fields': []}
8 def make_field(name='value', string='unknown', required=False, fields=[]):
11 {'id': name, 'name': name, 'string': string, 'required': required, 'fields': fields},
14 class test_basic_fields(TransactionCase):
15 def get_fields(self, field):
16 return self.registry('base_import.import')\
17 .get_fields(self.cr, self.uid, 'base_import.tests.models.' + field)
20 """ A basic field is not required """
21 self.assertEqual(self.get_fields('char'), make_field())
23 def test_required(self):
24 """ Required fields should be flagged (so they can be fill-required) """
25 self.assertEqual(self.get_fields('char.required'), make_field(required=True))
27 def test_readonly(self):
28 """ Readonly fields should be filtered out"""
29 self.assertEqual(self.get_fields('char.readonly'), [ID_FIELD])
31 def test_readonly_states(self):
32 """ Readonly fields with states should not be filtered out"""
33 self.assertEqual(self.get_fields('char.states'), make_field())
35 def test_readonly_states_noreadonly(self):
36 """ Readonly fields with states having nothing to do with
37 readonly should still be filtered out"""
38 self.assertEqual(self.get_fields('char.noreadonly'), [ID_FIELD])
40 def test_readonly_states_stillreadonly(self):
41 """ Readonly fields with readonly states leaving them readonly
42 always... filtered out"""
43 self.assertEqual(self.get_fields('char.stillreadonly'), [ID_FIELD])
46 """ M2O fields should allow import of themselves (name_get),
47 their id and their xid"""
48 self.assertEqual(self.get_fields('m2o'), make_field(fields=[
49 {'id': 'value', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
50 {'id': 'value', 'name': '.id', 'string': 'Database ID', 'required': False, 'fields': []},
53 def test_m2o_required(self):
54 """ If an m2o field is required, its three sub-fields are
55 required as well (the client has to handle that: requiredness
58 self.assertEqual(self.get_fields('m2o.required'), make_field(required=True, fields=[
59 {'id': 'value', 'name': 'id', 'string': 'External ID', 'required': True, 'fields': []},
60 {'id': 'value', 'name': '.id', 'string': 'Database ID', 'required': True, 'fields': []},
63 class test_o2m(TransactionCase):
64 def get_fields(self, field):
65 return self.registry('base_import.import')\
66 .get_fields(self.cr, self.uid, 'base_import.tests.models.' + field)
68 def test_shallow(self):
69 self.assertEqual(self.get_fields('o2m'), make_field(fields=[
70 {'id': 'id', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
71 # FIXME: should reverse field be ignored?
72 {'id': 'parent_id', 'name': 'parent_id', 'string': 'unknown', 'required': False, 'fields': [
73 {'id': 'parent_id', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
74 {'id': 'parent_id', 'name': '.id', 'string': 'Database ID', 'required': False, 'fields': []},
76 {'id': 'value', 'name': 'value', 'string': 'unknown', 'required': False, 'fields': []},
79 class test_match_headers_single(TransactionCase):
80 def test_match_by_name(self):
81 match = self.registry('base_import.import')._match_header(
82 'f0', [{'name': 'f0'}], {})
84 self.assertEqual(match, [{'name': 'f0'}])
86 def test_match_by_string(self):
87 match = self.registry('base_import.import')._match_header(
88 'some field', [{'name': 'bob', 'string': "Some Field"}], {})
90 self.assertEqual(match, [{'name': 'bob', 'string': "Some Field"}])
92 def test_nomatch(self):
93 match = self.registry('base_import.import')._match_header(
94 'should not be', [{'name': 'bob', 'string': "wheee"}], {})
96 self.assertEqual(match, [])
98 def test_recursive_match(self):
101 'string': "My Field",
103 {'name': 'f0', 'string': "Sub field 0", 'fields': []},
104 {'name': 'f1', 'string': "Sub field 2", 'fields': []},
107 match = self.registry('base_import.import')._match_header(
110 self.assertEqual(match, [f, f['fields'][1]])
112 def test_recursive_nomatch(self):
113 """ Match first level, fail to match second level
117 'string': "My Field",
119 {'name': 'f0', 'string': "Sub field 0", 'fields': []},
120 {'name': 'f1', 'string': "Sub field 2", 'fields': []},
123 match = self.registry('base_import.import')._match_header(
126 self.assertEqual(match, [])
128 class test_match_headers_multiple(TransactionCase):
129 def test_noheaders(self):
131 self.registry('base_import.import')._match_headers(
135 def test_nomatch(self):
137 self.registry('base_import.import')._match_headers(
139 ['foo', 'bar', 'baz', 'qux'],
140 ['v1', 'v2', 'v3', 'v4'],
145 ['foo', 'bar', 'baz', 'qux'],
146 dict.fromkeys(range(4))
150 def test_mixed(self):
152 self.registry('base_import.import')._match_headers(
153 iter(['foo bar baz qux/corge'.split()]),
155 {'name': 'bar', 'string': 'Bar'},
156 {'name': 'bob', 'string': 'Baz'},
157 {'name': 'qux', 'string': 'Qux', 'fields': [
158 {'name': 'corge', 'fields': []},
162 (['foo', 'bar', 'baz', 'qux/corge'], {
170 class test_preview(TransactionCase):
171 def make_import(self):
172 Import = self.registry('base_import.import')
173 id = Import.create(self.cr, self.uid, {
174 'res_model': 'res.users',
175 'file': u"로그인,언어\nbob,1\n".encode('euc_kr'),
179 def test_encoding(self):
180 Import, id = self.make_import()
181 result = Import.parse_preview(self.cr, self.uid, id, {
185 self.assertTrue('error' in result)
187 def test_csv_errors(self):
188 Import, id = self.make_import()
190 result = Import.parse_preview(self.cr, self.uid, id, {
193 'encoding': 'euc_kr',
195 self.assertTrue('error' in result)
197 def test_csv_errors(self):
198 Import, id = self.make_import()
200 result = Import.parse_preview(self.cr, self.uid, id, {
203 'encoding': 'euc_kr',
205 self.assertTrue('error' in result)
207 def test_success(self):
208 Import = self.registry('base_import.import')
209 id = Import.create(self.cr, self.uid, {
210 'res_model': 'base_import.tests.models.preview',
211 'file': 'name,Some Value,Counter\n'
217 result = Import.parse_preview(self.cr, self.uid, id, {
223 self.assertEqual(result['matches'], {0: ['name'], 1: ['somevalue'], 2: None})
224 self.assertEqual(result['headers'], ['name', 'Some Value', 'Counter'])
225 # Order depends on iteration order of fields_get
226 self.assertItemsEqual(result['fields'], [
227 {'id': 'id', 'name': 'id', 'string': 'External ID', 'required':False, 'fields': []},
228 {'id': 'name', 'name': 'name', 'string': 'Name', 'required':False, 'fields': []},
229 {'id': 'somevalue', 'name': 'somevalue', 'string': 'Some Value', 'required':True, 'fields': []},
230 {'id': 'othervalue', 'name': 'othervalue', 'string': 'Other Variable', 'required':False, 'fields': []},
232 self.assertEqual(result['preview'], [
237 # Ensure we only have the response fields we expect
238 self.assertItemsEqual(result.keys(), ['matches', 'headers', 'fields', 'preview'])
240 class test_convert_import_data(TransactionCase):
241 """ Tests conversion of base_import.import input into data which
242 can be fed to Model.import_data
245 Import = self.registry('base_import.import')
246 id = Import.create(self.cr, self.uid, {
247 'res_model': 'base_import.tests.models.preview',
248 'file': 'name,Some Value,Counter\n'
253 record = Import.browse(self.cr, self.uid, id)
254 data, fields = Import._convert_import_data(
255 record, ['name', 'somevalue', 'othervalue'],
256 {'quoting': '"', 'separator': ',', 'headers': True,})
258 self.assertItemsEqual(fields, ['name', 'somevalue', 'othervalue'])
259 self.assertItemsEqual(data, [
265 def test_filtered(self):
266 """ If ``False`` is provided as field mapping for a column,
267 that column should be removed from importable data
269 Import = self.registry('base_import.import')
270 id = Import.create(self.cr, self.uid, {
271 'res_model': 'base_import.tests.models.preview',
272 'file': 'name,Some Value,Counter\n'
277 record = Import.browse(self.cr, self.uid, id)
278 data, fields = Import._convert_import_data(
279 record, ['name', False, 'othervalue'],
280 {'quoting': '"', 'separator': ',', 'headers': True,})
282 self.assertItemsEqual(fields, ['name', 'othervalue'])
283 self.assertItemsEqual(data, [
289 def test_norow(self):
290 """ If a row is composed only of empty values (due to having
291 filtered out non-empty values from it), it should be removed
293 Import = self.registry('base_import.import')
294 id = Import.create(self.cr, self.uid, {
295 'res_model': 'base_import.tests.models.preview',
296 'file': 'name,Some Value,Counter\n'
301 record = Import.browse(self.cr, self.uid, id)
302 data, fields = Import._convert_import_data(
303 record, ['name', False, 'othervalue'],
304 {'quoting': '"', 'separator': ',', 'headers': True,})
306 self.assertItemsEqual(fields, ['name', 'othervalue'])
307 self.assertItemsEqual(data, [
312 def test_nofield(self):
313 Import = self.registry('base_import.import')
315 id = Import.create(self.cr, self.uid, {
316 'res_model': 'base_import.tests.models.preview',
317 'file': 'name,Some Value,Counter\n'
321 record = Import.browse(self.cr, self.uid, id)
324 Import._convert_import_data,
326 {'quoting': '"', 'separator': ',', 'headers': True,})
328 def test_falsefields(self):
329 Import = self.registry('base_import.import')
331 id = Import.create(self.cr, self.uid, {
332 'res_model': 'base_import.tests.models.preview',
333 'file': 'name,Some Value,Counter\n'
337 record = Import.browse(self.cr, self.uid, id)
340 Import._convert_import_data,
341 record, [False, False, False],
342 {'quoting': '"', 'separator': ',', 'headers': True,})