Beispiel #1
0
    def test_get_tickets(self):
        for pdata in (
            {'prefix': 'p2', 'name':'product, too', 'description': ''},
            {'prefix': 'p3', 'name':'strike three', 'description': ''},
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [(t['product'], t['id']) for t in
                Product.get_tickets(self.global_env, product.prefix)]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id']) for t in
                Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Beispiel #2
0
 def _do_product_add(self, prefix, owner, name):
     product = Product(self.env)
     product._data.update({'prefix': prefix, 'name': name, 'owner': owner})
     try:
         product.insert()
     except TracError, exc:
         raise AdminCommandError(to_unicode(exc))
Beispiel #3
0
    def test_insert_into_multiple_products(self):
        # UIDs are global, autoincremented
        # IDs are product-scoped, incremented in the SQL translator
        self.env = ProductEnvironment(self.global_env, self.default_product)

        tid = self._insert_ticket('hello kitty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 1)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello kitteh', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 2)
        self.assertEqual(ticket.id, tid)

        p2 = Product(self.global_env)
        p2.prefix = 'p2'
        p2.name = 'product, too'
        p2.owner = 'admin'
        p2.insert()
        self.env = ProductEnvironment(self.global_env, p2)

        tid = self._insert_ticket('hello catty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 3)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello ocelot', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 4)
        self.assertEqual(ticket.id, tid)
Beispiel #4
0
    def test_insert_into_multiple_products(self):
        # UIDs are global, autoincremented
        # IDs are product-scoped, incremented in the SQL translator
        self.env = ProductEnvironment(self.global_env, self.default_product)

        tid = self._insert_ticket('hello kitty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 1)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello kitteh', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 2)
        self.assertEqual(ticket.id, tid)

        p2 = Product(self.global_env)
        p2.prefix = 'p2'
        p2.name = 'product, too'
        p2.owner = 'admin'
        p2.insert()
        self.env = ProductEnvironment(self.global_env, p2)

        tid = self._insert_ticket('hello catty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 3)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello ocelot', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 4)
        self.assertEqual(ticket.id, tid)
Beispiel #5
0
    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {'prefix':'tp2',
                   'name':'test project 2',
                   'description':'a different test project'}
        p3_data = {'prefix':'tp3',
                   'name':'test project 3',
                   'description':'test project'}

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'prefix':'tp3', 'name':'test project 3'}))
        self.assertEqual(1, len(products))
Beispiel #6
0
 def _do_product_add(self, prefix, owner, name):
     product = Product(self.env)
     product._data.update({'prefix':prefix, 'name':name, 'owner':owner})
     try:
         product.insert()
     except TracError, exc:
         raise AdminCommandError(to_unicode(exc))
Beispiel #7
0
 def test_select(self):
     """tests that select can search Products by fields"""
     
     p2_data = {'prefix':'tp2',
                'name':'test project',
                'description':'a different test project'}
     p3_data = {'prefix':'tp3',
                'name':'test project',
                'description':'test project'}
     
     product2 = Product(self.env)
     product2._data.update(p2_data)
     product3 = Product(self.env)
     product3._data.update(p3_data)
     
     product2.insert()
     product3.insert()
     
     products = list(Product.select(self.env, where={'prefix':'tp'}))
     self.assertEqual(1, len(products))
     products = list(Product.select(self.env, where={'name':'test project'}))
     self.assertEqual(3, len(products))
     products = list(Product.select(self.env, where={'prefix':'tp3',
                                                     'name':'test project'}))
     self.assertEqual(1, len(products))
