<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Gurock Software Support Forum]]></title>
	<link rel="self" href="http://forum.gurock.com/feed/atom/"/>
	<updated>2012-05-16T19:26:47Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.gurock.com/</id>
		<entry>
			<title type="html"><![CDATA[Assigned items view?]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/889/assigned-items-view/new/posts/"/>
			<summary type="html"><![CDATA[<p>As I assess test software, I&#039;m looking for a way to not only manage testing but manage testers as well.&nbsp; &nbsp;Our organization has 6-8 lanes of concurrent development (as well as dozens of projects that are currently complete but could re-emerge in the future) and no one is assigned to work in just one project.&nbsp; &nbsp;In Test Rails is there any way for me to tell:</p><p>a) How many test runs I&#039;ve assigned to a particular person and how much time those tests are estimated to take?&nbsp; &nbsp;</p><p>b) for a tester to see a To Do list that includes assignments from ALL projects at once, instead of having to drill into every project to see what there is to be done?</p>]]></summary>
			<author>
				<name><![CDATA[jrobinson]]></name>
				<uri>http://forum.gurock.com/user/785/</uri>
			</author>
			<updated>2012-05-16T19:26:47Z</updated>
			<id>http://forum.gurock.com/topic/889/assigned-items-view/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: API to update test results]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/888/re-api-to-update-test-results/new/posts/"/>
			<summary type="html"><![CDATA[<p>We have written automation test suites in robotium(junit based java framework for android applications). We&#039;re planning to add the test results programmatically in testrail after running each test case. </p><p> In our setup, we have weekly releases and therefore will be running the tests weekly.For each week we create a test plan.</p><p>The API,&nbsp; add_result_for_case uses &lt;run_id&gt;/&lt;case_id&gt;&nbsp; - Needs Test run id and test case id. </p><p>However, looking around on testrail, we see that Test case id in &quot;Test suites &amp; cases&quot;, and the test case id under test plan(same test case included in test plan) is different.</p><p> If i have Test case id T1. A test plan created including this test case has id C1 for the same test case.</p><p>So each time a new test plan is created a different id is generated for the same test case.</p><p>Now we are trying to automatically update the results in test plan.Do i need to manually give that test id(listed in test run) in code? Or is it sufficient to provide the fixed test case id (independent of what is listed in the test plan ).</p><p>Thanks<br />Sandhya</p>]]></summary>
			<author>
				<name><![CDATA[sndy212]]></name>
				<uri>http://forum.gurock.com/user/780/</uri>
			</author>
			<updated>2012-05-15T23:21:25Z</updated>
			<id>http://forum.gurock.com/topic/888/re-api-to-update-test-results/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Specific formatting for API Requests]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/882/specific-formatting-for-api-requests/new/posts/"/>
			<summary type="html"><![CDATA[<p>I have been trying to get this to work for over 10 hours and I can&#039;t figure this out. Unfortunately, the examples in the documentation aren&#039;t very clear.</p><p>What is the specific syntax for sending these requests? Where does the key go? Where do the arguments go? Does the key have to go at the end of the request? The beginning? I have tried every combination and I always get &quot;Error: Key missing or invalid&quot; or &quot;Exceptions must be valid objects derived from the Exception base class in \/Applications\/MAMP\/htdocs\/testrail\/sys\/helpers\/ex.php at 23&quot;}&quot;</p><p>Needless to say, this is becoming very frustrating for me. Is there any way that I can get a specific example or an explanation with multiple examples of how to access this API with more than 1 argument? Every example I see has 1 argument, but I can&#039;t even get that to work.</p><p>I am trying to get this to work on my local machine before I move it into production. I am using MAMP and sending cURL requests using PHP. </p><p>Thank you.</p>]]></summary>
			<author>
				<name><![CDATA[Blaino]]></name>
				<uri>http://forum.gurock.com/user/763/</uri>
			</author>
			<updated>2012-05-14T00:33:22Z</updated>
			<id>http://forum.gurock.com/topic/882/specific-formatting-for-api-requests/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Feature Request: Save settings to Tree in Groups]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/881/feature-request-save-settings-to-tree-in-groups/new/posts/"/>
			<summary type="html"><![CDATA[<p>In Test Suites &amp; Cases, if you have a test suite that is large enough, viewing the cases isn&#039;t easy. </p><p>In the Groups bar on the right side of the screen,&nbsp; the following message appears at the bottom of the test cases &quot; __ more cases available. Show all cases or switch to compact view. &quot; The designing of test cases becomes tedious when I have to click &quot;show all&quot; every time. </p><p>It would be nice if:<br /></p><ul><li><p>You save the setting to &quot;show all cases&quot; so a user doesn&#039;t have to click it every time to access a test there</p></li><li><p>You save the settings for which parts of the tree were collapsed/expanded. This would include the list of the test cases in the main window (the window to the left of the &quot;Groups&quot; sidebar.</p></li></ul><p>We don&#039;t use the compact view, but would like to see a collapsing feature to the &quot;View all&quot; in the main window. This would save my company a lot of time and effort!</p><p>Thanks.</p>]]></summary>
			<author>
				<name><![CDATA[Npha]]></name>
				<uri>http://forum.gurock.com/user/769/</uri>
			</author>
			<updated>2012-05-08T17:59:24Z</updated>
			<id>http://forum.gurock.com/topic/881/feature-request-save-settings-to-tree-in-groups/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Archiving tests]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/879/archiving-tests/new/posts/"/>
			<summary type="html"><![CDATA[<p>Hi,</p><p>Deleting tests which are no longer applicable is a bit severe - it might be necessary to revisit them at some point in the future.</p><p>Could you add the ability to archive a test, so that it doesn&#039;t appear in a test suite?</p><p>Cheers,<br />Matt</p>]]></summary>
			<author>
				<name><![CDATA[matthew1471]]></name>
				<uri>http://forum.gurock.com/user/90/</uri>
			</author>
			<updated>2012-05-03T07:43:48Z</updated>
			<id>http://forum.gurock.com/topic/879/archiving-tests/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Feature Request/Bug: Remove Suite from Copy/Move dialog with no tests]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/878/feature-requestbug-remove-suite-from-copymove-dialog-with-no-tests/new/posts/"/>
			<summary type="html"><![CDATA[<p>I would call this a bug, but when I am moving test cases around the drop down shows all suites from all projects, regardless if the suite has tests or not.&nbsp; Since the user can&#039;t select tests from a suite if the suite has no tests, there is no reason to show it. </p><p>The list is getting very unmanageable in my application already. </p><p>At the very least, a checkbox to hide empty suites, would be a godsend.</p>]]></summary>
			<author>
				<name><![CDATA[brian @ spredfast]]></name>
				<uri>http://forum.gurock.com/user/509/</uri>
			</author>
			<updated>2012-05-02T23:23:43Z</updated>
			<id>http://forum.gurock.com/topic/878/feature-requestbug-remove-suite-from-copymove-dialog-with-no-tests/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Feature Request: In Line Attribute Editing]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/877/feature-request-in-line-attribute-editing/new/posts/"/>
			<summary type="html"><![CDATA[<p>The feature of being able to display test case attributes in line is very helpful.</p><p>What would make this feature massively better would be in line editing.&nbsp; It would make work flow and case maintenance much much easier.</p>]]></summary>
			<author>
				<name><![CDATA[brian @ spredfast]]></name>
				<uri>http://forum.gurock.com/user/509/</uri>
			</author>
			<updated>2012-05-02T23:07:45Z</updated>
			<id>http://forum.gurock.com/topic/877/feature-request-in-line-attribute-editing/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Memory leak when closing live logging]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/876/memory-leak-when-closing-live-logging/new/posts/"/>
			<summary type="html"><![CDATA[<p>Hello,</p><p>I am evaluating SmartInspect 3.3.3.72 in a delphi 2010 application and get a memory leak when I close the live viewer while my application is running.<br />There is one not freed instance of THandleStream and TSiBufferedStream left.</p><p>Is there a way to fix this leak?</p><p>Best regards, Peter</p><p>My connection String is:<br />&#039;pipe(async.enabled=true, reconnect=true, reconnect.interval=&quot;10s&quot;)&#039;</p><p>Here is the complete memcheck log:</p><p>--------------------------------2012/5/2 9:33:17--------------------------------<br />A memory block has been leaked. The size is: 8284</p><p>This block was allocated by thread 0x14A4, and the stack trace (return addresses) at the time was:<br />0040487c +04 GearPro.exe&nbsp; System&nbsp; &nbsp; &nbsp; &nbsp; 2979&nbsp; +5 @.GetMem<br />006037ad +21 GearPro.exe&nbsp; SmartInspect 21316&nbsp; +3 @TSiBufferedStream.Create<br />006158aa +5a GearPro.exe&nbsp; SmartInspect 30352&nbsp; +5 @TSiPipeProtocol.InternalConnect<br />00602689 +41 GearPro.exe&nbsp; SmartInspect 20866&nbsp; +5 @TSiProtocol.ImplConnect<br />0046dbda +42 GearPro.exe&nbsp; Classes&nbsp; &nbsp; &nbsp; 11019&nbsp; +8 @@ThreadProc<br />004078bc +28 GearPro.exe&nbsp; Controller&nbsp; &nbsp;13582 +33 @@ThreadWrapper<br />75403398 +10 kernel32.dll&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BaseThreadInitThunk</p><p>The block is currently used for an object of class: Unknown</p><p>The allocation number is: 1122</p><p>--------------------------------2012/5/2 9:33:17--------------------------------<br />A memory block has been leaked. The size is: 28</p><p>This block was allocated by thread 0x14A4, and the stack trace (return addresses) at the time was:<br />0040487c +04 GearPro.exe&nbsp; System&nbsp; &nbsp; &nbsp; &nbsp; 2979&nbsp; +5 @.GetMem<br />0040618a +0a GearPro.exe&nbsp; HConvUnits&nbsp; &nbsp; 9433&nbsp; +1 @TObject.NewInstance<br />004067b3 +07 GearPro.exe&nbsp; AxCtrls&nbsp; &nbsp; &nbsp; 10277&nbsp; +5 initialization<br />00603799 +0d GearPro.exe&nbsp; SmartInspect 21313&nbsp; +0 @TSiBufferedStream.Create<br />006158aa +5a GearPro.exe&nbsp; SmartInspect 30352&nbsp; +5 @TSiPipeProtocol.InternalConnect<br />00602689 +41 GearPro.exe&nbsp; SmartInspect 20866&nbsp; +5 @TSiProtocol.ImplConnect<br />0046dbda +42 GearPro.exe&nbsp; Classes&nbsp; &nbsp; &nbsp; 11019&nbsp; +8 @@ThreadProc<br />004078bc +28 GearPro.exe&nbsp; Controller&nbsp; &nbsp;13582 +33 @@ThreadWrapper<br />75403398 +10 kernel32.dll&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BaseThreadInitThunk</p><p>The block is currently used for an object of class: TSiBufferedStream</p><p>The allocation number is: 1120</p><p>--------------------------------2012/5/2 9:33:17--------------------------------<br />A memory block has been leaked. The size is: 12</p><p>This block was allocated by thread 0x14A4, and the stack trace (return addresses) at the time was:<br />0040487c +04 GearPro.exe&nbsp; System&nbsp; &nbsp; &nbsp; &nbsp; 2979&nbsp; +5 @.GetMem<br />0040618a +0a GearPro.exe&nbsp; HConvUnits&nbsp; &nbsp; 9433&nbsp; +1 @TObject.NewInstance<br />004067b3 +07 GearPro.exe&nbsp; AxCtrls&nbsp; &nbsp; &nbsp; 10277&nbsp; +5 initialization<br />00466946 +0a GearPro.exe&nbsp; Classes&nbsp; &nbsp; &nbsp; &nbsp;6085&nbsp; +0 @THandleStream.Create<br />00615888 +38 GearPro.exe&nbsp; SmartInspect 30350&nbsp; +3 @TSiPipeProtocol.InternalConnect<br />00602689 +41 GearPro.exe&nbsp; SmartInspect 20866&nbsp; +5 @TSiProtocol.ImplConnect<br />0046dbda +42 GearPro.exe&nbsp; Classes&nbsp; &nbsp; &nbsp; 11019&nbsp; +8 @@ThreadProc<br />004078bc +28 GearPro.exe&nbsp; Controller&nbsp; &nbsp;13582 +33 @@ThreadWrapper<br />75403398 +10 kernel32.dll&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BaseThreadInitThunk</p><p>The block is currently used for an object of class: THandleStream</p><p>The allocation number is: 1029</p><p>--------------------------------2012/5/2 9:33:17--------------------------------<br />This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):</p><p>1 - 12 bytes: THandleStream x 1<br />13 - 28 bytes: TSiBufferedStream x 1</p><p>The sizes of leaked medium and large blocks are (excluding expected leaks registered by pointer): 8284</p><p>Note: This memory leak check is only performed if Delphi is currently running on the same computer. Memory leak detail is logged to a text file in the same folder as this application. To disable this</p>]]></summary>
			<author>
				<name><![CDATA[PKoegel]]></name>
				<uri>http://forum.gurock.com/user/764/</uri>
			</author>
			<updated>2012-05-02T08:01:07Z</updated>
			<id>http://forum.gurock.com/topic/876/memory-leak-when-closing-live-logging/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Accessing the TestRail API]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/875/accessing-the-testrail-api/new/posts/"/>
			<summary type="html"><![CDATA[<p>Hello,</p><p>I&#039;m a little confused by how I&#039;m supposed to access the TestRail API. I&#039;m trying to take tests from Excel or CSV and automatically import them into TestRail. I know you can run a script to turn the files into XML and then manually import, but I want it done automatically. </p><p>From what I understand you have to send a HTTP request, but what I&#039;m confused about is how to format all the information. Do I have to create a JSON object from the XML and send that object within the HTTP request? </p><p>Any help would be great. If this has been answered already, I&#039;m sorry. I looked through a few hundred questions and haven&#039;t found what I&#039;m looking for. </p><p>Thank you,</p><p>Blaine Anderson</p>]]></summary>
			<author>
				<name><![CDATA[Blaino]]></name>
				<uri>http://forum.gurock.com/user/763/</uri>
			</author>
			<updated>2012-05-01T20:45:14Z</updated>
			<id>http://forum.gurock.com/topic/875/accessing-the-testrail-api/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Push Custom with User mapping]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/874/push-custom-with-user-mapping/new/posts/"/>
			<summary type="html"><![CDATA[<p>We are trying to integrate Testrail and Jira.&nbsp; So far we are able to get Defects: custom and Defects: User mapping to work.&nbsp; But not together.&nbsp; I am by no means a programmer and could use a bit of help if possible.&nbsp; This of course is all copied from examples and modified to add both.</p><div class="codebox"><pre><code>&lt;?php

class Jira_custom_defect_plugin extends Defect_plugin
{
    private $_api;
    
    private $_address;
    private $_user;
    private $_password;
    
    private static $_meta = array(
    &#039;author&#039; =&gt; &#039;Gurock Software&#039;,
    &#039;version&#039; =&gt; &#039;1.0&#039;,
    &#039;description&#039; =&gt; &#039;Jira defect plugin for TestRail&#039;,
    &#039;can_push&#039; =&gt; true,
    &#039;can_lookup&#039; =&gt; true,
    &#039;default_config&#039; =&gt; 
        &#039;; Please configure your Jira connection below
        [connection]
        address=http://&lt;your-server&gt;/
        user=testrail
        password=secret
 
        [users]
        user@example.com=user:secret&#039;
    );
        
    public function get_meta()
    {
        return self::$_meta;
    }
    
    // *********************************************************
    // CONSTRUCT / DESTRUCT
    // *********************************************************    
    
    public function __construct()
    {
    }
    
    public function __destruct()
    {
        if ($this-&gt;_api)
        {
            try
            {
                $api = $this-&gt;_api;
                $this-&gt;_api = null;
                $api-&gt;logout();
            }
            catch (Exception $e)
            {
                // Possible exceptions are ignored here.
            }
        }
    }

    // *********************************************************
    // CONFIGURATION
    // *********************************************************
    
    public function validate_config($config)
    {
        $ini = ini::parse($config);
        
        if (!isset($ini[&#039;connection&#039;]))
        {
            throw new ValidationException(&#039;Missing [connection] group&#039;);
        }
        
        $keys = array(&#039;address&#039;, &#039;user&#039;, &#039;password&#039;);
        
        // Check required values for existance
        foreach ($keys as $key)
        {
            if (!isset($ini[&#039;connection&#039;][$key]) ||
                !$ini[&#039;connection&#039;][$key])
            {
                throw new ValidationException(
                    &quot;Missing configuration for key &#039;$key&#039;&quot;
                );
            }
        }
        
        $address = $ini[&#039;connection&#039;][&#039;address&#039;];
        
        // Check whether the address is a valid url (syntax only)
        if (!check::url($address))
        {
            throw new ValidationException(&#039;Address is not a valid url&#039;);
        }
    }
    
    public function configure($config)
    {
        $ini = ini::parse($config);
        $this-&gt;_address = str::slash($ini[&#039;connection&#039;][&#039;address&#039;]);
        $this-&gt;_user = $ini[&#039;connection&#039;][&#039;user&#039;];
        $this-&gt;_password = $ini[&#039;connection&#039;][&#039;password&#039;];    
    
        if (isset($ini[&#039;users&#039;]))
        {
            $this-&gt;_users = $ini[&#039;users&#039;];
        }
        else
        {
            $this-&gt;_users = array();
        }
    }
    // *********************************************************
    // API / CONNECTION
    // *********************************************************
    
    private function _get_api($context = null)
    {
    if ($this-&gt;_api)
    {
        return $this-&gt;_api;
    }
 
    $user = $this-&gt;_user;
    $password = $this-&gt;_password;
 
    // Find the appropriate Jira user for the bug reporter
    // (by mapping the current TestRail user to her Jira
    // account).
    if ($context &amp;&amp; $this-&gt;_users)
    {
        $credentials = arr::get(
            $this-&gt;_users,
            str::to_lower($context[&#039;user&#039;]-&gt;email)
        );
 
        if ($credentials)
        {
            if (preg_match(&#039;/([^:]+):(.+)/&#039;, $credentials, $matches))
            {
                $user = $matches[1];
                $password = $matches[2];
            }
        }
    }
 
    $this-&gt;_api = new Jira_api($this-&gt;_address);
    $this-&gt;_api-&gt;login($user, $password);
    return $this-&gt;_api;
    }
    
    // *********************************************************
    // PUSH
    // *********************************************************
        
    public function prepare_push($context)
    {
        // Return a form with the following fields/properties
        return array(
            &#039;fields&#039; =&gt; array(
                &#039;summary&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;string&#039;,
                    &#039;label&#039; =&gt; &#039;Summary&#039;,
                    &#039;required&#039; =&gt; true,
                    &#039;size&#039; =&gt; &#039;full&#039;
                ),
                &#039;type&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;dropdown&#039;,
                    &#039;label&#039; =&gt; &#039;Issue Type&#039;,
                    &#039;required&#039; =&gt; true,
                    &#039;remember&#039; =&gt; true,
                    &#039;size&#039; =&gt; &#039;compact&#039;
                ),
                &#039;project&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;dropdown&#039;,
                    &#039;label&#039; =&gt; &#039;Project&#039;,
                    &#039;required&#039; =&gt; true,
                    &#039;remember&#039; =&gt; true,
                    &#039;cascading&#039; =&gt; true,
                    &#039;size&#039; =&gt; &#039;compact&#039;
                ),
                &#039;component&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;dropdown&#039;,
                    &#039;label&#039; =&gt; &#039;Component&#039;,
                    &#039;required&#039; =&gt; true,
                    &#039;remember&#039; =&gt; true,
                    &#039;depends_on&#039; =&gt; &#039;project&#039;,
                    &#039;size&#039; =&gt; &#039;compact&#039;
                ),
                &#039;buildaffected&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;string&#039;,
                    &#039;label&#039; =&gt; &#039;Build Affected&#039;,
                    &#039;remember&#039; =&gt; true,
                    &#039;size&#039; =&gt; &#039;compact&#039;
                ),
                &#039;description&#039; =&gt; array(
                    &#039;type&#039; =&gt; &#039;text&#039;,
                    &#039;label&#039; =&gt; &#039;Description&#039;
                )
            )
        );
    }
    
    private function _get_summary_default($context)
    {
        $test = current($context[&#039;tests&#039;]);
        $summary = &#039;Failed test: &#039; . $test-&gt;case-&gt;title;
        
        if ($context[&#039;test_count&#039;] &gt; 1)
        {
            $summary .= &#039; (+others)&#039;;
        }
        
        return $summary;
    }
    
    private function _get_description_default($context)
    {
        if ($context[&#039;test_change&#039;]-&gt;comment)
        {
            $comment = $context[&#039;test_change&#039;]-&gt;comment;
            $comment .= &quot;\n&quot;;
        }
        else 
        {
            $comment = &#039;&#039;;
        }
        
        $tests = $context[&#039;tests&#039;];
        foreach ($tests as $test)
        {
            $comment .= &quot;\nTest: &quot;;
            $comment .= $test-&gt;case-&gt;title;
            $comment .= &quot;\n&quot;;
            $comment .= $test-&gt;url;
        }
        
        return $comment;
    }
    
    private function _to_id_name_lookup($items)
    {
        $result = array();
        foreach ($items as $item)
        {
            $result[$item-&gt;id] = $item-&gt;name;
        }
        return $result;
    }
    
    public function prepare_field($context, $input, $field)
    {
        $data = array();
        
        // Take into account the preferences of the user, but only
        // for the initial form rendering (not for dynamic loads).
        if ($context[&#039;event&#039;] == &#039;prepare&#039;)
        {
            $prefs = arr::get($context, &#039;preferences&#039;);
        }
        else
        {
            $prefs = null;
        }

        // Process those fields that do not need a connection to the
        // Jira installation.        
        if ($field == &#039;summary&#039; || $field == &#039;description&#039; || $field == &#039;buildaffected&#039;)
        {
            switch ($field)
            {
                case &#039;summary&#039;:
                    $data[&#039;default&#039;] = $this-&gt;_get_summary_default(
                        $context);
                    break;
                    
                case &#039;description&#039;:
                    $data[&#039;default&#039;] = $this-&gt;_get_description_default(
                        $context);
                    break;
                    
                case &#039;buildaffected&#039;:
                    $data[&#039;default&#039;] = arr::get($prefs, &#039;buildaffected&#039;);
                    break;
            }
        
            return $data;
        }
                
        // And then try to connect/login (in case we haven&#039;t set up a
        // working connection previously in this request) and process
        // the remaining fields.
        $api = $this-&gt;_get_api($context);
        
        switch ($field)
        {
            case &#039;type&#039;:
                $data[&#039;options&#039;] = $this-&gt;_to_id_name_lookup(
                    $api-&gt;get_types()
                );
                
                // Select the stored preference or the first item in
                // the list otherwise.
                $default = arr::get($prefs, &#039;type&#039;);
                if ($default)
                {
                    $data[&#039;default&#039;] = $default;
                }
                else
                {
                    if ($data[&#039;options&#039;])
                    {
                        $data[&#039;default&#039;] = key($data[&#039;options&#039;]);
                    }
                }                
                break;

            case &#039;project&#039;:
                $data[&#039;default&#039;] = arr::get($prefs, &#039;project&#039;);
                $data[&#039;options&#039;] = $this-&gt;_to_id_name_lookup(
                    $api-&gt;get_projects()
                );
                break;

            case &#039;component&#039;:
                if (isset($input[&#039;project&#039;]))
                {
                    $data[&#039;default&#039;] = arr::get($prefs, &#039;component&#039;);
                    $data[&#039;options&#039;] = $this-&gt;_to_id_name_lookup(
                        $api-&gt;get_components($input[&#039;project&#039;])
                    );
                }
                break;
        }
        
        return $data;
    }
    
    public function validate_push($context, $input)
    {
    }    
    
    public function push($context, $input)
    {
        $api = $this-&gt;_get_api();
        
        $data = array();
        $data[&#039;summary&#039;] = $input[&#039;summary&#039;];
        $data[&#039;type&#039;] = $input[&#039;type&#039;];
        $data[&#039;project&#039;] = $input[&#039;project&#039;];
        $data[&#039;component&#039;] = $input[&#039;component&#039;];
        $data[&#039;description&#039;] = $input[&#039;description&#039;];
        $data[&#039;customFieldValues&#039;] = array(
            array(
                &#039;customfieldId&#039; =&gt; &#039;customfield_10103&#039;,
                &#039;values&#039; =&gt; array($input[&#039;buildaffected&#039;])
            )
        );
        
        return $api-&gt;add_issue($data);
    }
    
    // *********************************************************
    // LOOKUP
    // *********************************************************
    
    public function lookup($defect_id)
    {
        $api = $this-&gt;_get_api();
        $issue = $api-&gt;get_issue($defect_id);
        
        $attributes = array();
        
        // Add some important attributes for the issue such as the
        // issue type, current status and project. Note that the
        // attribute values (and description) support HTML and we
        // thus need to escape possible HTML characters (with &#039;h&#039;)
        // in this plugin.
        
        if (isset($issue-&gt;type))
        {
            $t = arr::get(
                obj::get_lookup($api-&gt;get_types()), 
                $issue-&gt;type
            );
            
            if ($t)
            {
                $attributes[&#039;Type&#039;] = h($t-&gt;name);
            }
        }

        $status = &#039;&#039;;
        if (isset($issue-&gt;status))
        {
            $s = arr::get(
                obj::get_lookup($api-&gt;get_statuses()),
                $issue-&gt;status
            );
            
            if ($s)
            {
                $attributes[&#039;Status&#039;] = h($s-&gt;name);
                $status = $s-&gt;name;
            }
        }

        if (isset($issue-&gt;project))
        {
            // Add a link to the project.
            $attributes[&#039;Project&#039;] = str::format(
                &#039;&lt;a target=&quot;_blank&quot; href=&quot;{0}browse/{1}&quot;&gt;{2}&lt;/a&gt;&#039;,
                a($this-&gt;_address),
                a($issue-&gt;project),
                h($issue-&gt;project)
            );
        }
        
        // Decide which status to return to TestRail based on the
        // resolution property of the issue (whether the issue was
        // resolved or not). The issue or statuses don&#039;t have any
        // additional meta information so that&#039;s unfortunately the
        // only distinction we can make for the status.
        $status_id = GI_DEFECTS_STATUS_OPEN;

        if (isset($issue-&gt;resolution))
        {
            if ($issue-&gt;resolution)
            {
                $status_id = GI_DEFECTS_STATUS_RESOLVED;
            }
        }
        
        // Format the description of the issue (we use a monospace
        // font).
        if (isset($issue-&gt;description) &amp;&amp; $issue-&gt;description)
        {
            $description = str::format(
                &#039;&lt;div class=&quot;monospace&quot;&gt;{0}&lt;/div&gt;&#039;,
                nl2br(
                    html::link_urls(
                        h($issue-&gt;description)
                    )
                )
            );
        }
        else
        {
            $description = null;
        }
        
        return array(
            &#039;id&#039; =&gt; $defect_id,
            &#039;url&#039; =&gt; str::format(
                &#039;{0}browse/{1}&#039;,
                $this-&gt;_address,
                $defect_id
            ),
            &#039;title&#039; =&gt; $issue-&gt;summary,
            &#039;status_id&#039; =&gt; $status_id,
            &#039;status&#039; =&gt; $status,
            &#039;description&#039; =&gt; $description,
            &#039;attributes&#039; =&gt; $attributes
        );
    }
}

/**
 * Jira API
 *
 * Wrapper class for the Jira API with login/logout and functions
 * for retrieving projects etc. from a Jira installation. Uses the
 * SOAP API of Jira.
 */
class Jira_api
{
    private $_soap;
    private $_token;
    
    /**
     * Construct
     *
     * Initializes a new Jira API object. Expects the web address
     * of the Jira installation including http or https prefix.
     */    
    public function __construct($address)
    {
        $address = str::slash($address);
        $this-&gt;_soap = new SoapClient(
            $address . &#039;rpc/soap/jirasoapservice-v2?wsdl&#039;,
            array(&#039;trace&#039; =&gt; true)
        );
    }
    
    private function _send_command($command, $data = array())
    {
        if (logger::is_on(GI_LOG_LEVEL_DEBUG))
        {
            logger::debugf(&#039;SOAP call: {0}&#039;, $command);
        }
        
        // Send along the token of the login, if available.
        if ($this-&gt;_token)
        {
            if ($data)
            {
                array_unshift($data, $this-&gt;_token);
            }
            else 
            {
                $data = array($this-&gt;_token);
            }
        }
        
        $result = $this-&gt;_soap-&gt;__soapCall($command, $data);
        
        // In case debug logging is enabled, we append the data
        // we&#039;ve sent and the entire request/response to the log.
        if (logger::is_on(GI_LOG_LEVEL_DEBUG))
        {
            logger::debugr(
                &#039;$soap&#039;,
                array(
                    &#039;request_headers&#039; =&gt; 
                        $this-&gt;_soap-&gt;__getLastRequestHeaders(),
                    &#039;request&#039; =&gt; 
                        $this-&gt;_soap-&gt;__getLastRequest(),
                    &#039;response_headers&#039; =&gt; 
                        $this-&gt;_soap-&gt;__getLastResponseHeaders(),
                    &#039;response&#039; =&gt; 
                        $this-&gt;_soap-&gt;__getLastResponse()
                )
            );
        }
        
        return $result;
    }
    
    /**
     * Login
     *
     * Logs in to the Jira installation using the provided user
     * and password.
     */    
    public function login($user, $password)
    {
        $data = array($user, $password);
        $this-&gt;_token = $this-&gt;_send_command(&#039;login&#039;, $data);
    }
    
    /**
     * Logout
     *
     * Logs the user out. You can use login() to log in again.
     */    
    public function logout()
    {
        $this-&gt;_send_command(&#039;logout&#039;);
        $this-&gt;_token = null;
    }

    /**
     * Get Types
     *
     * Returns a list of issue types for the Jira installation.
     * The issue types are returned as array of objects, each
     * with its ID and name.
     */    
    public function get_types()
    {
        $response = $this-&gt;_send_command(&#039;getIssueTypes&#039;);
        
        if (!$response)
        {
            return array();
        }
        
        $result = array();
        foreach ($response as $type)
        {
            $t = obj::create();
            $t-&gt;id = (string) $type-&gt;id;
            $t-&gt;name = (string) $type-&gt;name;
            $result[] = $t;
        }
        
        return $result;
    }
    
    /**
     * Get Statuses
     *
     * Returns a list of statuses for the Jira installation.
     * The statuses are returned as array of objects, each with
     * its ID and name.
     */    
    public function get_statuses()
    {
        $response = $this-&gt;_send_command(&#039;getStatuses&#039;);
        
        if (!$response)
        {
            return array();
        }
        
        $result = array();
        foreach ($response as $status)
        {
            $s = obj::create();
            $s-&gt;id = (string) $status-&gt;id;
            $s-&gt;name = (string) $status-&gt;name;
            $result[] = $s;
        }
        
        return $result;
    }
    
    /**
     * Get Projects
     *
     * Returns a list of projects for the Jira installation. The
     * projects are returned as array of objects, each with its ID
     * and name.
     */    
    public function get_projects()
    {
        $response = $this-&gt;_send_command(&#039;getProjectsNoSchemes&#039;);
        
        if (!$response)
        {
            return array();
        }
        
        $result = array();
        foreach ($response as $project)
        {
            $p = obj::create();
            $p-&gt;id = (string) $project-&gt;key;
            $p-&gt;name = (string) $project-&gt;name;
            $result[] = $p;
        }
        
        return $result;
    }
    
    /**
     * Get Components
     *
     * Returns a list of components for the given project for the Jira
     * installation. Components are returned as array of objects, each
     * with its ID and name.
     */
    public function get_components($project_id)
    {
        $data = array($project_id);
        $response = $this-&gt;_send_command(&#039;getComponents&#039;, $data);

        if (!$response)
        {
            return array();
        }
        
        $result = array();
        foreach ($response as $component)
        {
            $c = obj::create();
            $c-&gt;id = (string) $component-&gt;id;
            $c-&gt;name = (string) $component-&gt;name;
            $result[] = $c;
        }
        
        return $result;
    }
    
    /**
     * Get Issue
     *
     * Gets an existing case from the Jira installation and returns
     * it. The resulting issue object has various properties such
     * as the summary, description, project etc.
     */     
    public function get_issue($issue_id)
    {
        $data = array($issue_id);
        return $this-&gt;_send_command(&#039;getIssue&#039;, $data);
    }
        
    /**
     * Add Issue
     *
     * Adds a new issue to the Jira installation with the given
     * parameters (title, project etc.) and returns its ID. The
     * parameters must be named according to the Jira API format,
     * e.g.:
     *
     * summary:     The summary of the new issue
     * type:        The ID of the type of the new issue (bug,
     *              feature request etc.)
     * project:     The ID of the project the issue should be added
     *              to
     * component:   The ID of the component the issue should be
     *              added to
     * description: The description of the new issue
     */    
    public function add_issue($options)
    {
        if (isset($options[&#039;component&#039;]))
        {
            // Jira requires an array of components instead of a
            // single component.
            $options[&#039;components&#039;] = array(
                array(&#039;id&#039; =&gt; $options[&#039;component&#039;])
            );
        }
        
        $data = array($options);
        $response = $this-&gt;_send_command(&#039;createIssue&#039;, $data);
        return $response-&gt;key;
    }
}

class JiraException extends Exception
{
}

// Check for the soap PHP module/extensions that is required by
// this plugin.
if (!class_exists(&#039;SoapClient&#039;, false))
{
    throw new JiraException(
        &#039;The Jira defect plugin requires the soap PHP extension
which has not yet been installed.&#039;
    );
}</code></pre></div><p>Thanks in advance.</p>]]></summary>
			<author>
				<name><![CDATA[JBandura]]></name>
				<uri>http://forum.gurock.com/user/762/</uri>
			</author>
			<updated>2012-05-01T16:45:51Z</updated>
			<id>http://forum.gurock.com/topic/874/push-custom-with-user-mapping/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Formatting not working in some cases]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/873/formatting-not-working-in-some-cases/new/posts/"/>
			<summary type="html"><![CDATA[<p>I want to bold the word TEST_WINCOMP_VER so I wrote my test step like this:<br /></p><div class="quotebox"><blockquote><p>7. Edit the **TEST_WINCOMP_VER** value.</p></blockquote></div><p>The output looks like this though:<br /><span class="postimg"><img src="http://dl.dropbox.com/u/13053740/text.png" alt="PunBB bbcode test" /></span></p><p>It should not be italic and it should not remove the underscores from my database value. Looks like a bug?</p>]]></summary>
			<author>
				<name><![CDATA[cksv]]></name>
				<uri>http://forum.gurock.com/user/745/</uri>
			</author>
			<updated>2012-04-30T18:01:39Z</updated>
			<id>http://forum.gurock.com/topic/873/formatting-not-working-in-some-cases/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Feature Request: Move action buttons to the top.]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/872/feature-request-move-action-buttons-to-the-top/new/posts/"/>
			<summary type="html"><![CDATA[<p>When I view a test case, the previous/next, print, and edit items are at the top.&nbsp; However, when I edit a test case, the save/cancel buttons are at the bottom.</p><p>I&#039;d like to request that these be moved to occupy the same area as the prev/next &amp;c items.&nbsp; I wrote a Greasemonkey script that does this, which I can email in if you&#039;d like.</p><p>Thanks!</p>]]></summary>
			<author>
				<name><![CDATA[CSchelin]]></name>
				<uri>http://forum.gurock.com/user/761/</uri>
			</author>
			<updated>2012-04-30T13:50:34Z</updated>
			<id>http://forum.gurock.com/topic/872/feature-request-move-action-buttons-to-the-top/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Test Runs comprising test cases across various test suites]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/871/test-runs-comprising-test-cases-across-various-test-suites/new/posts/"/>
			<summary type="html"><![CDATA[<p>Hi,</p><p>Is there a possibility to add one test run to include test cases belonging to various test suites???</p><p>It will be a very interesting feature and we are in need of this for our testing.</p>]]></summary>
			<author>
				<name><![CDATA[Vijaya]]></name>
				<uri>http://forum.gurock.com/user/749/</uri>
			</author>
			<updated>2012-04-30T05:57:30Z</updated>
			<id>http://forum.gurock.com/topic/871/test-runs-comprising-test-cases-across-various-test-suites/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Feature request: Organize test suites manually]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/870/feature-request-organize-test-suites-manually/new/posts/"/>
			<summary type="html"><![CDATA[<p>Please add the ability to drag and move test suites just like you can with test cases. I don&#039;t want them to be organized alphabetically. I want to group them based on my own preference.</p>]]></summary>
			<author>
				<name><![CDATA[cksv]]></name>
				<uri>http://forum.gurock.com/user/745/</uri>
			</author>
			<updated>2012-04-25T01:09:17Z</updated>
			<id>http://forum.gurock.com/topic/870/feature-request-organize-test-suites-manually/new/posts/</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[New testrail API needed?]]></title>
			<link rel="alternate" href="http://forum.gurock.com/topic/869/new-testrail-api-needed/new/posts/"/>
			<summary type="html"><![CDATA[<p>When I make a request for the API like </p><p>http://myserver/testrail/index.php?/miniapi/get_test/10833&amp;key=MySecret Key</p><p>I get the response {&quot;result&quot;:false,&quot;error&quot;:&quot;Your client version of TestRail does not match the server version (2.5.1.1623). Please refresh this page.&quot;}</p><p>The testrail api is still the same as the 2.4 version , which was downloaded at at <a href="http://code.gurock.com/p/testrail-miniapi/downloads/19/">http://code.gurock.com/p/testrail-miniapi/downloads/19/</a></p><p>Is there a new API that needs to be installed for the new version of TestRail that&#039;s not available on the API download page yet?</p>]]></summary>
			<author>
				<name><![CDATA[mvrooman]]></name>
				<uri>http://forum.gurock.com/user/494/</uri>
			</author>
			<updated>2012-04-24T23:00:46Z</updated>
			<id>http://forum.gurock.com/topic/869/new-testrail-api-needed/new/posts/</id>
		</entry>
</feed>

