Commits

seccanj committed 8955ec6

Release 1.5.1 (2012-08-12): See README.txt for details.

Comments (0)

Files changed (61)

 Test Manager plugin for Trac
 
-  Copyright 2010-2011 Roberto Bordolanghi
+  Copyright 2010-2011 Roberto Longobardi
   
   The Test Manager plugin for Trac is free software: you can 
   redistribute it and/or modify it under the terms of the GNU General 
 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.5.1 (2012-08-12):
+
+  This is somewhat of a major release, in that it includes several new interesting features and many bug fixes.
+  See the list below for more details.
+  
+  In addition to that, I realized a VIDEO TUTORIAL showing out the main features of this Test Manager, to 
+  help new and existing users take confidence with recent changes, new features and so on.
+  
+  Check the tutorial on YouTube: http://www.youtube.com/watch?v=BIi3QMT0rT4 
+  
+  Also the trac-hacks user manual has been restructured, updated and enriched with the recent changes and features.
+
+  o Enhancement #353771 (SourceForge): Time tracking capability. 
+                                       
+                                       This is now possible by means of the enhancements to the tabular views of
+                                       both test catalogs and test plans and the addition of a custom field.
+                                       See the comments to the feature request and the video tutorial, where this
+                                       customization example is fully explored.
+
+  o Enhancement #3537704 (SourceForge): Possibility to select columns for the table view. 
+                                        
+                                        This is now possible from the administration panel.
+                                        
+                                        I also added an interesting feature that allows for adding a statistical
+                                        row to the test catalog and test plan tabular views, with the option to have
+                                        the sum, average or count of the values in any column, being it a standard
+                                        or a custom property of test cases or catalogs.
+                                        
+                                        This feature is also used to realize the feature #353771 above.
+                                        See the video tutorial for an interesting use of this one to track test
+                                        execution effort estimation of an entire test plan  and compare it to actual 
+                                        execution time.
+                                       
+  o Enhancement #3537700 (SourceForge): Option to select table view as default view. 
+                                        This is now possible from the administration panel.
+                                   
+  o Enhancement #3537696 (SourceForge): Possibility to change test plans. 
+                                        
+                                        This is now possible by means of several new actions available on test cases:
+                                         - On a test case definition page, you have a new action button to add the 
+                                           test case to a plan. A dialog box appears showing you the suitable plans 
+                                           (the ones not containing all test cases).
+                                         - On a test case instance (a test case inside a plan) page, you have a new 
+                                           action button to remove the test case from the plan.
+                                         - On a test case instance (a test case inside a plan) page, in case the plan
+                                           is containing an old snapshot of the test case and you wish to update its text 
+                                           description to the latest version, you have a new action button to do that.
+                                       
+  o Fixed Ticket #8932 (Track-Hacks): The test plan tabular view has been enhanced to also 
+                                      show test case full text description
+
+  o Fixed Ticket #10131 and #10217 (Track-Hacks): Deleting a Test Case, deleting Test Catalogs containing Test items.
+                                                  This only happened on PosgreSQL.
+
+  o Fixed some bugs that I found ad which were not reported:
+    - The quick search in test catalogs was not working.
+    - Indentation of test cases in tabular views for both catalogs and plans was incorrect.
+    - Localization (i.e. translation) did not work for some parts of the Administration panel, 
+      the Statistical charts page and several dialog boxes.
+    - Some more I can't recall :D
+
 Release 1.4.11 (2012-06-03):
 
   The data referential integrity in case of test catalog, test case and test plan deletion has been enhanced.

sqlexecutor/trunk/setup.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 
     version='1.0.6',
     packages=['sqlexecutor'],
     package_data={'sqlexecutor' : ['*.txt', 'templates/*.html', 'htdocs/*.*', 'htdocs/js/*.js', 'htdocs/css/*.css', 'htdocs/images/*.*']},
-    author = 'Roberto Bordolanghi',
-    author_email='seccanj@gmail.com',
-    license='BSD. See the file LICENSE.txt contained in the package.',
+    author = 'Roberto Longobardi',
+    author_email='otrebor.dev@gmail.com',
+    license='GPL v. 3. See the file LICENSE.txt contained in the package.',
     url='http://trac-hacks.org/wiki/TestManagerForTracPlugin',
     download_url='https://sourceforge.net/projects/testman4trac/files/',
     description='Test management plugin for Trac - SQL Executor component',

sqlexecutor/trunk/sqlexecutor/README.txt

 Trac Generic SQL Executor - Part of the Test Manager plugin for Trac
 
-  Copyright 2010-2011 Roberto Bordolanghi
+  Copyright 2010-2011 Roberto Longobardi
   
   The Test Manager plugin for Trac is free software: you can 
   redistribute it and/or modify it under the terms of the GNU General 

sqlexecutor/trunk/sqlexecutor/__init__.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

sqlexecutor/trunk/sqlexecutor/sql.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

testman4trac/trunk/setup.cfg

 [extract_messages]
 add_comments = TRANSLATOR:
-copyright_holder = Roberto Bordolanghi
-msgid_bugs_address = seccanj@gmail.com
+copyright_holder = Roberto Longobardi
+msgid_bugs_address = otrebor.dev@gmail.com
 output_file = testmanager/locale/messages.pot
 # Note: specify as 'keywords' the functions for which the messages
 #       should be extracted. This should match the list of functions
 
 [extract_messages_js]
 add_comments = TRANSLATOR:
-copyright_holder = Roberto Bordolanghi
-msgid_bugs_address = seccanj@gmail.com
+copyright_holder = Roberto Longobardi
+msgid_bugs_address = otrebor.dev@gmail.com
 output_file = testmanager/locale/messages-js.pot
 keywords = _ N_ tag_
 mapping_file = messages-js.cfg