Beispiel #8
0
    def _do_save(self, req, product):
        """common processing for product save events"""
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        prefix = req.args.get('prefix')
        description = req.args.get('description', '')

        owner = req.args.get('owner') or req.authname
        keys = {'prefix': prefix}
        field_data = {'name': name,
                      'description': description,
                      'owner': owner,
                      }

        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        if product._exists:
            if name != product.name and Product.select(self.env,
                                                       where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))
            elif not name:
                warn(_('You must provide a name for the product.'))
            else:
                req.perm.require('PRODUCT_MODIFY')
                product.update_field_dict(field_data)
                product.update(req.authname)
                add_notice(req, _('Your changes have been saved.'))
        else:
            req.perm.require('PRODUCT_CREATE')

            if not prefix:
                warn(_('You must provide a prefix for the product.'))
            elif Product.select(self.env, where={'prefix': prefix}):
                warn(_('Product "%(id)s" already exists, please choose another '
                       'prefix.', id=prefix))
            if not name:
                warn(_('You must provide a name for the product.'))
            elif Product.select(self.env, where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))

            if not warnings:
                prod = Product(self.env)
                prod.update_field_dict(keys)
                prod.update_field_dict(field_data)
                prod.insert()
                add_notice(req, _('The product "%(id)s" has been added.',
                                  id=prefix))

        if warnings:
            product.update_field_dict(keys)
            product.update_field_dict(field_data)
            return self._render_editor(req, product)
        req.redirect(req.href.products(prefix))
Beispiel #9
0
 def _load_product_from_data(cls, env, prefix):
     r"""Ensure test product with prefix is loaded
     """
     # TODO: Use fixtures implemented in #314
     product_data = cls.PRODUCT_DATA[prefix]
     prefix = to_unicode(prefix)
     product = Product(env)
     product._data.update(product_data)
     product.insert()
Beispiel #10
0
 def _load_product_from_data(cls, env, prefix):
     r"""Ensure test product with prefix is loaded
     """
     # TODO: Use fixtures implemented in #314
     product_data = cls.PRODUCT_DATA[prefix]
     prefix = to_unicode(prefix)
     product = Product(env)
     product._data.update(product_data)
     product.insert()
