205 lines
6.0 KiB
Python
205 lines
6.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
import sys
|
|
import unittest
|
|
from mock import patch
|
|
from trytond.tests.test_tryton import install_module, with_transaction
|
|
from trytond.transaction import Transaction
|
|
from trytond.pool import Pool
|
|
|
|
|
|
class MPTTTestCase(unittest.TestCase):
|
|
'Test Modified Preorder Tree Traversal'
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
install_module('tests')
|
|
|
|
def check_tree(self, parent_id=None, left=-1, right=sys.maxint):
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
with Transaction().set_context(active_test=False):
|
|
childs = Mptt.search([
|
|
('parent', '=', parent_id),
|
|
], order=[('left', 'ASC')])
|
|
for child in childs:
|
|
assert child.left > left, \
|
|
'%s: left %d <= parent left %d' % \
|
|
(child, child.left, left)
|
|
assert child.left < child.right, \
|
|
'%s: left %d >= right %d' % \
|
|
(child, child.left, child.right)
|
|
assert child.right < right, \
|
|
'%s: right %d >= parent right %d' % \
|
|
(child, child.right, right)
|
|
self.check_tree(child.id, left=child.left,
|
|
right=child.right)
|
|
next_left = -1
|
|
for child in childs:
|
|
assert child.left > next_left, \
|
|
'%s: left %d <= next left %d' % \
|
|
(child, child.left, next_left)
|
|
next_left = child.right
|
|
childs.reverse()
|
|
previous_right = sys.maxint
|
|
for child in childs:
|
|
assert child.right < previous_right, \
|
|
'%s: right %d >= previous right %d' \
|
|
% (child, child.right, previous_right)
|
|
previous_right = child.left
|
|
|
|
def reparent(self, parent=None):
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
records = Mptt.search([
|
|
('parent', '=', parent),
|
|
])
|
|
if not records:
|
|
return
|
|
for record in records:
|
|
for record2 in records:
|
|
if record != record2:
|
|
record.parent = record2
|
|
record.save()
|
|
record.parent = parent
|
|
record.save()
|
|
for record in records:
|
|
self.reparent(record)
|
|
|
|
def create(self):
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
new_records = [None, None, None]
|
|
for j in range(3):
|
|
parent_records = new_records
|
|
new_records = []
|
|
k = 0
|
|
to_create = []
|
|
for parent_record in parent_records:
|
|
to_create.extend([{
|
|
'name': 'Test %d %d %d' % (j, k, i),
|
|
'parent': (parent_record.id
|
|
if parent_record else None),
|
|
} for i in range(3)])
|
|
k += 1
|
|
new_records = Mptt.create(to_create)
|
|
|
|
@with_transaction()
|
|
def test_create(self):
|
|
'Test create tree'
|
|
self.create()
|
|
self.check_tree()
|
|
|
|
@with_transaction()
|
|
def test_reparent(self):
|
|
'Test re-parent'
|
|
self.create()
|
|
self.reparent()
|
|
|
|
@with_transaction()
|
|
def test_active(self):
|
|
'Test active'
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
self.create()
|
|
|
|
records = Mptt.search([])
|
|
for record in records:
|
|
if record.id % 2:
|
|
record.active = False
|
|
record.save()
|
|
self.check_tree()
|
|
self.reparent()
|
|
self.check_tree()
|
|
|
|
records = Mptt.search([])
|
|
Mptt.write(records, {
|
|
'active': True,
|
|
})
|
|
Mptt.write(records[::2], {
|
|
'active': False
|
|
})
|
|
self.check_tree()
|
|
|
|
records = Mptt.search([])
|
|
Mptt.write(records, {
|
|
'active': True,
|
|
})
|
|
Mptt.write(records[:len(records) // 2], {
|
|
'active': False
|
|
})
|
|
self.check_tree()
|
|
|
|
records = Mptt.search([])
|
|
Mptt.write(records, {
|
|
'active': False
|
|
})
|
|
self.reparent()
|
|
self.check_tree()
|
|
|
|
@with_transaction()
|
|
def test_delete(self):
|
|
'Test delete'
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
self.create()
|
|
|
|
records = Mptt.search([])
|
|
for record in records:
|
|
if record.id % 2:
|
|
Mptt.delete([record])
|
|
self.check_tree()
|
|
|
|
records = Mptt.search([])
|
|
Mptt.delete(records[:len(records) // 2])
|
|
self.check_tree()
|
|
|
|
records = Mptt.search([])
|
|
Mptt.delete(records)
|
|
self.check_tree()
|
|
|
|
@with_transaction()
|
|
def test_update_only_if_parent_is_modified(self):
|
|
'The left and right fields must only be updated if parent is modified'
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
self.create()
|
|
|
|
records = Mptt.search([
|
|
('parent', '=', None),
|
|
])
|
|
with patch.object(Mptt, '_update_tree') as mock:
|
|
Mptt.write(records, {'name': 'Parent Records'})
|
|
self.assertFalse(mock.called)
|
|
|
|
first_parent, second_parent = records[:2]
|
|
Mptt.write(list(first_parent.childs), {
|
|
'parent': second_parent.id,
|
|
})
|
|
|
|
self.assertTrue(mock.called)
|
|
|
|
@with_transaction()
|
|
def test_nested_create(self):
|
|
pool = Pool()
|
|
Mptt = pool.get('test.mptt')
|
|
|
|
record, = Mptt.create([{
|
|
'name': 'Test nested create 1',
|
|
'childs': [('create', [{
|
|
'name': 'Test nested create 1 1',
|
|
}])],
|
|
}])
|
|
self.check_tree()
|
|
|
|
|
|
def suite():
|
|
return unittest.TestLoader().loadTestsFromTestCase(MPTTTestCase)
|