testman4trac/trunk/setup.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 
 
 setup(
     name='TestManager',
-    version='1.4.11',
+    version='1.5.1',
     packages=['testmanager','testmanager.upgrades'],
     package_data={
         'testmanager' : [
             'htdocs/testmanager/*.js'
         ]
     },
-    author = 'Roberto Bordolanghi',
-    author_email='seccanj@gmail.com',
-    license='BSD. See the file LICENSE.txt contained in the package.',
+    author = 'Roberto Longobardi',
+    author_email='otrebor.dev@gmail.com',
+    license='GPL v. 3. See the file LICENSE.txt contained in the package.',
     url='http://trac-hacks.org/wiki/TestManagerForTracPlugin',
     download_url='https://sourceforge.net/projects/testman4trac/files/',
     description='Test management plugin for Trac',

testman4trac/trunk/testmanager/README.txt

 Test Manager plugin for Trac
 
-  Copyright 2010-2011 Roberto Bordolanghi
+  Copyright 2010-2011 Roberto Longobardi
   
   The Test Manager plugin for Trac is free software: you can 
   redistribute it and/or modify it under the terms of the GNU General 
 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.5.1 (2012-08-12):
+
+  This is somewhat of a major release, in that it includes several new interesting features and many bug fixes.
+  See the list below for more details.
+  
+  In addition to that, I realized a VIDEO TUTORIAL showing out the main features of this Test Manager, to 
+  help new and existing users take confidence with recent changes, new features and so on.
+  
+  Check the tutorial on YouTube: http://www.youtube.com/watch?v=BIi3QMT0rT4 
+  
+  Also the trac-hacks user manual has been restructured, updated and enriched with the recent changes and features.
+
+  o Enhancement #353771 (SourceForge): Time tracking capability. 
+                                       
+                                       This is now possible by means of the enhancements to the tabular views of
+                                       both test catalogs and test plans and the addition of a custom field.
+                                       See the comments to the feature request and the video tutorial, where this
+                                       customization example is fully explored.
+
+  o Enhancement #3537704 (SourceForge): Possibility to select columns for the table view. 
+                                        
+                                        This is now possible from the administration panel.
+                                        
+                                        I also added an interesting feature that allows for adding a statistical
+                                        row to the test catalog and test plan tabular views, with the option to have
+                                        the sum, average or count of the values in any column, being it a standard
+                                        or a custom property of test cases or catalogs.
+                                        
+                                        This feature is also used to realize the feature #353771 above.
+                                        See the video tutorial for an interesting use of this one to track test
+                                        execution effort estimation of an entire test plan  and compare it to actual 
+                                        execution time.
+                                       
+  o Enhancement #3537700 (SourceForge): Option to select table view as default view. 
+                                        This is now possible from the administration panel.
+                                   
+  o Enhancement #3537696 (SourceForge): Possibility to change test plans. 
+                                        
+                                        This is now possible by means of several new actions available on test cases:
+                                         - On a test case definition page, you have a new action button to add the 
+                                           test case to a plan. A dialog box appears showing you the suitable plans 
+                                           (the ones not containing all test cases).
+                                         - On a test case instance (a test case inside a plan) page, you have a new 
+                                           action button to remove the test case from the plan.
+                                         - On a test case instance (a test case inside a plan) page, in case the plan
+                                           is containing an old snapshot of the test case and you wish to update its text 
+                                           description to the latest version, you have a new action button to do that.
+                                       
+  o Fixed Ticket #8932 (Track-Hacks): The test plan tabular view has been enhanced to also 
+                                      show test case full text description
+
+  o Fixed Ticket #10131 and #10217 (Track-Hacks): Deleting a Test Case, deleting Test Catalogs containing Test items.
+                                                  This only happened on PosgreSQL.
+
+  o Fixed some bugs that I found ad which were not reported:
+    - The quick search in test catalogs was not working.
+    - Indentation of test cases in tabular views for both catalogs and plans was incorrect.
+    - Localization (i.e. translation) did not work for some parts of the Administration panel, 
+      the Statistical charts page and several dialog boxes.
+    - Some more I can't recall :D
+
 Release 1.4.11 (2012-06-03):
 
   The data referential integrity in case of test catalog, test case and test plan deletion has been enhanced.

testman4trac/trunk/testmanager/__init__.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

testman4trac/trunk/testmanager/admin.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (c) 2011 Christian Masopust and Roberto Bordolanghi. 
+# Copyright (c) 2011 Christian Masopust and Roberto Longobardi. 
 # All rights reserved.
 # 
 # This file is part of the Test Manager plugin for Trac.
 from trac.wiki.formatter import format_to_html
 from trac.mimeview.api import Context
 
+from tracgenericclass.model import GenericClassModelProvider
+
 from testmanager.api import *
 from tracgenericclass.util import *
 from testmanager.util import *
 
         try:
             if req.method == 'POST':
-                default_days_back = req.args.get('default_days_back')
-                default_interval = req.args.get('default_interval')
-                testplan_sortby = req.args.get('testplan_sortby')
-                open_new_window = req.args.get('open_new_window')
+                default_days_back = req.args.get('default_days_back', '90')
+                default_interval = req.args.get('default_interval', '7')
+                testplan_sortby = req.args.get('testplan_sortby', 'name')
+                open_new_window = req.args.get('open_new_window', 'False')
+                testcatalog_default_view = req.args.get('testcatalog_default_view', 'tree')
+                testplan_default_view = req.args.get('testplan_default_view', 'tree')
 
                 self.env.config.set('testmanager', 'default_days_back', default_days_back)
                 self.env.config.set('testmanager', 'default_interval', default_interval)
                 self.env.config.set('testmanager', 'testplan.sortby', testplan_sortby)
-                self.env.config.set('testmanager', 'testcase.open_new_window', ("False", "True")[open_new_window == "on"])
+                self.env.config.set('testmanager', 'testcase.open_new_window', ('False', 'True')[open_new_window == 'on'])
+                self.env.config.set('testmanager', 'testcatalog.default_view', testcatalog_default_view)
+                self.env.config.set('testmanager', 'testplan.default_view', testplan_default_view)
 
+                _set_columns_visible(self.env, 'testcatalog', req.args, self.env.config)
+                _set_columns_visible(self.env, 'testplan', req.args, self.env.config)
+                
+                _set_columns_total_operation(self.env, 'testcatalog', req.args, self.env.config)
+                _set_columns_total_operation(self.env, 'testplan', req.args, self.env.config)
+                
                 self.env.config.save()
                 add_notice(req, _("Settings saved"))
         except:
             self.env.log.error(formatExceptionInfo())
             add_warning(req, _("Error saving the settings"))
 
-        data['default_days_back'] = self.env.config.get('testmanager', 'default_days_back')
-        data['default_interval'] = self.env.config.get('testmanager', 'default_interval')
-        data['testplan_sortby'] = self.env.config.get('testmanager', 'testplan.sortby')
-        data['open_new_window'] = self.env.config.get('testmanager', 'testcase.open_new_window')
-
+        data['default_days_back'] = self.env.config.get('testmanager', 'default_days_back', '90')
+        data['default_interval'] = self.env.config.get('testmanager', 'default_interval', '7')
+        data['testplan_sortby'] = self.env.config.get('testmanager', 'testplan.sortby', 'name')
+        data['open_new_window'] = self.env.config.get('testmanager', 'testcase.open_new_window', 'False')
+        data['testcatalog_default_view'] = self.env.config.get('testmanager', 'testcatalog.default_view', 'tree')
+        data['testplan_default_view'] = self.env.config.get('testmanager', 'testplan.default_view', 'tree')
+        
+        testcatalog_columns, foo, bar = get_all_table_columns_for_object(self.env, 'testcatalog', self.env.config)
+        testplan_columns, foo, bar = get_all_table_columns_for_object(self.env, 'testplan', self.env.config)
+        
+        data['testcatalog_columns'] = testcatalog_columns
+        data['testplan_columns'] = testplan_columns
+        
         return 'admin_settings.html', data
 
     def _render_templates(self, req, cat, page, component):
         add_stylesheet(req, 'common/css/wiki.css')
         add_stylesheet(req, 'testmanager/css/admin.css')
         return 'admin_templates.html', data
+
+        
+def get_all_table_columns_for_object(env, objtype, settings):
+    genericClassModelProvider = GenericClassModelProvider(env)
+    
+    tcat_fields = genericClassModelProvider.get_custom_fields_for_realm('testcatalog')
+    tcat_has_custom = tcat_fields is not None and len(tcat_fields) > 0
+    
+    tc_fields = genericClassModelProvider.get_custom_fields_for_realm('testcase')
+    tc_has_custom = tc_fields is not None and len(tc_fields) > 0
+
+    if objtype == 'testplan':
+        tcip_fields = genericClassModelProvider.get_custom_fields_for_realm('testcaseinplan')
+        tcip_has_custom = tcip_fields is not None and len(tcip_fields) > 0
+    else:
+        tcip_fields = False
+        tcip_has_custom = None
+
+    custom_ctx = {
+        'testcatalog': [tcat_has_custom, tcat_fields],
+        'testcase': [tc_has_custom, tc_fields],
+        'testcaseinplan': [tcip_has_custom, tcip_fields]
+        }
+   
+    result = []
+    result_map = {}
+    
+    # Common columns
+    result.append({'name': 'title', 'label': _("Name"), 'visible': _is_column_visible(objtype, 'title', settings), 'totals': _get_column_total_operation(objtype, 'title', settings)})
+            
+    # Custom testcatalog columns
+    if tcat_has_custom:
+        for f in tcat_fields:
+            if f['type'] == 'text':
+                result.append(_get_column_settings(objtype, f, settings))
+
+    # Base testcase columns
+    result.append({'name': 'id', 'label': _("ID"), 'visible': _is_column_visible(objtype, 'id', settings), 'totals': _get_column_total_operation(objtype, 'id', settings)})
+
+    # Custom testcase columns
+    if tc_has_custom:
+        for f in tc_fields:
+            if f['type'] == 'text':
+                result.append(_get_column_settings(objtype, f, settings))
+
+    if objtype == 'testplan':
+        # Base testcaseinplan columns
+        result.append({'name': 'status', 'label': _("Status"), 'visible': _is_column_visible(objtype, 'status', settings), 'totals': _get_column_total_operation(objtype, 'status', settings)})
+        result.append({'name': 'author', 'label': _("Author"), 'visible': _is_column_visible(objtype, 'author', settings), 'totals': _get_column_total_operation(objtype, 'author', settings)})
+        result.append({'name': 'time', 'label': _("Last Change"), 'visible': _is_column_visible(objtype, 'time', settings), 'totals': _get_column_total_operation(objtype, 'time', settings)})
+
+        # Custom testcaseinplan columns
+        if tcip_has_custom:
+            for f in tcip_fields:
+                if f['type'] == 'text':
+                    result.append(_get_column_settings(objtype, f, settings))
+
+    # Full test case description
+    result.append({'name': 'description', 'label': _("Description"), 'visible': _is_column_visible(objtype, 'description', settings), 'totals': _get_column_total_operation(objtype, 'description', settings)})
+
+    for r in result:
+        result_map[r['name']] = r
+    
+    return result, result_map, custom_ctx
+    
+def _get_column_settings(objtype, field, settings):
+    return {'name': field['name'], 'label': field['label'], 'visible': _is_column_visible(objtype, field['name'], settings), 'totals': _get_column_total_operation(objtype, field['name'], settings)}
+
+def _is_column_visible(objtype, column_name, settings):
+    visible = settings.get('testmanager', objtype + '.visible_'+column_name)
+    
+    if visible is None or visible == '' or visible == 'True':
+        return 'True'
+    
+    return 'False'
+    
+def _set_columns_visible(env, objtype, args, settings):
+    columns, foo, bar = get_all_table_columns_for_object(env, objtype, settings)
+
+    for column in columns:
+        col_name = objtype + '.' + column['name']
+        if args.get(col_name, '') == 'on':
+            settings.remove('testmanager', objtype + '.visible_'+column['name'])
+        else:
+            settings.set('testmanager', objtype + '.visible_'+column['name'], 'False')
+
+def _get_column_total_operation(objtype, column_name, settings):
+    operation = settings.get('testmanager', objtype + '.totals_'+column_name)
+    
+    if operation is None or operation == '':
+        return None
+    
+    return operation
+    
+def _set_columns_total_operation(env, objtype, args, settings):
+    columns, foo, bar = get_all_table_columns_for_object(env, objtype, settings)
+
+    for column in columns:
+        arg_name = 'totals.' + objtype + '_' + column['name']
+        if args.get(arg_name, 'none') != 'none':
+            settings.set('testmanager', objtype + '.totals_'+column['name'], args.get(arg_name))
+        else:
+            settings.remove('testmanager', objtype + '.totals_'+column['name'])

testman4trac/trunk/testmanager/api.py

 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 
             for outcome in self.outcomes_by_color[color]:
                 self.outcomes_by_name[outcome] = [color, self.outcomes_by_color[color][outcome]]
 
-    def get_next_id(self, type):
-        propname = self.NEXT_PROPERTY_NAME[type]
-    
-        # Get current latest ID for the desired object type
-        latest_id = self.get_config_property(propname)
-        if not latest_id:
-            latest_id = '0'
+    def get_next_id(self, type_):
+        latest_id = -1
+        if type_ in self.NEXT_PROPERTY_NAME:
+            propname = self.NEXT_PROPERTY_NAME[type_]
+        
+            # Get current latest ID for the desired object type
+            latest_id = self.get_config_property(propname)
+            if not latest_id:
+                latest_id = '0'
 
-        # Increment next ID
-        self.set_config_property(propname, str(int(latest_id)+1))
+            # Increment next ID
+            self.set_config_property(propname, str(int(latest_id)+1))
 
         return latest_id
     
             match = True
         
         if req.path_info.startswith('/testcreate') and (((type == 'catalog' or type == 'testcase') and ('TEST_MODIFY' in req.perm)) or 
-             (type == 'testplan' and ('TEST_PLAN_ADMIN' in req.perm))):
+             ((type == 'testplan' or type == 'testcaseinplan') and ('TEST_PLAN_ADMIN' in req.perm))):
             match = True
         elif (req.path_info.startswith('/teststatusupdate') and 'TEST_EXECUTE' in req.perm):
             match = True