Beispiel #11
0
    def test_insert(self):
        """test saving new Product"""
        data = {'prefix':'new', 'name':'new', 'description':'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))
Beispiel #12
0
 def test_insert(self):
     """test saving new Product"""
     data = {'prefix':'new', 'name':'new', 'description':'new'}
     product = Product(self.env)
     product._data.update(data)
     product.insert()
     
     check_products = list(Product.select(self.env, where={'prefix':'new'}))
     
     self.assertEqual(product._data['prefix'],
                      check_products[0]._data['prefix'])
     self.assertEqual(1, len(check_products))
Beispiel #13
0
 def setUp(self):
     self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
     self.env.path = tempfile.mkdtemp('bh-product-tempenv')
     
     self.envprovider = MultiProductEnvironmentProvider(self.env)
     try:
         self.envprovider.upgrade_environment(self.env.db_transaction)
     except OperationalError:
         # table remains but database version is deleted
         pass
     
     self.default_data = {'prefix':'tp',
                          'name':'test project',
                          'description':'a test project'}
     
     product = Product(self.env)
     product._data.update(self.default_data)
     product.insert()
Beispiel #14
0
    def test_new_product_perm(self):
        """Only product owner and TRAC_ADMIN will access new product
        """
        newproduct = Product(self.global_env)
        newproduct.prefix = 'NEW'
        newproduct.name = 'New product'
        newproduct.owner = 'owneruser'
        newproduct.insert()

        env = ProductEnvironment(self.global_env, newproduct)
        self.global_perm_admin._do_add('adminuser', 'TRAC_ADMIN')
        admin_perm = perm.PermissionCache(env, 'adminuser')
        owner_perm = perm.PermissionCache(env, 'owneruser')
        user_perm = perm.PermissionCache(env, 'testuser')
        global_permsys = perm.PermissionSystem(self.global_env)
        permsys = perm.PermissionSystem(env)

        self.assertEquals({'EMAIL_VIEW': True, 'TEST_ADMIN': True,
                           'TEST_CREATE': True, 'TEST_DELETE': True,
                           'TEST_MODIFY': True, 'TRAC_ADMIN' : True},
                          global_permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, global_permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, global_permsys.get_user_permissions('testuser'))
        self.assertEquals({}, permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, permsys.get_user_permissions('testuser'))

        all_actions = self.permsys.get_actions()
        all_actions.remove('TRAC_ADMIN')
        for action in all_actions:
            self.assertTrue(admin_perm.has_permission(action))
            self.assertTrue(owner_perm.has_permission(action))
            self.assertFalse(user_perm.has_permission(action))

        self.assertTrue(admin_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(owner_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(user_perm.has_permission('TRAC_ADMIN'))
Beispiel #15
0
    def test_new_product_perm(self):
        """Only product owner and TRAC_ADMIN will access new product
        """
        newproduct = Product(self.global_env)
        newproduct.prefix = 'NEW'
        newproduct.name = 'New product'
        newproduct.owner = 'owneruser'
        newproduct.insert()

        env = ProductEnvironment(self.global_env, newproduct)
        self.global_perm_admin._do_add('adminuser', 'TRAC_ADMIN')
        admin_perm = perm.PermissionCache(env, 'adminuser')
        owner_perm = perm.PermissionCache(env, 'owneruser')
        user_perm = perm.PermissionCache(env, 'testuser')
        global_permsys = perm.PermissionSystem(self.global_env)
        permsys = perm.PermissionSystem(env)

        self.assertEquals({'EMAIL_VIEW': True, 'TEST_ADMIN': True,
                           'TEST_CREATE': True, 'TEST_DELETE': True,
                           'TEST_MODIFY': True, 'TRAC_ADMIN' : True},
                          global_permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, global_permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, global_permsys.get_user_permissions('testuser'))
        self.assertEquals({}, permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, permsys.get_user_permissions('testuser'))

        all_actions = self.permsys.get_actions()
        all_actions.remove('TRAC_ADMIN')
        for action in all_actions:
            self.assertTrue(admin_perm.has_permission(action))
            self.assertTrue(owner_perm.has_permission(action))
            self.assertFalse(user_perm.has_permission(action))

        self.assertTrue(admin_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(owner_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(user_perm.has_permission('TRAC_ADMIN'))
Beispiel #16
0
    def test_get_tickets(self):
        for pdata in (
            {
                'prefix': 'p2',
                'name': 'product, too',
                'description': ''
            },
            {
                'prefix': 'p3',
                'name': 'strike three',
                'description': ''
            },
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [
                (t['product'], t['id'])
                for t in Product.get_tickets(self.global_env, product.prefix)
            ]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id'])
                                    for t in Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Beispiel #17
0
class ProductTestCase(unittest.TestCase):
    """Unit tests covering the Product model"""
    INITIAL_PREFIX = 'tp'
    INITIAL_NAME = 'test project'
    INITIAL_DESCRIPTION = 'a test project'

    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
        self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')

        self.mpsystem = MultiProductSystem(self.env)
        try:
            self.mpsystem.upgrade_environment(self.env.db_transaction)
        except self.env.db_exc.OperationalError:
            # table remains but database version is deleted
            pass

        self.listener = self._enable_resource_change_listener()
        self.default_data = {'prefix':self.INITIAL_PREFIX,
                             'name':self.INITIAL_NAME,
                             'description':self.INITIAL_DESCRIPTION}

        self.global_env = self.env
        self.product = Product(self.env)
        self.product._data.update(self.default_data)
        self.product.insert()

    def tearDown(self):
        shutil.rmtree(self.env.path)
        self.env.reset_db()

    def _enable_resource_change_listener(self):
        listener = TestResourceChangeListener(self.env)
        listener.resource_type = Product
        listener.callback = self.listener_callback
        return listener

    def listener_callback(self, action, resource, context, old_values = None):
        # pylint: disable=unused-argument
        # pylint: disable=attribute-defined-outside-init
        self.prefix = resource.prefix
        self.name = resource.name
        self.description = resource.description

    def test_set_table_field(self):
        """tests that table.field style update works"""
        test = {'prefix': 'td',
                'name': 'test field access',
                'description': 'product to test field setting'}

        product = Product(self.env)

        # attempt to set the fields from the data
        product.prefix = test['prefix']
        product.name = test['name']
        product.description = test['description']

        self.assertEqual(product._data['prefix'], test['prefix'])
        self.assertEqual(product._data['name'], test['name'])
        self.assertEqual(product._data['description'], test['description'])

    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {'prefix':'tp2',
                   'name':'test project 2',
                   'description':'a different test project'}
        p3_data = {'prefix':'tp3',
                   'name':'test project 3',
                   'description':'test project'}

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'prefix':'tp3', 'name':'test project 3'}))
        self.assertEqual(1, len(products))

    def test_update(self):
        """tests that we can use update to push data to the database"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('test project', product._data['name'])

        new_data = {'prefix':'tp',
                    'name':'updated',
                    'description':'nothing'}
        product._data.update(new_data)
        product.update()

        comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('updated', comp_product._data['name'])

    def test_update_key_change(self):
        """tests that we raise an error for attempting to update key fields"""
        bad_data = {'prefix':'tp0',
                    'name':'update',
                    'description':'nothing'}
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product._data.update(bad_data)
        self.assertRaises(TracError, product.update)

    def test_insert(self):
        """test saving new Product"""
        data = {'prefix':'new', 'name':'new', 'description':'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))

    def test_insert_duplicate_key(self):
        """test attempted saving of Product with existing key fails"""
        dupe_key_data = {'prefix':'tp',
                         'name':'dupe',
                         'description':'dupe primary key'}
        product2 = Product(self.env)
        product2._data.update(dupe_key_data)
        self.assertRaises(TracError, product2.insert)

    def test_delete(self):
        """test that we are able to delete Products"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        post = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(0, len(post))

    def test_delete_twice(self):
        """test that we error when deleting twice on the same key"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        self.assertRaises(TracError, product.delete)

    def test_field_data_get(self):
        """tests that we can use table.field syntax to get to the field data"""
        prefix = self.default_data['prefix']
        name = self.default_data['name']
        description = self.default_data['description']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]
        self.assertEqual(prefix, product.prefix)
        self.assertEqual(name, product.name)
        self.assertEqual(description, product.description)

    def test_field_set(self):
        """tests that we can use table.field = something to set field data"""
        prefix = self.default_data['prefix']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]

        new_description = 'test change of description'
        product.description = new_description
        self.assertEqual(new_description, product.description)

    def test_missing_unique_fields(self):
        """ensure that that insert method works when _meta does not specify
        unique fields when inserting more than one ProductResourceMap instances
        """
        class TestModel(ModelBase):
            """A test model with no unique_fields"""
            _meta = {'table_name': 'bloodhound_testmodel',
                     'object_name': 'TestModelObject',
                     'key_fields': ['id',],
                     'non_key_fields': ['value'],
                     'unique_fields': [],}

        from trac.db import DatabaseManager
        schema = [TestModel._get_schema(), ]
        with self.env.db_transaction as db:
            db_connector, dummy = DatabaseManager(self.env)._get_connector()
            for table in schema:
                for statement in db_connector.to_sql(table):
                    db(statement)

        structure =  dict([(table.name, [col.name for col in table.columns])
                           for table in schema])
        tm1 = TestModel(self.env)
        tm1._data.update({'id':1, 'value':'value1'})
        tm1.insert()
        tm2 = TestModel(self.env)
        tm2._data.update({'id':2, 'value':'value2'})
        tm2.insert()

    def test_change_listener_created(self):
        self.assertEqual('created', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)
        self.assertEqual(self.INITIAL_NAME, self.name)
        self.assertEqual(self.INITIAL_DESCRIPTION, self.description)

    def test_change_listener_changed(self):
        CHANGED_NAME = "changed name"
        self.product.name = CHANGED_NAME
        self.product.update()
        self.assertEqual('changed', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(CHANGED_NAME, self.name)
        self.assertEqual({"name":self.INITIAL_NAME}, self.listener.old_values)

    def test_change_listener_deleted(self):
        self.product.delete()
        self.assertEqual('deleted', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)

    def test_get_tickets(self):
        for pdata in (
            {'prefix': 'p2', 'name':'product, too', 'description': ''},
            {'prefix': 'p3', 'name':'strike three', 'description': ''},
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [(t['product'], t['id']) for t in
                Product.get_tickets(self.global_env, product.prefix)]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id']) for t in
                Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Beispiel #18
0
    def _render_admin_panel(self, req, cat, page, product):
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        description = req.args.get('description', '')
        prefix = req.args.get('prefix') if product is None else product
        owner = req.args.get('owner')
        keys = {'prefix': prefix}
        field_data = {
            'name': name,
            'description': description,
            'owner': owner,
        }

        # Detail view?
        if product:
            prod = Product(self.env, keys)
            if req.method == 'POST':
                if req.args.get('save'):
                    req.perm.require('PRODUCT_MODIFY')
                    prod.update_field_dict(field_data)
                    prod.update()
                    add_notice(req, _('Your changes have been saved.'))
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('cancel'):
                    req.redirect(req.href.admin(cat, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'product': prod}
        else:
            default = self.config.get('ticket', 'default_product')
            if req.method == 'POST':
                # Add Product
                if req.args.get('add') and req.args.get('prefix'):
                    req.perm.require('PRODUCT_CREATE')
                    if not owner:
                        add_warning(req, _('All fields are required!'))
                        req.redirect(req.href.admin(cat, page))

                    try:
                        prod = Product(self.env, keys)
                    except ResourceNotFound:
                        prod = Product(self.env)
                        prod.update_field_dict(keys)
                        prod.update_field_dict(field_data)
                        prod.insert()
                        add_notice(
                            req,
                            _('The product "%(id)s" has been added.',
                              id=prefix))
                        req.redirect(req.href.admin(cat, page))
                    else:
                        if prod.prefix is None:
                            raise TracError(_('Invalid product id.'))
                        raise TracError(
                            _("Product %(id)s already exists.", id=prefix))

                # Remove product
                elif req.args.get('remove'):
                    raise TracError(_('Product removal is not allowed!'))

                # Set default product
                elif req.args.get('apply'):
                    prefix = req.args.get('default')
                    if prefix and prefix != default:
                        self.log.info("Setting default product to %s", prefix)
                        self.config.set('ticket', 'default_product', prefix)
                        _save_config(self.config, req, self.log)
                        req.redirect(req.href.admin(cat, page))

            products = Product.select(self.env)
            data = {'view': 'list', 'products': products, 'default': default}
        if self.config.getbool('ticket', 'restrict_owner'):
            perm = PermissionSystem(self.env)

            def valid_owner(username):
                return perm.get_user_permissions(username).get('TICKET_MODIFY')

            data['owners'] = [
                username
                for username, name, email in self.env.get_known_users()
                if valid_owner(username)
            ]
            data['owners'].insert(0, '')
            data['owners'].sort()
        else:
            data['owners'] = None
        return 'admin_products.html', data
Beispiel #19
0
class ProductTestCase(unittest.TestCase):
    """Unit tests covering the Product model"""
    INITIAL_PREFIX = 'tp'
    INITIAL_NAME = 'test project'
    INITIAL_DESCRIPTION = 'a test project'

    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
        self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')

        self.mpsystem = MultiProductSystem(self.env)
        try:
            self.mpsystem.upgrade_environment(self.env.db_transaction)
        except self.env.db_exc.OperationalError:
            # table remains but database version is deleted
            pass

        self.listener = self._enable_resource_change_listener()
        self.default_data = {
            'prefix': self.INITIAL_PREFIX,
            'name': self.INITIAL_NAME,
            'description': self.INITIAL_DESCRIPTION
        }

        self.global_env = self.env
        self.product = Product(self.env)
        self.product._data.update(self.default_data)
        self.product.insert()

    def tearDown(self):
        shutil.rmtree(self.env.path)
        self.env.reset_db()

    def _enable_resource_change_listener(self):
        listener = TestResourceChangeListener(self.env)
        listener.resource_type = Product
        listener.callback = self.listener_callback
        return listener

    def listener_callback(self, action, resource, context, old_values=None):
        # pylint: disable=unused-argument
        # pylint: disable=attribute-defined-outside-init
        self.prefix = resource.prefix
        self.name = resource.name
        self.description = resource.description

    def test_set_table_field(self):
        """tests that table.field style update works"""
        test = {
            'prefix': 'td',
            'name': 'test field access',
            'description': 'product to test field setting'
        }

        product = Product(self.env)

        # attempt to set the fields from the data
        product.prefix = test['prefix']
        product.name = test['name']
        product.description = test['description']

        self.assertEqual(product._data['prefix'], test['prefix'])
        self.assertEqual(product._data['name'], test['name'])
        self.assertEqual(product._data['description'], test['description'])

    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {
            'prefix': 'tp2',
            'name': 'test project 2',
            'description': 'a different test project'
        }
        p3_data = {
            'prefix': 'tp3',
            'name': 'test project 3',
            'description': 'test project'
        }

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix': 'tp'}))
        self.assertEqual(1, len(products))
        products = list(
            Product.select(self.env, where={'name': 'test project'}))
        self.assertEqual(1, len(products))
        products = list(
            Product.select(self.env,
                           where={
                               'prefix': 'tp3',
                               'name': 'test project 3'
                           }))
        self.assertEqual(1, len(products))

    def test_update(self):
        """tests that we can use update to push data to the database"""
        product = list(Product.select(self.env, where={'prefix': 'tp'}))[0]
        self.assertEqual('test project', product._data['name'])

        new_data = {
            'prefix': 'tp',
            'name': 'updated',
            'description': 'nothing'
        }
        product._data.update(new_data)
        product.update()

        comp_product = list(Product.select(self.env, where={'prefix':
                                                            'tp'}))[0]
        self.assertEqual('updated', comp_product._data['name'])

    def test_update_key_change(self):
        """tests that we raise an error for attempting to update key fields"""
        bad_data = {
            'prefix': 'tp0',
            'name': 'update',
            'description': 'nothing'
        }
        product = list(Product.select(self.env, where={'prefix': 'tp'}))[0]
        product._data.update(bad_data)
        self.assertRaises(TracError, product.update)

    def test_insert(self):
        """test saving new Product"""
        data = {'prefix': 'new', 'name': 'new', 'description': 'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':
                                                              'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))

    def test_insert_duplicate_key(self):
        """test attempted saving of Product with existing key fails"""
        dupe_key_data = {
            'prefix': 'tp',
            'name': 'dupe',
            'description': 'dupe primary key'
        }
        product2 = Product(self.env)
        product2._data.update(dupe_key_data)
        self.assertRaises(TracError, product2.insert)

    def test_delete(self):
        """test that we are able to delete Products"""
        product = list(Product.select(self.env, where={'prefix': 'tp'}))[0]
        product.delete()

        post = list(Product.select(self.env, where={'prefix': 'tp'}))
        self.assertEqual(0, len(post))

    def test_delete_twice(self):
        """test that we error when deleting twice on the same key"""
        product = list(Product.select(self.env, where={'prefix': 'tp'}))[0]
        product.delete()

        self.assertRaises(TracError, product.delete)

    def test_field_data_get(self):
        """tests that we can use table.field syntax to get to the field data"""
        prefix = self.default_data['prefix']
        name = self.default_data['name']
        description = self.default_data['description']
        product = list(Product.select(self.env, where={'prefix': prefix}))[0]
        self.assertEqual(prefix, product.prefix)
        self.assertEqual(name, product.name)
        self.assertEqual(description, product.description)

    def test_field_set(self):
        """tests that we can use table.field = something to set field data"""
        prefix = self.default_data['prefix']
        product = list(Product.select(self.env, where={'prefix': prefix}))[0]

        new_description = 'test change of description'
        product.description = new_description
        self.assertEqual(new_description, product.description)

    def test_missing_unique_fields(self):
        """ensure that that insert method works when _meta does not specify
        unique fields when inserting more than one ProductResourceMap instances
        """
        class TestModel(ModelBase):
            """A test model with no unique_fields"""
            _meta = {
                'table_name': 'bloodhound_testmodel',
                'object_name': 'TestModelObject',
                'key_fields': [
                    'id',
                ],
                'non_key_fields': ['value'],
                'unique_fields': [],
            }

        from trac.db import DatabaseManager
        schema = [
            TestModel._get_schema(),
        ]
        with self.env.db_transaction as db:
            db_connector, dummy = DatabaseManager(self.env)._get_connector()
            for table in schema:
                for statement in db_connector.to_sql(table):
                    db(statement)

        structure = dict([(table.name, [col.name for col in table.columns])
                          for table in schema])
        tm1 = TestModel(self.env)
        tm1._data.update({'id': 1, 'value': 'value1'})
        tm1.insert()
        tm2 = TestModel(self.env)
        tm2._data.update({'id': 2, 'value': 'value2'})
        tm2.insert()

    def test_change_listener_created(self):
        self.assertEqual('created', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)
        self.assertEqual(self.INITIAL_NAME, self.name)
        self.assertEqual(self.INITIAL_DESCRIPTION, self.description)

    def test_change_listener_changed(self):
        CHANGED_NAME = "changed name"
        self.product.name = CHANGED_NAME
        self.product.update()
        self.assertEqual('changed', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(CHANGED_NAME, self.name)
        self.assertEqual({"name": self.INITIAL_NAME}, self.listener.old_values)

    def test_change_listener_deleted(self):
        self.product.delete()
        self.assertEqual('deleted', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)

    def test_get_tickets(self):
        for pdata in (
            {
                'prefix': 'p2',
                'name': 'product, too',
                'description': ''
            },
            {
                'prefix': 'p3',
                'name': 'strike three',
                'description': ''
            },
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [
                (t['product'], t['id'])
                for t in Product.get_tickets(self.global_env, product.prefix)
            ]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id'])
                                    for t in Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Beispiel #20
0
    def _render_admin_panel(self, req, cat, page, product):
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        description = req.args.get('description','')
        prefix = req.args.get('prefix') if product is None else product
        owner = req.args.get('owner')
        keys = {'prefix':prefix}
        field_data = {'name':name,
                      'description':description,
                      'owner':owner,
                      }
        data = {}

        # Detail view?
        if product:
            prod = Product(self.env, keys)
            if req.method == 'POST':
                if req.args.get('save'):
                    req.perm.require('PRODUCT_MODIFY')
                    prod.update_field_dict(field_data)
                    prod.update(req.authname)
                    add_notice(req, _('Your changes have been saved.'))
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('cancel'):
                    req.redirect(req.href.admin(cat, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'product': prod}
        else:
            default = self.config.get('ticket', 'default_product')
            if req.method == 'POST':
                # Add Product
                if req.args.get('add'):
                    req.perm.require('PRODUCT_CREATE')
                    if not (prefix and name and owner):
                        if not prefix:
                            add_warning(req, _("You must provide a prefix "
                                               "for the product."))
                        if not name:
                            add_warning(req, _("You must provide a name "
                                               "for the product."))
                        if not owner:
                            add_warning(req, _("You must provide an owner "
                                               "for the product."))
                        data['prefix'] = prefix
                        data['name'] = name
                        data['owner'] = owner
                    else:
                        try:
                            prod = Product(self.env, keys)
                        except ResourceNotFound:
                            prod = Product(self.env)
                            prod.update_field_dict(keys)
                            prod.update_field_dict(field_data)
                            prod.insert()
                            add_notice(req, _('The product "%(id)s" has been '
                                              'added.', id=prefix))
                            req.redirect(req.href.admin(cat, page))
                        else:
                            if prod.prefix is None:
                                raise TracError(_('Invalid product id.'))
                            raise TracError(_("Product %(id)s already exists.",
                                              id=prefix))

                # Remove product
                elif req.args.get('remove'):
                    raise TracError(_('Product removal is not allowed!'))

                # Set default product
                elif req.args.get('apply'):
                    prefix = req.args.get('default')
                    if prefix and prefix != default:
                        self.log.info("Setting default product to %s",
                                      prefix)
                        self.config.set('ticket', 'default_product',
                                        prefix)
                        _save_config(self.config, req, self.log)
                        req.redirect(req.href.admin(cat, page))

                # Clear default product
                elif req.args.get('clear'):
                    self.log.info("Clearing default product")
                    self.config.set('ticket', 'default_product', '')
                    _save_config(self.config, req, self.log)
                    req.redirect(req.href.admin(cat, page))

            data['view'] = 'list'
            data['products'] = Product.select(self.env)
            data['default'] = default
        if self.config.getbool('ticket', 'restrict_owner'):
            perm = PermissionSystem(self.env)
            def valid_owner(username):
                return perm.get_user_permissions(username).get('TICKET_MODIFY')
            data['owners'] = [username for username, name, email
                              in self.env.get_known_users()
                              if valid_owner(username)]
            data['owners'].insert(0, '')
            data['owners'].sort()
        else:
            data['owners'] = None
        return 'admin_products.html', data
Beispiel #21
0
    def _do_save(self, req, product):
        """common processing for product save events"""
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        prefix = req.args.get('prefix')
        description = req.args.get('description', '')

        owner = req.args.get('owner') or req.authname
        keys = {'prefix': prefix}
        field_data = {
            'name': name,
            'description': description,
            'owner': owner,
        }

        warnings = []

        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        if product._exists:
            if name != product.name and Product.select(self.env,
                                                       where={'name': name}):
                warn(
                    _(
                        'A product with name "%(name)s" already exists, please '
                        'choose a different name.',
                        name=name))
            elif not name:
                warn(_('You must provide a name for the product.'))
            else:
                req.perm.require('PRODUCT_MODIFY')
                product.update_field_dict(field_data)
                product.update(req.authname)
                add_notice(req, _('Your changes have been saved.'))
        else:
            req.perm.require('PRODUCT_CREATE')

            if not prefix:
                warn(_('You must provide a prefix for the product.'))
            elif Product.select(self.env, where={'prefix': prefix}):
                warn(
                    _(
                        'Product "%(id)s" already exists, please choose another '
                        'prefix.',
                        id=prefix))
            if not name:
                warn(_('You must provide a name for the product.'))
            elif Product.select(self.env, where={'name': name}):
                warn(
                    _(
                        'A product with name "%(name)s" already exists, please '
                        'choose a different name.',
                        name=name))

            if not warnings:
                prod = Product(self.env)
                prod.update_field_dict(keys)
                prod.update_field_dict(field_data)
                prod.insert()
                add_notice(
                    req, _('The product "%(id)s" has been added.', id=prefix))

        if warnings:
            product.update_field_dict(keys)
            product.update_field_dict(field_data)
            return self._render_editor(req, product)
        req.redirect(req.href.products(prefix))