-        elif (req.path_info.startswith('/testdelete') and type == 'testplan' and 'TEST_PLAN_ADMIN' in req.perm):
+        elif (req.path_info.startswith('/testdelete') and (type == 'testplan' or type == 'testcaseinplan') and 'TEST_PLAN_ADMIN' in req.perm):
             match = True
         elif (req.path_info.startswith('/testimport') and ('TEST_MODIFY' in req.perm)):
             match = True
                 except:
                     self.env.log.error("Error adding test catalog!")
                     self.env.log.error(formatExceptionInfo())
-                    add_notice(req, _("Error adding test catalog"))
+                    add_warning(req, _("An error occurred while adding the test catalog."))
                     req.redirect(req.href.wiki(path))
 
                 # Redirect to see the new wiki page.
                 
             elif object_type == 'testplan':
                 req.perm.require('TEST_PLAN_ADMIN')
+                is_update = req.args.get('update', 'false')
 
-                contains_all_str = req.args.get('containsAll', 'true')
-                snapshot_str = req.args.get('snapshot', 'false')
-                selected_tcs_str = req.args.get('selectedTCs', '')
+                if is_update == 'true':
+                    planId = req.args.get('planid')
+                    
+                    try:
+                        # Update the version of the test case in plan to 
+                        # the latest wiki page version
+                        pagename = tcId
+                        id = tcId.rpartition('_TC')[2]
+                        tcip = TestCaseInPlan(self.env, id, planId, pagename)
+                        tcip.update_version()
+                        tcip.save_changes(author, "Version updated")
+                        add_notice(req, _("The test case version was updated successfully."))
+                        
+                    except:
+                        self.env.log.error("Error updating the test case version!")
+                        self.env.log.error(formatExceptionInfo())
+                        add_warning(req, _("An error occurred while updating the test case version."))
+                
+                    # Display the updated test case in plan
+                    req.redirect(req.href.wiki(tcId, planid=planId))
+                    
+                else:
+                    contains_all_str = req.args.get('containsAll', 'true')
+                    snapshot_str = req.args.get('snapshot', 'false')
+                    selected_tcs_str = req.args.get('selectedTCs', '')
 
-                contains_all = (0, 1)[contains_all_str == 'true']
-                snapshot = (0, 1)[snapshot_str == 'true']
-                selected_tcs = []
-                if contains_all_str == 'false' and not selected_tcs_str == '':
-                    selected_tcs = selected_tcs_str.split(',')
+                    contains_all = (0, 1)[contains_all_str == 'true']
+                    snapshot = (0, 1)[snapshot_str == 'true']
+                    selected_tcs = []
+                    if contains_all_str == 'false' and not selected_tcs_str == '':
+                        selected_tcs = selected_tcs_str.split(',')
 
-                catid = path.rpartition('_TT')[2]
+                    catid = path.rpartition('_TT')[2]
 
+                    try:
+                        # Add the new test plan in the database
+                        new_tc = TestPlan(self.env, id, catid, pagename, title, author, contains_all, snapshot, selected_tcs)
+                        new_tc.insert()
+
+                    except:
+                        self.env.log.error("Error adding test plan!")
+                        self.env.log.error(formatExceptionInfo())
+                        # Back to the catalog
+                        add_warning(req, _("An error occurred while generating the test plan."))
+                        req.redirect(req.href.wiki(path))
+
+                    # Display the new test plan
+                    req.redirect(req.href.wiki(path, planid=str(id)))
+                    
+            elif object_type == 'testcaseinplan':
+                req.perm.require('TEST_PLAN_ADMIN')
+                
+                tcatId = req.args.get('tcatId')
+                planid = req.args.get('planid')
+                self.env.log.debug("About to add test case %s to test plan %s" % (tcId, planid))
+
+                tp = None
+                tcip = None
+                page_name = None
                 try:
-                    # Add the new test plan in the database
-                    new_tc = TestPlan(self.env, id, catid, pagename, title, author, contains_all, snapshot, selected_tcs)
-                    new_tc.insert()
+                    tc = TestCase(self.env, tcId)
+                    tp = TestPlan(self.env, planid, tcatId)
+                    
+                    page_name = tc['page_name']
 
+                    # Add the test case to the plan, i.e. add a testcaseinplan object
+                    tcip = TestCaseInPlan(self.env, tcId, planid)
+                    if not tcip.exists:
+                        tcip['page_name'] = page_name
+                        if tp['freeze_tc_versions']:
+                            # Set the wiki page version to the current latest version
+                            tcip['page_version'] = tc.wikipage.version
+                        tcip.set_status(self.get_default_tc_status(), author)
+                        tcip.insert()
+                        add_notice(req, _("The Test Case was successfully added to the plan."))
+                    else:
+                        add_warning(req, _("The Test Case was already contained in the specified Test Plan."))
+                    
                 except:
-                    self.env.log.error("Error adding test plan!")
+                    self.env.log.error("Error adding test case to plan!")
                     self.env.log.error(formatExceptionInfo())
-                    # Back to the catalog
-                    req.redirect(req.href.wiki(path))
+                    # Back to the test case
+                    add_warning(req, _("An error occurred while adding the test case into the plan."))
+                    req.redirect(req.href.wiki(page_name))
 
-                # Display the new test plan
-                req.redirect(req.href.wiki(path, planid=str(id)))
-                    
+                # Redirect to test case in plan
+                if tp['freeze_tc_versions']:
+                    req.redirect(req.href.wiki(page_name, planid=planid, version=tcip['page_version']))
+                else:
+                    req.redirect(req.href.wiki(page_name, planid=planid))
+                
             elif object_type == 'testcase':
                 req.perm.require('TEST_MODIFY')
                 
                             # Generate a new Id for the next iteration
                             id = self.get_next_id(object_type)
                             pagename = path + '_TC'+str(id)
-                                    
+
+                        add_notice(req, _("The Test Case(s) were successfully pasted into the catalog."))
+                            
                     except:
                         self.env.log.error("Error pasting test cases!")
                         self.env.log.error(formatExceptionInfo())
+                        add_warning(req, _("An error occurred while pasting the test case(s) into the catalog."))
                         req.redirect(req.href.wiki(pagename))
                 
                     # Redirect to test catalog, forcing a page refresh by means of a random request parameter
                     except:
                         self.env.log.error("Error duplicating test case!")
                         self.env.log.error(formatExceptionInfo())
+                        add_warning(req, _("An error occurred while duplicating the test case."))
                         req.redirect(req.href.wiki(tcId))
 
                     # Redirect tp allow for editing the copy test case
                     except:
                         self.env.log.error("Error adding test case!")
                         self.env.log.error(formatExceptionInfo())
-                        add_notice(req, _("Error adding test case"))
+                        add_warning(req, _("An error occurred while adding the test case."))
                         req.redirect(req.path_info)
 
                     # Redirect to edit the test case description
                 self.env.log.debug("About to delete test plan %s on catalog %s" % (planid, catid))
 
                 try:
-                    # Add the new test plan in the database
+                    # Delete the test plan
                     tp = TestPlan(self.env, planid, catid)
                     tp.delete()
 
+                    add_notice(req, _("The Test Plan was deleted successfully."))
+                    
                 except:
                     self.env.log.error("Error deleting test plan!")
                     self.env.log.error(formatExceptionInfo())
                     # Back to the catalog
+                    add_warning(req, _("An error occurred while deleting the test plan."))
                     req.redirect(req.href.wiki(path))
 
                 # Redirect to test catalog, forcing a page refresh by means of a random request parameter
                 req.redirect(req.href.wiki(path, mode=mode, fulldetails=fulldetails, random=str(datetime.now(utc).microsecond)))
+                
+            elif object_type == 'testcaseinplan':
+                req.perm.require('TEST_PLAN_ADMIN')
+                
+                planid = req.args.get('planid')
+                tcId = req.args.get('tcId')
+                id = tcId.rpartition('TC')[2]
+                
+                self.env.log.debug("About to remove test case %s from test plan %s" % (tcId, planid))
 
+                tp = None
+                try:
+                    tp = TestPlan(self.env, planid)
+
+                    # Remove the test case from the plan, i.e. delete the testcaseinplan object
+                    tcip = TestCaseInPlan(self.env, id, planid)
+                    
+                    tcip.delete_history()
+                    tcip.delete()
+
+                    add_notice(req, _("The Test Case was successfully removed from the plan."))
+                    
+                except:
+                    self.env.log.error("Error removing test case from plan!")
+                    self.env.log.error(formatExceptionInfo())
+                    # Back to the test case in plan
+                    add_warning(req, _("An error occurred while removing the test case from the plan."))
+                    req.redirect(req.href.wiki(tcId, planid=planid))
+
+                # Redirect to test plan, forcing a page refresh by means of a random request parameter
+                req.redirect(req.href.wiki(tp['page_name'], planid=planid, random=str(datetime.now(utc).microsecond)))
+                
         elif req.path_info.startswith('/testimport'):
             if req.method == 'POST':
                 if 'import_file' in req.args:
             object_type = req.args.get('type')
             cat_name = req.args.get('cat_name')
             planid = req.args.get('planid', '-1')
-            separator = req.args.get('separator', ',')
+            separator = req.args.get('column_separator', ',')
             fulldetails_str = req.args.get('fulldetails', '')
             raw_wiki_format_str = req.args.get('raw_wiki_format', '')
             

testman4trac/trunk/testmanager/htdocs/css/testmanager.css

     margin-right: 3px;
 }
 
+.statusIconElement:hover {
+	border: 1px solid black;
+}
+
 .rightIcon {
-    background: transparent url(../images/pencil.png) no-repeat scroll 0 0;
+    background: transparent url('../images/pencil.png') no-repeat scroll 0 0;
     padding-right:25px;
 }
 
 	cursor: pointer;
 	z-index: 9000;
 	position: absolute;
+    background: transparent url('../images/status-menu-bg.png') no-repeat 29px 7px;
+	/* background-attachment: fixed; */
 }
 
 ul.statusContextMenuUl {
 	float:left;
 	position:relative;
 	padding: 7px;
-	background-color: white;
+	/* background-color: white; */
 }
 
 ul.statusContextMenuUl > li > img {
 	padding: 1px;
-	background-color: white;
+	/* background-color: white; */
 }
 
 .statusContextSubMenuDiv {
 	background-color: purple;
 }
 
+.testArtifactPropertiesDiv {
+	margin-left: 30px;
+	background-color: #FFFBEA;
+	line-height: 140%;
+}
+
 @media print {
     .collapsed > div, .collapsed > table, .collapsed > ul, .collapsed > dl { 
         display: block; 

testman4trac/trunk/testmanager/htdocs/images/status-menu-bg.png

Added
New image

testman4trac/trunk/testmanager/htdocs/images/tree.png

Old
Old image
New
New image

testman4trac/trunk/testmanager/htdocs/images/tree_table.png

Old
Old image
New
New image

testman4trac/trunk/testmanager/htdocs/js/compatibility.js

 /* -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

testman4trac/trunk/testmanager/htdocs/js/cookies.js

 /* -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

testman4trac/trunk/testmanager/htdocs/js/it.js

 // Generated messages javascript file from compiled MO file
-babel.Translations.load({"domain":"testmanager-js","locale":"it","messages":{"Are you sure you want to delete the test plan and the state of all its contained test cases?":"Sei sicuro di voler eliminare il piano di test e lo stato di tutti i casi di test in esso contenuti?","Are you sure you want to duplicate the test catalog and all its contained test cases?":"Sei sicuro di voler duplicare il catalogo e tutti i casi di test in esso contenuti?","Length between 4 and 90 characters.":"Lunghezza da 4 a 90 caratteri.","Results: ":"Risultati: ","You must specify a name. Length between 4 and 90 characters.":"Devi indicare un nome. Lunghezza da 4 a 90 caratteri.","[Insert problem summary]":"[Inserire una descrizione del problema]"},"plural_expr":"(n != 1)"}).install();
+babel.Translations.load({"domain":"testmanager-js","locale":"it","messages":{"Are you sure you want to delete the test plan and the state of all its contained test cases?":"Sei sicuro di voler eliminare il piano di test e lo stato di tutti i casi di test in esso contenuti?","Are you sure you want to duplicate the test catalog and all its contained test cases?":"Sei sicuro di voler duplicare il catalogo e tutti i casi di test in esso contenuti?","Are you sure you want to remove the test case from the plan?":"Sei sicuro di voler eliminare il caso di test dal piano?","Length between 4 and 90 characters.":"Lunghezza da 4 a 90 caratteri.","Results: ":"Risultati: ","You must specify a name. Length between 4 and 90 characters.":"Devi indicare un nome. Lunghezza da 4 a 90 caratteri.","[Insert problem summary]":"[Inserire una descrizione del problema]"},"plural_expr":"(n != 1)"}).install();

testman4trac/trunk/testmanager/htdocs/js/menu.js

 /* -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 

testman4trac/trunk/testmanager/htdocs/js/testmanager.js

 /* -*- coding: utf-8 -*-
 #
-# Copyright (C) 2010-2011 Roberto Bordolanghi
+# Copyright (C) 2010-2012 Roberto Longobardi
 # 
 # This file is part of the Test Manager plugin for Trac.
 # 
     })(jQuery_testmanager);	
 }
 
+function addTestCaseToTestplanDialog() {
+	(function($) {
+		$(function() {
+			$("#dialog_select_testplan").dialog({width: 640, height: 430, modal: true});
+		});
+	})(jQuery_testmanager);	
+}
+
+function addTestCaseToPlan(tcId, tcatId) {
+	(function($) {
+		$(function() {
+			var planid = $("input[@name=selected_planid]:checked").val();
+			
+			if (planid && planid != '') {
+				var url = baseLocation+"/testcreate?type=testcaseinplan&tcatId="+tcatId+"&tcId="+tcId+"&planid="+planid;
+				window.location = url;
+			}
+		});
+	})(jQuery_testmanager);	
+}
+
+function addTestCaseToPlanCancel() {
+	(function($) {
+        $(function() {
+            $("#dialog_select_testplan").dialog('close');
+        });
+    })(jQuery_testmanager);	
+}
+
 function duplicateTestCase(tcName, catName) { 
 	var url = baseLocation+'/testcreate?type=testcase&duplicate=true&tcId='+tcName+'&path='+catName; 
 	window.location = url;
 }
 
-function regenerateTestPlan(planId, path) {
-    var url = baseLocation+"/testcreate?type=testplan&update=true&planid="+planId+"&path="+path;
+function updateTestCase(tcName, planId) {
+    var url = baseLocation+"/testcreate?type=testplan&update=true&tcId="+tcName+"&planid="+planId;
     window.location = url;
 }
 
+function removeTestCase(tcName, planId) {
+    if (confirm(_("Are you sure you want to remove the test case from the plan?"))) {
+		var url = baseLocation+"/testdelete?type=testcaseinplan&tcId="+tcName+"&planid="+planId;
+		window.location = url;
+	}
+}
+
 function creaTicket(tcName, planId, planName, summary){
     var tokens = $('span[name=breadcrumb]').map(function() { return this.innerHTML; }).get();
     var fullSummary = "";
 }
 
 function filterMatch(node1,node2,res) {
-    var name=(node1.innerHTML + (node2 ? node2.innerHTML : "")).toLowerCase();
+    var name=(node1.innerText + ' ' + (node2 ? (node2.innerText ? node2.innerText : node2.textContent) : '')).toLowerCase();
     var match=true;
     for (var i=0;i<res.length;i++) {
         match=match && name.match(res[i]);
     node = node.firstChild;
     while (node != null) {
         if (node.tagName === "TD") {
-            name += node.innerHTML;
+            name += ' ' + (node.innerText ? node.innerText : node.textContent);
         }
         
         node = node.nextSibling;

testman4trac/trunk/testmanager/locale/de/LC_MESSAGES/testmanager-js.po

 # German translations for TestManager.
-# Copyright (C) 2012 Roberto Bordolanghi
+# Copyright (C) 2012 Roberto Longobardi
 # This file is distributed under the same license as the TestManager
 # project.
 #

testman4trac/trunk/testmanager/locale/de/LC_MESSAGES/testmanager.mo

Binary file modified.

testman4trac/trunk/testmanager/locale/de/LC_MESSAGES/testmanager.po

 # German translations for TestManager.
-# Copyright (C) 2012 Roberto Bordolanghi
+# Copyright (C) 2012 Roberto Longobardi
 # This file is distributed under the same license as the TestManager
 # project.
 #
 "Project-Id-Version: Test Manager for Trac plugin\n"
 "Report-Msgid-Bugs-To: http://trac-hacks.org/wiki/TestManagerForTracPlugin"
 "\n"
-"POT-Creation-Date: 2012-06-03 12:56+0200\n"
+"POT-Creation-Date: 2012-08-09 21:46+0200\n"
 "PO-Revision-Date: 2012-01-04 07:58+0000\n"
 "Last-Translator: podskalsky <andreas.podskalsky@siemens.com>\n"
 "Language-Team: German "
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 0.9.6\n"
 
-#: testmanager/admin.py:57 testmanager/templates/testmanagerstats.html:142
+#: testmanager/admin.py:59 testmanager/templates/testmanagerstats.html:145
 msgid "Settings"
 msgstr "Einstellungen"
 
-#: testmanager/admin.py:58
+#: testmanager/admin.py:60
 msgid "Templates"
 msgstr "Templates"
 
-#: testmanager/admin.py:85
+#: testmanager/admin.py:97
 msgid "Settings saved"
 msgstr "Einstellungen gespeichert"
 
-#: testmanager/admin.py:88
+#: testmanager/admin.py:100
 msgid "Error saving the settings"
 msgstr "Fehler beim Speichern der Einstellungen"
 
-#: testmanager/admin.py:127
+#: testmanager/admin.py:147
 msgid "A Test Case template with that name already exists"
 msgstr "Ein Testfall-Template mit diesem Namen existiert bereits"
 
-#: testmanager/admin.py:135 testmanager/admin.py:153
+#: testmanager/admin.py:155 testmanager/admin.py:173
 msgid "Please enter a Template name first"
 msgstr "Bitte zuerst einen Template-Namen angeben"
 
-#: testmanager/admin.py:145
+#: testmanager/admin.py:165
 msgid "A Test Catalog template with that name already exists"
 msgstr "Ein Test-Verzeichnis-Template mit diesem Namen existiert bereits"
 
-#: testmanager/admin.py:161
+#: testmanager/admin.py:181
 #, python-format
 msgid "Template '%s' not removed as it is in use for a Test Catalog"
 msgstr ""
 "Template '%s' nicht gelöscht weil es in einem Test-Verzeichnis benutzt "
 "wird"
 
-#: testmanager/admin.py:166
+#: testmanager/admin.py:186
 #, python-format
 msgid "Error deleting Test Case template '%s'"
 msgstr "Feher beim Löschen des Testfall-Templates '%s'"
 
-#: testmanager/admin.py:168
+#: testmanager/admin.py:188
 #, python-format
 msgid "Test Case template '%s' deleted"
 msgstr "Testfall-Template '%s' gelöscht"
 
-#: testmanager/admin.py:180
+#: testmanager/admin.py:200
 #, python-format
 msgid "Template '%s' not removed as it is currently the default template"
 msgstr "Template '%s' nicht gelöscht weil es das Default-Template ist"
 
-#: testmanager/admin.py:185
+#: testmanager/admin.py:205
 #, python-format
 msgid "Error deleting Test Catalog template '%s'"
 msgstr "Fehler beim Löschen des Test-Verzeichnis-Template '%s'"
 
-#: testmanager/admin.py:187
+#: testmanager/admin.py:207
 #, python-format
 msgid "Test Catalog template '%s' deleted"
 msgstr "Test-Verzeichnis-Template '%s' gelöscht"
 
-#: testmanager/admin.py:196
+#: testmanager/admin.py:216
 msgid "Default Test Catalog template updated"
 msgstr "Default Test-Verzeichnis-Template aktualisiert"
 
-#: testmanager/admin.py:199
+#: testmanager/admin.py:219
 msgid "Failed to update default Test Catalog template"
 msgstr "Fehler beim Aktualisieren des Default-Test-Verzeichnis-Template"
 
-#: testmanager/admin.py:211
+#: testmanager/admin.py:231
 msgid "Failed to update Test Case templates"
 msgstr "Fehler beim Aktualisieren des Test-Verzeichnis-Template"
 
-#: testmanager/admin.py:213
+#: testmanager/admin.py:233
 msgid "Default Test Case templates updated"
 msgstr "Default-Test-Verzeichnis-Template aktualisiert"
 
-#: testmanager/admin.py:244
+#: testmanager/admin.py:264
 msgid "Template saved"
 msgstr "Template gespeichert"
 
-#: testmanager/api.py:247 testmanager/wiki.py:640 testmanager/wiki.py:1085
-#: testmanager/wiki.py:1467
+#: testmanager/admin.py:315 testmanager/model.py:733 testmanager/wiki.py:860
+#: testmanager/templates/admin_settings.html:40
+#: testmanager/templates/admin_templates.html:30
+#: testmanager/templates/admin_templates.html:61
+#: testmanager/templates/admin_templates.html:136
+msgid "Name"
+msgstr "Name"
+
+#: testmanager/admin.py:324 testmanager/api.py:1231 testmanager/model.py:715
+#: testmanager/model.py:719 testmanager/model.py:723 testmanager/model.py:730
+msgid "ID"
+msgstr "ID"
+
+#: testmanager/admin.py:334 testmanager/api.py:249 testmanager/api.py:262
+#: testmanager/api.py:1265 testmanager/model.py:727 testmanager/wiki.py:1588
+msgid "Status"
+msgstr "Status"
+
+#: testmanager/admin.py:335 testmanager/api.py:249 testmanager/api.py:1265
+#: testmanager/model.py:734 testmanager/wiki.py:391 testmanager/wiki.py:700
+#: testmanager/wiki.py:860 testmanager/wiki.py:1158 testmanager/wiki.py:1588
+msgid "Author"
+msgstr "Autor"
+
+#: testmanager/admin.py:336 testmanager/api.py:1265
+msgid "Last Change"
+msgstr "Letzte Änderung"
+
+#: testmanager/admin.py:345 testmanager/api.py:1243
+#: testmanager/templates/admin_templates.html:30
+#: testmanager/templates/admin_templates.html:61
+#: testmanager/templates/admin_templates.html:141
+msgid "Description"
+msgstr "Beschreibung"
+
+#: testmanager/api.py:249 testmanager/wiki.py:700 testmanager/wiki.py:1158
+#: testmanager/wiki.py:1588
 msgid "Timestamp"
 msgstr "Zeitstempel"
 
-#: testmanager/api.py:247 testmanager/api.py:1159 testmanager/model.py:683
-#: testmanager/wiki.py:640 testmanager/wiki.py:1038 testmanager/wiki.py:1085
-#: testmanager/wiki.py:1467
-msgid "Author"
-msgstr "Autor"
-
-#: testmanager/api.py:247 testmanager/api.py:260 testmanager/api.py:1159
-#: testmanager/model.py:676 testmanager/wiki.py:1038 testmanager/wiki.py:1467
-msgid "Status"
-msgstr "Status"
-
-#: testmanager/api.py:380
-msgid "Error adding test catalog"
+#: testmanager/api.py:382
+#, fuzzy
+msgid "An error occurred while adding the test catalog."
 msgstr "Fehler beim Hinzufügen des Test-Verzeichnises"
 
-#: testmanager/api.py:504
-msgid "Error adding test case"
+#: testmanager/api.py:403
+#, fuzzy
+msgid "The test case version was updated successfully."
+msgstr "Erfolgreich importierte Testfälle"
+
+#: testmanager/api.py:408
+msgid "An error occurred while updating the test case version."
+msgstr ""
+
+#: testmanager/api.py:435
+msgid "An error occurred while generating the test plan."
+msgstr ""
+
+#: testmanager/api.py:466
+msgid "The Test Case was successfully added to the plan."
+msgstr ""
+
+#: testmanager/api.py:468
+msgid "The Test Case was already contained in the specified Test Plan."
+msgstr ""
+
+#: testmanager/api.py:474
+msgid "An error occurred while adding the test case into the plan."
+msgstr ""
+
+#: testmanager/api.py:525
+msgid "The Test Case(s) were successfully pasted into the catalog."
+msgstr ""
+
+#: testmanager/api.py:530
+msgid "An error occurred while pasting the test case(s) into the catalog."
+msgstr ""
+
+#: testmanager/api.py:556
+msgid "An error occurred while duplicating the test case."
+msgstr ""
+
+#: testmanager/api.py:576
+#, fuzzy
+msgid "An error occurred while adding the test case."
 msgstr "Fehler beim Hinzufügen des Testfalls"
 
-#: testmanager/api.py:1125
+#: testmanager/api.py:602
+#, fuzzy
+msgid "The Test Plan was deleted successfully."
+msgstr "Erfolgreich importierte Testfälle"
+
+#: testmanager/api.py:608
+msgid "An error occurred while deleting the test plan."
+msgstr ""
+
+#: testmanager/api.py:633
+msgid "The Test Case was successfully removed from the plan."
+msgstr ""
+
+#: testmanager/api.py:639
+msgid "An error occurred while removing the test case from the plan."
+msgstr ""
+
+#: testmanager/api.py:1231
 msgid "Type"
 msgstr "Type"
 
-#: testmanager/api.py:1125 testmanager/model.py:664 testmanager/model.py:668
-#: testmanager/model.py:672 testmanager/model.py:679 testmanager/wiki.py:953
-#: testmanager/wiki.py:1029
-msgid "ID"
-msgstr "ID"
-
-#: testmanager/api.py:1125
+#: testmanager/api.py:1231
 msgid "Parent ID"
 msgstr "Parent ID"
 
-#: testmanager/api.py:1128
+#: testmanager/api.py:1234
 msgid "Test Plan Title"
 msgstr "Testplan Titel"
 
-#: testmanager/api.py:1130
+#: testmanager/api.py:1236
 msgid "Title"
 msgstr "Titel"
 
-#: testmanager/api.py:1133 testmanager/model.py:685
+#: testmanager/api.py:1239 testmanager/model.py:736 testmanager/wiki.py:393
+#: testmanager/wiki.py:1167
 msgid "Contains all Test Cases"
 msgstr "Enthält alle Testfälle"
 
-#: testmanager/api.py:1133
+#: testmanager/api.py:1239
 msgid "Snapshot"
 msgstr "Snapshot"
 
-#: testmanager/api.py:1137 testmanager/wiki.py:963
-#: testmanager/templates/admin_templates.html:28
-#: testmanager/templates/admin_templates.html:59
-#: testmanager/templates/admin_templates.html:139
-msgid "Description"
-msgstr "Beschreibung"
-
-#: testmanager/api.py:1159 testmanager/wiki.py:1038
-msgid "Last Change"
-msgstr "Letzte Änderung"
-
-#: testmanager/api.py:1198 testmanager/api.py:1199
+#: testmanager/api.py:1304 testmanager/api.py:1305
 msgid "No"
 msgstr "Ja"
 
-#: testmanager/api.py:1198 testmanager/api.py:1199
+#: testmanager/api.py:1304 testmanager/api.py:1305
 msgid "Yes"
 msgstr "Nein"
 
-#: testmanager/model.py:665 testmanager/model.py:669 testmanager/model.py:674
-#: testmanager/model.py:681
+#: testmanager/model.py:716 testmanager/model.py:720 testmanager/model.py:725
+#: testmanager/model.py:732
 msgid "Wiki page name"
 msgstr "Wiki-Seiten-Name"
 
-#: testmanager/model.py:673
+#: testmanager/model.py:724
 msgid "Plan ID"
 msgstr "Plan ID"
 
-#: testmanager/model.py:675
+#: testmanager/model.py:726
 msgid "Wiki page version"
 msgstr "Wiki-Page Version"
 
-#: testmanager/model.py:680
+#: testmanager/model.py:731
 msgid "Catalog ID"
 msgstr "Verzeichnis ID"
 
-#: testmanager/model.py:682 testmanager/wiki.py:944 testmanager/wiki.py:1020
-#: testmanager/templates/admin_settings.html:32
-#: testmanager/templates/admin_templates.html:28
-#: testmanager/templates/admin_templates.html:59
-#: testmanager/templates/admin_templates.html:134
-msgid "Name"
-msgstr "Name"
-
-#: testmanager/model.py:684
+#: testmanager/model.py:735 testmanager/wiki.py:392 testmanager/wiki.py:860
 msgid "Created"
 msgstr "Erstellt"
 
-#: testmanager/model.py:686
+#: testmanager/model.py:737
 msgid "Freeze Test Case versions"
 msgstr "Testfall-Version einfrieren"
 
-#: testmanager/model.py:817 testmanager/wiki.py:405 testmanager/wiki.py:465
+#: testmanager/model.py:868 testmanager/wiki.py:445 testmanager/wiki.py:509
 msgid "Test Case"
 msgstr "Testfall"
 
-#: testmanager/model.py:821
+#: testmanager/model.py:872
 msgid "Test Plan"
 msgstr "Testplan"
 
-#: testmanager/model.py:826 testmanager/stats.py:241
+#: testmanager/model.py:877 testmanager/stats.py:241
 msgid "Successful"
 msgstr "Erfolgreich"
 
-#: testmanager/model.py:827
+#: testmanager/model.py:878
 msgid "Untested"
 msgstr "Ungetestet"
 
-#: testmanager/model.py:828 testmanager/stats.py:241
+#: testmanager/model.py:879 testmanager/stats.py:241
 msgid "Failed"
 msgstr "Fehlgeschlagen"
 
 msgid "Test Manager"
 msgstr "Testmanager"
 
-#: testmanager/wiki.py:150
+#: testmanager/wiki.py:126
+msgid ""
+"You cannot rename Test Catalog, Test Case or Test Plan wiki pages this "
+"way. If you wish to modify the TITLE of the object, just Edit the page "
+"and change the text between '==' and '=='. If you wish to move the object"
+" elsewhere, instead, use the 'move' Test Manager functions."
+msgstr ""
+
+#: testmanager/wiki.py:161
 msgid ""
 "You cannot delete a Test Plan this way. Expand the Test Plans list under "
 "the corrisponding Catalog and use the X buttons to delete the Test Plans."
 msgstr ""
 
-#: testmanager/wiki.py:159
+#: testmanager/wiki.py:170
 msgid "You cannot delete the root catalogs list."
 msgstr ""
 
-#: testmanager/wiki.py:164
+#: testmanager/wiki.py:175
 msgid ""
 "Deleting this Test Catalog will delete all the contained Test Catalogs, "
 "Test Cases, Test Plans and the status history of them."
 msgstr ""
 
-#: testmanager/wiki.py:188
+#: testmanager/wiki.py:205
 msgid ""
 "Select the catalog into which to paste the Test Cases and click on 'Paste"
 " the copied Test Cases here'. "
 "Verzeichnis zum Einfügen der Testfälle auswählen und 'Kopierte Testfälle "
 "hierher einfügen' anklicken."
 
-#: testmanager/wiki.py:189 testmanager/wiki.py:193 testmanager/wiki.py:215
-#: testmanager/wiki.py:220 testmanager/wiki.py:395 testmanager/wiki.py:400
-#: testmanager/templates/admin_templates.html:155
+#: testmanager/wiki.py:206 testmanager/wiki.py:209 testmanager/wiki.py:225
+#: testmanager/wiki.py:229 testmanager/wiki.py:435 testmanager/wiki.py:440
+#: testmanager/wiki.py:685 testmanager/wiki.py:774 testmanager/wiki.py:838
+#: testmanager/wiki.py:898 testmanager/templates/admin_templates.html:157
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: testmanager/wiki.py:192
+#: testmanager/wiki.py:208
 msgid ""
 "Select the catalog into which to paste the Test Case and click on 'Move "
 "the copied Test Case here'. "
 "Verzeichnis zum Einfügen des Testfalls auswählen und 'Kopierten Testfall "
 "hierher verschieben' anklicken."
 
-#: testmanager/wiki.py:195
+#: testmanager/wiki.py:211
 msgid "Test Catalogs List"
 msgstr "Test-Verzeichnis-Liste"
 
-#: testmanager/wiki.py:198
+#: testmanager/wiki.py:214
 msgid "New Catalog:"
 msgstr "Neues Verzeichnis:"
 
-#: testmanager/wiki.py:199
+#: testmanager/wiki.py:215
 msgid "Add a Catalog"
 msgstr "Verzeichnis hinzufügen"
 
-#: testmanager/wiki.py:214
+#: testmanager/wiki.py:224
 msgid ""
 "Select the catalog (even this one) into which to paste the Test Cases and"
 " click on 'Paste the copied Test Cases here'. "
 "Verzeichnis zum Einfügen der Testfälle auswählen (auch das aktuelle) und "
 "'Kopierte Testfälle hierher einfügen' anklicken."
 
-#: testmanager/wiki.py:219
+#: testmanager/wiki.py:228
 msgid ""
 "Select the catalog (even this one) into which to paste the Test Case and "
 "click on 'Move the copied Test Case here'. "
 "Verzeichnis zum Einfügen des Testfalls auswählen (auch das aktuelle) und "
 "'Kopierten Testfall hierher verschieben ' anklicken."
 
-#: testmanager/wiki.py:223 testmanager/templates/admin_templates.html:102
+#: testmanager/wiki.py:232 testmanager/templates/admin_templates.html:104
 msgid "Test Catalog"
 msgstr "Test-Verzeichnis"
 
-#: testmanager/wiki.py:225
+#: testmanager/wiki.py:234
 msgid "New Sub-Catalog:"
 msgstr "Neues Unterverzeichnis:"
 
-#: testmanager/wiki.py:226
+#: testmanager/wiki.py:235
 msgid "Add a Sub-Catalog"
 msgstr "Unterverzeichnis hinzufügen"
 
-#: testmanager/wiki.py:257
+#: testmanager/wiki.py:266
 msgid "New Test Case:"
 msgstr "Neuer Testfall"
 
-#: testmanager/wiki.py:261
+#: testmanager/wiki.py:270
 msgid "Add a Test Case"
 msgstr "Testfall hinzufügen"
 
-#: testmanager/wiki.py:265
+#: testmanager/wiki.py:274
 msgid "New Test Plan:"
 msgstr "Neuer Testplan:"
 
-#: testmanager/wiki.py:269
+#: testmanager/wiki.py:278
 msgid "Generate a new Test Plan"
 msgstr "Neuen Testplan erstellen"
 
-#: testmanager/wiki.py:279
+#: testmanager/wiki.py:288
 msgid "Select Multiple Test Cases"
 msgstr "Mehrfache Testfälle auswählen"
 
-#: testmanager/wiki.py:282
+#: testmanager/wiki.py:291
 msgid "Copy the Selected Test Cases"
 msgstr "Ausgewählte Testfälle kopieren"
 
-#: testmanager/wiki.py:286
+#: testmanager/wiki.py:295
 msgid "Paste the copied Test Cases here"
 msgstr "Kopierte Testfälle hierher einfügen"
 
-#: testmanager/wiki.py:289
+#: testmanager/wiki.py:298
 msgid "Move the copied Test Case here"
 msgstr "Kopierten Testfall hierher verschieben "
 
-#: testmanager/wiki.py:293
+#: testmanager/wiki.py:302
 msgid "Import Test Cases"
 msgstr "Testfälle importieren"
 
-#: testmanager/wiki.py:296
+#: testmanager/wiki.py:305
 msgid "Export Test Catalog"
 msgstr "Test-Verzeichnis exportieren"
 
-#: testmanager/wiki.py:310
+#: testmanager/wiki.py:320
 msgid "Delete this version"
 msgstr ""
 
-#: testmanager/wiki.py:311
+#: testmanager/wiki.py:321
 #, fuzzy
 msgid "Delete Test Catalog"
 msgstr "Test-Verzeichnis"
 
-#: testmanager/wiki.py:336 testmanager/wiki.py:505
+#: testmanager/wiki.py:354 testmanager/wiki.py:563
 msgid "Back to the Catalog"
 msgstr "Zürück zum Verzeichnis"
 
-#: testmanager/wiki.py:347
+#: testmanager/wiki.py:359
 msgid "Test Plan: "
 msgstr "Testplan:"
 
-#: testmanager/wiki.py:357
+#: testmanager/wiki.py:372
 msgid "Export Test Plan"
 msgstr "Testplan exportieren"
 
-#: testmanager/wiki.py:394
+#: testmanager/wiki.py:393 testmanager/wiki.py:1158
+#, fuzzy
+msgid "Contained Test Cases"
+msgstr "Enthält alle Testfälle"
+
+#: testmanager/wiki.py:393 testmanager/wiki.py:1167
+#, fuzzy
+msgid "Contains selected Test Cases"
+msgstr "Enthält alle Testfälle"
+
+#: testmanager/wiki.py:394 testmanager/wiki.py:1158
+#, fuzzy
+msgid "Test Case Versions"
+msgstr "Testfall-Version einfrieren"
+
+#: testmanager/wiki.py:394 testmanager/wiki.py:1168
+msgid "Points to latest Test Case versions"
+msgstr ""
+
+#: testmanager/wiki.py:394 testmanager/wiki.py:1168
+msgid "Contains a snapshot of Test Case versions"
+msgstr ""
+
+#: testmanager/wiki.py:402
+msgid "Switch to Tabular View"
+msgstr ""
+
+#: testmanager/wiki.py:407
+msgid "Switch to Tree View"
+msgstr ""
+
+#: testmanager/wiki.py:434
 msgid ""
 "The Test Cases have been copied. Now select the catalog into which to "
 "paste the Test Cases and click on 'Paste the copied Test Cases here'.  "
 "Testfälle auswählen und 'Kopierte Testfälle hierher verschieben' "
 "anklicken."
 
-#: testmanager/wiki.py:399
+#: testmanager/wiki.py:439
 msgid ""
 "The Test Case has been cut. Now select the catalog into which to move the"
 " Test Case and click on 'Move the copied Test Case here'. "
 " Testfalls auswählen und 'Kopierten Testfall hierher verschieben ' "
 "anklicken."
 
-#: testmanager/wiki.py:414 testmanager/wiki.py:476
+#: testmanager/wiki.py:454 testmanager/wiki.py:521
 msgid "Open a Ticket on this Test Case"
 msgstr "Ticket zu diesem Testfall öffnen"
 
-#: testmanager/wiki.py:416 testmanager/wiki.py:478
+#: testmanager/wiki.py:456 testmanager/wiki.py:523
 msgid "Show Related Tickets"
 msgstr "Zugehörige Tickets anzeigen"
 
-#: testmanager/wiki.py:418
+#: testmanager/wiki.py:458
 msgid "Move the Test Case into another catalog"
 msgstr "Testfall in ein anderes Verzeichnis verschieben"
 
-#: testmanager/wiki.py:420
+#: testmanager/wiki.py:460
 msgid "Duplicate the Test Case"
 msgstr "Testfall kopieren"
 
-#: testmanager/wiki.py:498
+#: testmanager/wiki.py:462
+#, fuzzy
+msgid "Add to a Test Plan"
+msgstr "Zürück zum Testplan"
+
+#: testmanager/wiki.py:538
+msgid "Update to latest version of Test Case"
+msgstr ""
+
+#: testmanager/wiki.py:544
+#, fuzzy
+msgid "Remove from the Test Plan"
+msgstr "Zürück zum Testplan"
+
+#: testmanager/wiki.py:556
 msgid "Back to the Test Plan"
 msgstr "Zürück zum Testplan"
 
-#: testmanager/wiki.py:562
+#: testmanager/wiki.py:620
 msgid "Edit"
 msgstr "Bearbeiten"
 
-#: testmanager/wiki.py:566
+#: testmanager/wiki.py:624
 msgid "Save"
 msgstr "Speichern"
 
-#: testmanager/wiki.py:637
+#: testmanager/wiki.py:639
+msgid "Specify the new Test Plan properties."
+msgstr ""
+
+#: testmanager/wiki.py:642
+msgid "Test Plan properties"
+msgstr ""
+
+#: testmanager/wiki.py:648
+msgid "The new Test Plan will contain:"
+msgstr ""
+
+#: testmanager/wiki.py:655
+#, fuzzy
+msgid "All the Test Cases in the Catalog"
+msgstr "Testfall in ein anderes Verzeichnis verschieben"
+
+#: testmanager/wiki.py:656
+msgid "Only the Test Cases selected before"
+msgstr ""
+
+#: testmanager/wiki.py:668
+msgid "The new Test Plan will:"
+msgstr ""
+
+#: testmanager/wiki.py:675
+msgid "Refer to a current snapshot of the versions of the test cases"
+msgstr ""
+
+#: testmanager/wiki.py:676
+msgid "Always point to the latest version of the Test Cases"
+msgstr ""
+
+#: testmanager/wiki.py:684
+#, fuzzy
+msgid "Create Test Plan"
+msgstr "Testplan exportieren"
+
+#: testmanager/wiki.py:697
 msgid "Object change history"
 msgstr "Objekt-Änderungs-Geschichte"
 
-#: testmanager/wiki.py:640
+#: testmanager/wiki.py:700
 msgid "Property"
 msgstr "Eigenschaft"
 
-#: testmanager/wiki.py:640
+#: testmanager/wiki.py:700
 msgid "Previous Value"
 msgstr "Verheriger Wert"
 
-#: testmanager/wiki.py:640
+#: testmanager/wiki.py:700
 msgid "New Value"
 msgstr "Neuer Wert"
 
-#: testmanager/wiki.py:790
+#: testmanager/wiki.py:730
+msgid "Select a file in CSV format to import the test cases from."
+msgstr ""
+
+#: testmanager/wiki.py:732
+msgid ""
+"The first row will have column names. The data must start from the second"
+" row."
+msgstr ""
+
+#: testmanager/wiki.py:733
+msgid "The file should have the following required columns:"
+msgstr ""
+
+#: testmanager/wiki.py:738
+msgid ""
+"Any subsequent columns are optional, and will generate <a href='http"
+"://trac-hacks.org/wiki/TestManagerForTracPlugin#Customfields' "
+"target='_blank'>custom test case fields</a>."
+msgstr ""
+
+#: testmanager/wiki.py:739
+msgid "Use lowercase identifiers, with no blanks, for the column names."
+msgstr ""
+
+#: testmanager/wiki.py:742
+msgid "Upload file"
+msgstr ""
+
+#: testmanager/wiki.py:748
+msgid "File name:"
+msgstr ""
+
+#: testmanager/wiki.py:760 testmanager/wiki.py:822
+msgid "Column separator:"
+msgstr ""
+
+#: testmanager/wiki.py:773
+msgid "Import"
+msgstr ""
+
+#: testmanager/wiki.py:789
+msgid ""
+"Select a name and a location on your machine for the CSV file to export "
+"the test cases to."
+msgstr ""
+
+#: testmanager/wiki.py:792
+msgid "Export options"
+msgstr ""
+
+#: testmanager/wiki.py:798
+msgid "Include full description:"
+msgstr ""
+
+#: testmanager/wiki.py:810
+msgid "Raw wiki syntax:"
+msgstr ""
+
+#: testmanager/wiki.py:837
+msgid "Export"
+msgstr ""
+
+#: testmanager/wiki.py:851
+#, fuzzy
+msgid "Add Test Case to a Test Plan"
+msgstr "Testfall-Template hinzufügen"
+
+#: testmanager/wiki.py:853
+msgid "Select the Test Plan to add the Test Case to."
+msgstr ""
+
+#: testmanager/wiki.py:856
+#, fuzzy
+msgid "Test Plans"
+msgstr "Testplan"
+
+#: testmanager/wiki.py:888
+msgid "No suitable Test Plans (i.e. with only selected Test Cases) found."
+msgstr ""
+
+#: testmanager/wiki.py:897
+#, fuzzy
+msgid "Add to Test Plan"
+msgstr "Zürück zum Testplan"
+
+#: testmanager/wiki.py:911 testmanager/templates/testimportresults.html:29
+msgid "Error"
+msgstr "Fehler"
+
+#: testmanager/wiki.py:914
 msgid "An error occurred performing the operation.<br /><br />Please try again."
 msgstr ""
 
-#: testmanager/wiki.py:877
+#: testmanager/wiki.py:1001
 msgid "All Catalogs"
 msgstr "Alle Verzeichnisse"
 
-#: testmanager/wiki.py:918 testmanager/wiki.py:939 testmanager/wiki.py:993
-#: testmanager/wiki.py:1015 testmanager/wiki.py:1071
+#: testmanager/wiki.py:1042 testmanager/wiki.py:1051 testmanager/wiki.py:1095
+#: testmanager/wiki.py:1102 testmanager/wiki.py:1144
 msgid "Filter:"
 msgstr "Filter:"
 
-#: testmanager/wiki.py:918 testmanager/wiki.py:939 testmanager/wiki.py:993
-#: testmanager/wiki.py:1015
+#: testmanager/wiki.py:1042 testmanager/wiki.py:1051 testmanager/wiki.py:1095
+#: testmanager/wiki.py:1102
 msgid ""
 "Type the test to search for, even more than one word. You can also filter"
 " on the test case status (untested, successful, failed)."
 "Sucheingabefeld für Testfall. Auch mehrere Wörter möglich. Filterung kann"
 " auch den Testfall-Status (untested, successful, failed) beinhalten."
 
-#: testmanager/wiki.py:919 testmanager/wiki.py:994
+#: testmanager/wiki.py:1043 testmanager/wiki.py:1096
 msgid "Expand all"
 msgstr "Alles ausklappen"
 
-#: testmanager/wiki.py:919 testmanager/wiki.py:994
+#: testmanager/wiki.py:1043 testmanager/wiki.py:1096
 msgid "Collapse all"
 msgstr "Alles einklappen"
 
-#: testmanager/wiki.py:1070
+#: testmanager/wiki.py:1143
 msgid "Available Test Plans"
 msgstr "Verfügbare Testpläne"