main
  1<?xml version="1.0" encoding="utf-8"?>
  2<!--
  3  This stylesheet is used for all HTML detail reports.
  4  It can be rendered in any of the following modes.
  5  
  6  Document / Fragment:
  7      A report can either be rendered a self-contained document or as
  8      a fragment meant to be included in another document.
  9  
 10  HTML / XHTML:
 11      A report can either be rendered in HTML or in XHTML syntax.
 12      
 13  One very important characteristic of the report is that while it uses JavaScript,
 14  it does not require it.  All of the report's contents may be accessed without error
 15  or serious inconvenience even with JavaScript disabled.  This is extremely important
 16  for Visual Studio integration since the IE browser prevents execution of scripts
 17  in local files by default.
 18-->
 19<xsl:stylesheet version="1.0"
 20                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 21                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 22                xmlns:g="http://www.gallio.org/"
 23                xmlns="http://www.w3.org/1999/xhtml">
 24  <xsl:template match="g:report" mode="xhtml-document">
 25    <html xml:lang="en" lang="en" dir="ltr">
 26      <head>
 27        <title>Gallio Test Report</title>
 28        <link rel="stylesheet" type="text/css" href="{$cssDir}Gallio-Report.css" />
 29        <script type="text/javascript" src="{$jsDir}Gallio-Report.js">
 30          <xsl:comment> comment inserted for Internet Explorer </xsl:comment>
 31        </script>
 32        <style type="text/css">
 33html
 34{
 35	overflow: auto;
 36}
 37        </style>
 38      </head>
 39      <body class="gallio-report">
 40        <xsl:apply-templates select="." mode="xhtml-body" />
 41      </body>
 42    </html>
 43  </xsl:template>
 44  
 45  <xsl:template match="g:report" mode="html-document">
 46    <xsl:call-template name="strip-namespace">
 47      <xsl:with-param name="nodes"><xsl:apply-templates select="." mode="xhtml-document" /></xsl:with-param>
 48    </xsl:call-template>
 49  </xsl:template>
 50
 51  <xsl:template match="g:report" mode="xhtml-fragment">
 52    <div class="gallio-report">
 53      <!-- Technically a link element should not appear outside of the "head"
 54           but most browsers tolerate it and this gives us better out of the box
 55           support in embedded environments like CCNet since no changes need to
 56           be made to the stylesheets of the containing application.
 57      -->
 58      <link rel="stylesheet" type="text/css" href="{$cssDir}Gallio-Report.css" />
 59      <style type="text/css">
 60html
 61{
 62	margin: 0px 0px 0px 0px;
 63	padding: 0px 17px 0px 0px;
 64	overflow: auto;
 65}
 66      </style>
 67      <script type="text/javascript" src="{$jsDir}Gallio-Report.js">
 68        <xsl:comment> comment inserted for Internet Explorer </xsl:comment>
 69      </script>
 70      
 71      <xsl:apply-templates select="." mode="xhtml-body" />
 72    </div>
 73  </xsl:template>
 74
 75  <xsl:template match="g:report" mode="html-fragment">
 76    <xsl:call-template name="strip-namespace">
 77      <xsl:with-param name="nodes"><xsl:apply-templates select="." mode="xhtml-fragment" /></xsl:with-param>
 78    </xsl:call-template>
 79  </xsl:template>
 80  
 81  <xsl:template match="g:report" mode="xhtml-body">
 82    <div id="Header" class="header">
 83      <div class="header-image"></div>
 84    </div>
 85    <div id="Navigator" class="navigator">
 86      <xsl:apply-templates select="g:testPackageRun" mode="navigator" />
 87    </div>
 88    <div id="Content" class="content">
 89      <xsl:apply-templates select="g:testPackageRun" mode="statistics" />
 90      <xsl:apply-templates select="g:testPackageConfig" mode="assemblies" />
 91      <xsl:apply-templates select="g:testModel/g:annotations" mode="annotations"/>
 92      <xsl:apply-templates select="g:testPackageRun" mode="summary"/>
 93      <xsl:apply-templates select="g:testPackageRun" mode="details"/>
 94    </div>
 95  </xsl:template>
 96  
 97  <xsl:template match="g:testPackageConfig" mode="assemblies">
 98    <div id="Assemblies" class="section">
 99      <h2>Assemblies</h2>
100      <div class="section-content">
101        <ul>
102          <xsl:for-each select="g:assemblyFiles/g:assemblyFile">
103            <li><xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="text()" /></xsl:call-template></li>
104          </xsl:for-each>
105        </ul>
106      </div>
107    </div>
108  </xsl:template>
109
110  <xsl:template match="g:annotations" mode="annotations">
111    <xsl:if test="g:annotation">
112      <div id="Annotations" class="section">
113        <h2>Annotations</h2>
114        <div class="section-content">
115          <ul>
116            <xsl:apply-templates select="g:annotation[@type='error']" mode="annotations"/>
117            <xsl:apply-templates select="g:annotation[@type='warning']" mode="annotations"/>
118            <xsl:apply-templates select="g:annotation[@type='info']" mode="annotations"/>
119          </ul>
120        </div>
121      </div>
122    </xsl:if>
123  </xsl:template>
124
125  <xsl:template match="g:annotation" mode="annotations">
126    <li>
127      <xsl:attribute name="class">annotation annotation-type-<xsl:value-of select="@type"/></xsl:attribute>
128      <div class="annotation-message">
129        <xsl:text>[</xsl:text><xsl:value-of select="@type"/><xsl:text>] </xsl:text>
130        <xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="@message" /></xsl:call-template>
131      </div>
132      
133      <xsl:if test="g:codeLocation/@path">
134        <div class="annotation-location">
135          <xsl:text>Location: </xsl:text>
136          <xsl:call-template name="format-code-location"><xsl:with-param name="codeLocation" select="g:codeLocation" /></xsl:call-template>
137        </div>
138      </xsl:if>
139      
140      <xsl:if test="g:codeReference/@assembly">
141        <div class="annotation-reference">
142          <xsl:text>Reference: </xsl:text>
143          <xsl:call-template name="format-code-reference"><xsl:with-param name="codeReference" select="g:codeReference" /></xsl:call-template>
144        </div>
145      </xsl:if>
146      
147      <xsl:if test="@details">
148        <div class="annotation-location">
149          <xsl:text>Details: </xsl:text>
150          <xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="@details" /></xsl:call-template>
151        </div>
152      </xsl:if>
153    </li>
154  </xsl:template>
155  
156  <xsl:template match="g:testPackageRun" mode="navigator">
157    <xsl:variable name="box-label"><xsl:call-template name="format-statistics"><xsl:with-param name="statistics" select="g:statistics" /></xsl:call-template></xsl:variable>
158    <a href="#Statistics" title="{$box-label}">
159      <xsl:attribute name="class">navigator-box <xsl:call-template name="status-from-statistics"><xsl:with-param name="statistics" select="g:statistics" /></xsl:call-template></xsl:attribute>
160    </a>
161
162    <div class="navigator-stripes">
163      <xsl:for-each select="descendant::g:testStepRun">
164        <xsl:variable name="status" select="g:result/g:outcome/@status"/>
165        <xsl:if test="$status != 'passed' and (g:testStep/@isTestCase = 'true' or not(g:children/g:testStepRun))">
166          <xsl:variable name="stripe-label"><xsl:value-of select="g:testStep/@name"/><xsl:text> </xsl:text><xsl:value-of select="$status"/>.</xsl:variable>
167          <a href="#testStepRun-{g:testStep/@id}" style="top:{position() * 98 div last() + 1}%" class="status-{$status}" title="{$stripe-label}">
168            <xsl:attribute name="onclick">
169              <xsl:text>expand([</xsl:text>
170              <xsl:for-each select="ancestor-or-self::g:testStepRun">
171                <xsl:if test="position() != 1">
172                  <xsl:text>,</xsl:text>
173                </xsl:if>
174                <xsl:text>'detailPanel-</xsl:text>
175                <xsl:value-of select="g:testStep/@id"/>
176                <xsl:text>'</xsl:text>
177              </xsl:for-each>
178              <xsl:text>]);</xsl:text>
179            </xsl:attribute>
180          </a>
181        </xsl:if>
182      </xsl:for-each>
183    </div>
184  </xsl:template>
185  
186  <xsl:template match="g:testPackageRun" mode="statistics">
187    <div id="Statistics" class="section">
188      <h2>Statistics</h2>
189      <div class="section-content">
190        <table class="statistics-table">
191          <tr>
192            <td class="statistics-label-cell">Start time:</td>
193            <td><xsl:call-template name="format-datetime"><xsl:with-param name="datetime" select="@startTime" /></xsl:call-template></td>
194          </tr>
195          <tr class="alternate-row">
196            <td class="statistics-label-cell">End time:</td>
197            <td><xsl:call-template name="format-datetime"><xsl:with-param name="datetime" select="@endTime" /></xsl:call-template></td>
198          </tr>
199          <xsl:apply-templates select="g:statistics" />
200        </table>
201      </div>
202    </div>
203  </xsl:template>
204
205  <xsl:template match="g:statistics">
206    <tr>
207      <td class="statistics-label-cell">Tests:</td>
208      <td><xsl:value-of select="@testCount" /> (<xsl:value-of select="@stepCount" /> steps)</td>
209    </tr>
210    <tr class="alternate-row">
211      <td class="statistics-label-cell">Results:</td>
212      <td><xsl:call-template name="format-statistics"><xsl:with-param name="statistics" select="." /></xsl:call-template></td>
213    </tr>
214    <tr>
215      <td class="statistics-label-cell">Duration:</td>
216      <td><xsl:value-of select="format-number(@duration, '0.00')" />s</td>
217    </tr>
218    <tr class="alternate-row">
219      <td class="statistics-label-cell">Assertions:</td>
220      <td><xsl:value-of select="@assertCount" /></td>
221    </tr>
222  </xsl:template>
223
224  <xsl:template match="g:testPackageRun" mode="summary">
225    <div id="Summary" class="section">
226      <h2>Summary<xsl:if test="$condensed"> (Condensed)</xsl:if></h2>
227      <div class="section-content">
228        <xsl:choose>
229          <xsl:when test="g:testStepRun/g:children/g:testStepRun">
230            <xsl:choose>
231              <xsl:when test="not($condensed) or g:testStepRun/g:result/g:outcome/@status!='passed'">
232                <ul>
233                  <xsl:apply-templates select="g:testStepRun/g:children/g:testStepRun" mode="summary" />
234                </ul>
235              </xsl:when>
236              <xsl:otherwise>
237                <em>All tests passed.</em>
238              </xsl:otherwise>
239            </xsl:choose>
240          </xsl:when>
241          <xsl:otherwise>
242            <em>This report does not contain any test runs.</em>
243          </xsl:otherwise>
244        </xsl:choose>
245      </div>
246    </div>
247  </xsl:template>
248
249  <xsl:template match="g:testStepRun" mode="summary">
250    <xsl:variable name="id" select="g:testStep/@id" />
251    
252    <xsl:if test="g:testStep/@isTestCase='false' and (not($condensed) or g:result/g:outcome/@status!='passed')">
253      <xsl:variable name="statisticsRaw">
254        <xsl:call-template name="aggregate-statistics">
255          <xsl:with-param name="testStepRun" select="." />
256        </xsl:call-template>
257      </xsl:variable>
258      <xsl:variable name="statistics" select="msxsl:node-set($statisticsRaw)/g:statistics" />
259
260      <li>
261        <span>
262          <xsl:choose>
263            <xsl:when test="g:children/g:testStepRun/g:testStep/@isTestCase='false'">
264              <xsl:call-template name="toggle">
265                <xsl:with-param name="href">summaryPanel-<xsl:value-of select="$id"/></xsl:with-param>
266              </xsl:call-template>
267            </xsl:when>
268            <xsl:otherwise>
269              <xsl:call-template name="toggle-stop" />
270            </xsl:otherwise>
271          </xsl:choose>
272
273          <a href="#testStepRun-{$id}">
274            <xsl:attribute name="onclick">
275              <xsl:text>expand([</xsl:text>
276              <xsl:for-each select="ancestor-or-self::g:testStepRun">
277                <xsl:if test="position() != 1">
278                  <xsl:text>,</xsl:text>
279                </xsl:if>
280                <xsl:text>'detailPanel-</xsl:text>
281                <xsl:value-of select="g:testStep/@id"/>
282                <xsl:text>'</xsl:text>
283              </xsl:for-each>
284              <xsl:text>]);</xsl:text>
285            </xsl:attribute>
286            <xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="g:testStep/@name" /></xsl:call-template>
287          </a>
288
289          <xsl:call-template name="outcome-bar">
290            <xsl:with-param name="outcome" select="g:result/g:outcome" />
291            <xsl:with-param name="statistics" select="$statistics" />
292          </xsl:call-template>
293        </span>
294        
295        <div class="panel">
296          <xsl:if test="g:children/g:testStepRun">
297            <ul id="summaryPanel-{$id}">
298              <xsl:apply-templates select="g:children/g:testStepRun" mode="summary" />
299            </ul>
300          </xsl:if>
301        </div>
302      </li>
303    </xsl:if>
304  </xsl:template>
305
306  <xsl:template match="g:testPackageRun" mode="details">
307    <div id="Details" class="section">
308      <h2>Details<xsl:if test="$condensed"> (Condensed)</xsl:if></h2>
309      <div class="section-content">
310        <xsl:choose>
311          <xsl:when test="g:testStepRun/g:children/g:testStepRun">
312            <xsl:choose>
313              <xsl:when test="not($condensed) or g:testStepRun/g:result/g:outcome/@status!='passed'">
314                <ul class="testStepRunContainer">
315                  <xsl:apply-templates select="g:testStepRun/g:children/g:testStepRun" mode="details" />
316                </ul>
317              </xsl:when>
318              <xsl:otherwise>
319                <em>All tests passed.</em>
320              </xsl:otherwise>
321            </xsl:choose>
322          </xsl:when>
323          <xsl:otherwise>
324            <em>This report does not contain any test runs.</em>
325          </xsl:otherwise>
326        </xsl:choose>
327      </div>
328    </div>
329  </xsl:template>
330
331  <xsl:template match="g:testStepRun" mode="details">
332    <xsl:if test="not($condensed) or g:result/g:outcome/@status!='passed'">
333      <xsl:variable name="id" select="g:testStep/@id" />
334      <xsl:variable name="testId" select="g:testStep/@testId" />
335      <xsl:variable name="test" select="ancestor::g:report/g:testModel/descendant::g:test[@id = $testId]" />
336      
337      <xsl:variable name="metadataEntriesFromTest" select="$test/g:metadata/g:entry" />
338      <xsl:variable name="metadataEntriesFromTestStep" select="g:testStep/g:metadata/g:entry" />
339      
340      <xsl:variable name="kind" select="$metadataEntriesFromTest[@key='TestKind']/g:value" />    
341      <xsl:variable name="nestingLevel" select="count(ancestor::g:testStepRun)" />
342      
343      <xsl:variable name="statisticsRaw">
344        <xsl:call-template name="aggregate-statistics">
345          <xsl:with-param name="testStepRun" select="." />
346        </xsl:call-template>
347      </xsl:variable>
348      <xsl:variable name="statistics" select="msxsl:node-set($statisticsRaw)/g:statistics" />
349
350      <li id="testStepRun-{$id}">
351        <span class="testStepRunHeading testStepRunHeading-Level{$nestingLevel}">
352          <xsl:call-template name="toggle">
353            <xsl:with-param name="href">detailPanel-<xsl:value-of select="$id"/></xsl:with-param>
354          </xsl:call-template>
355          <!--
356          <xsl:call-template name="icon">
357            <xsl:with-param name="kind" select="$kind" />
358          </xsl:call-template>
359          -->
360
361          <xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="g:testStep/@name" /></xsl:call-template>
362
363          <xsl:call-template name="outcome-bar">
364            <xsl:with-param name="outcome" select="g:result/g:outcome" />
365            <xsl:with-param name="statistics" select="$statistics" />
366            <xsl:with-param name="small" select="not(g:children/g:testStepRun)" />
367          </xsl:call-template>
368        </span>
369
370        <div id="detailPanel-{$id}" class="panel">
371          <xsl:choose>
372            <xsl:when test="$kind = 'Assembly' or $kind = 'Framework'">
373              <table class="statistics-table">
374                <tr class="alternate-row">
375                  <td class="statistics-label-cell">Results:</td>
376                  <td><xsl:call-template name="format-statistics"><xsl:with-param name="statistics" select="$statistics" /></xsl:call-template></td>
377                </tr>
378                <tr>
379                  <td class="statistics-label-cell">Duration:</td>
380                  <td><xsl:value-of select="format-number($statistics/@duration, '0.00')" />s</td>
381                </tr>
382                <tr class="alternate-row">
383                  <td class="statistics-label-cell">Assertions:</td>
384                  <td><xsl:value-of select="$statistics/@assertCount" /></td>
385                </tr>
386              </table>
387            </xsl:when>
388            <xsl:otherwise>
389              <xsl:text>Duration: </xsl:text>
390              <xsl:value-of select="format-number($statistics/@duration, '0.00')" />
391              <xsl:text>s, Assertions: </xsl:text>
392              <xsl:value-of select="$statistics/@assertCount"/>
393              <xsl:text>.</xsl:text>
394            </xsl:otherwise>
395          </xsl:choose>
396
397          <xsl:choose>
398            <xsl:when test="g:testStep/@isPrimary='true'">
399              <xsl:call-template name="print-metadata-entries">
400                <xsl:with-param name="entries" select="$metadataEntriesFromTest|$metadataEntriesFromTestStep" />
401              </xsl:call-template>
402            </xsl:when>
403            <xsl:otherwise>
404              <xsl:call-template name="print-metadata-entries">
405                <xsl:with-param name="entries" select="$metadataEntriesFromTestStep" />
406              </xsl:call-template>
407            </xsl:otherwise>
408          </xsl:choose>
409
410          <div id="testStepRun-{g:testStepRun/g:testStep/@id}" class="testStepRun">
411            <xsl:apply-templates select="." mode="details-content" />
412          </div>
413
414          <xsl:choose>
415            <xsl:when test="g:children/g:testStepRun">
416              <ul class="testStepRunContainer">
417                <xsl:apply-templates select="g:children/g:testStepRun" mode="details" />
418              </ul>
419            </xsl:when>
420            <xsl:otherwise>
421              <xsl:call-template name="toggle-autoclose">
422                <xsl:with-param name="href">detailPanel-<xsl:value-of select="$id"/></xsl:with-param>
423              </xsl:call-template>
424            </xsl:otherwise>
425          </xsl:choose>
426        </div>
427      </li>
428    </xsl:if>
429  </xsl:template>
430
431  <xsl:template match="g:testStepRun" mode="details-content">
432    <xsl:apply-templates select="g:executionLog">
433      <xsl:with-param name="stepId" select="g:testStep/@id" />
434    </xsl:apply-templates>
435  </xsl:template>
436
437  <xsl:template match="g:metadata">
438    <xsl:call-template name="print-metadata-entries">
439      <xsl:with-param name="entries" select="g:entry" />
440    </xsl:call-template>
441  </xsl:template>
442
443  <xsl:template name="print-metadata-entries">
444    <xsl:param name="entries" />
445    <xsl:variable name="visibleEntries" select="$entries[@key != 'TestKind']" />
446
447    <xsl:if test="$visibleEntries">
448      <ul class="metadata">
449        <xsl:apply-templates select="$visibleEntries">
450          <xsl:sort select="translate(@key, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" lang="en" data-type="text" />
451          <xsl:sort select="translate(@value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" lang="en" data-type="text" />
452        </xsl:apply-templates>
453      </ul>
454    </xsl:if>
455  </xsl:template>
456
457  <xsl:template match="g:entry">
458    <li><xsl:value-of select="@key" />: <xsl:call-template name="print-text-with-breaks"><xsl:with-param name="text" select="g:value" /></xsl:call-template></li>
459  </xsl:template>
460
461  <xsl:template match="g:executionLog">
462    <xsl:param name="stepId" />
463
464    <xsl:if test="g:streams/g:stream">
465      <div id="log-{$stepId}" class="log">
466        <xsl:apply-templates select="g:streams/g:stream" mode="stream">
467          <xsl:with-param name="attachments" select="g:attachments" />
468        </xsl:apply-templates>
469        
470        <xsl:if test="g:attachments/g:attachment">
471          <div class="logAttachmentList">
472            Attachments: <xsl:for-each select="g:attachments/g:attachment">
473              <xsl:apply-templates select="." mode="link" /><xsl:if test="position() != last()">, </xsl:if>
474            </xsl:for-each>.
475          </div>
476        </xsl:if>
477      </div>
478    </xsl:if>
479  </xsl:template>
480
481  <xsl:template match="g:streams/g:stream" mode="stream">
482    <xsl:param name="attachments" />
483
484    <div class="logStream logStream-{@name}">
485      <span class="logStreamHeading">
486        <xsl:value-of select="@name" />
487      </span>
488
489      <xsl:apply-templates select="g:body" mode="stream">
490        <xsl:with-param name="attachments" select="$attachments" />
491      </xsl:apply-templates>
492    </div>
493  </xsl:template>
494
495  <xsl:template match="g:body" mode="stream">
496    <xsl:param name="attachments" />
497
498    <div class="logStreamBody">
499      <xsl:apply-templates select="g:contents" mode="stream">
500        <xsl:with-param name="attachments" select="$attachments" />
501      </xsl:apply-templates>
502    </div>
503  </xsl:template>
504
505  <xsl:template match="g:section" mode="stream">
506    <xsl:param name="attachments" />
507
508    <div class="logStreamSection">
509      <span class="logStreamSectionHeading">
510        <xsl:value-of select="@name"/>
511      </span>
512      <div>
513        <xsl:apply-templates select="g:contents" mode="stream">
514          <xsl:with-param name="attachments" select="$attachments" />
515        </xsl:apply-templates>
516      </div>
517    </div>
518  </xsl:template>
519
520  <xsl:template match="g:contents" mode="stream">
521    <xsl:param name="attachments" />
522
523    <xsl:apply-templates select="child::node()[self::g:text or self::g:section or self::g:embed]" mode="stream">
524      <xsl:with-param name="attachments" select="$attachments" />
525    </xsl:apply-templates>
526  </xsl:template>
527
528  <xsl:template match="g:text" mode="stream">
529    <xsl:param name="attachments" />
530
531    <div>
532      <xsl:call-template name="print-text-with-breaks">
533        <xsl:with-param name="text" select="text()" />
534      </xsl:call-template>
535    </div>
536  </xsl:template>
537
538  <xsl:template match="g:embed" mode="stream">
539    <xsl:param name="attachments" />
540    <xsl:variable name="attachmentName" select="@attachmentName" />
541    
542    <div class="logAttachmentEmbedding">
543      <xsl:apply-templates select="$attachments/g:attachment[@name=$attachmentName]" mode="embed" />
544    </div>
545  </xsl:template>
546
547  <xsl:template match="g:attachment" mode="embed">
548    <xsl:variable name="isImage" select="starts-with(@contentType, 'image/')" />
549    <xsl:choose>
550      <xsl:when test="$attachmentBrokerUrl != ''">
551        <xsl:variable name="attachmentBrokerQuery"><xsl:value-of select="$attachmentBrokerUrl"/>testStepId=<xsl:value-of select="../../../g:testStep/@id"/>&amp;attachmentName=<xsl:value-of select="@name"/></xsl:variable>
552        <xsl:choose>
553          <xsl:when test="$isImage">
554            <img src="{$attachmentBrokerQuery}" alt="Attachment: {@name}" />
555          </xsl:when>
556          <xsl:otherwise>
557            <xsl:text>Attachment: </xsl:text>
558            <a href="{$attachmentBrokerQuery}"><xsl:value-of select="@name" /></a>
559          </xsl:otherwise>
560        </xsl:choose>
561      </xsl:when>
562      <xsl:when test="@contentDisposition = 'link'">
563        <xsl:variable name="attachmentUri"><xsl:call-template name="path-to-uri"><xsl:with-param name="path" select="@contentPath" /></xsl:call-template></xsl:variable>
564        <xsl:choose>
565          <xsl:when test="$isImage">
566            <img src="{$attachmentUri}" alt="Attachment: {@name}" />
567          </xsl:when>
568          <xsl:otherwise>
569            <xsl:text>Attachment: </xsl:text>
570            <a href="{$attachmentUri}"><xsl:value-of select="@name" /></a>
571          </xsl:otherwise>
572        </xsl:choose>
573      </xsl:when>
574      <xsl:when test="@contentDisposition = 'inline' and $isImage and @encoding = 'base64'">
575        <img src="data:{@contentType};base64,{text()}" alt="Attachment: {@name}" />
576      </xsl:when>
577      <xsl:otherwise>
578        <xsl:text>Attachment: </xsl:text>
579        <xsl:value-of select="@name" />
580        <xsl:text> (n/a)</xsl:text>
581      </xsl:otherwise>
582    </xsl:choose>
583  </xsl:template>
584  
585  <xsl:template match="g:attachment" mode="link">
586    <xsl:choose>
587      <xsl:when test="$attachmentBrokerUrl != ''">
588        <xsl:variable name="attachmentBrokerQuery"><xsl:value-of select="$attachmentBrokerUrl"/>testStepId=<xsl:value-of select="../../../g:testStep/@id"/>&amp;attachmentName=<xsl:value-of select="@name"/></xsl:variable>
589        <a href="{$attachmentBrokerQuery}"><xsl:value-of select="@name" /></a>
590      </xsl:when>
591      <xsl:when test="@contentDisposition = 'link'">
592        <xsl:variable name="attachmentUri"><xsl:call-template name="path-to-uri"><xsl:with-param name="path" select="@contentPath" /></xsl:call-template></xsl:variable>
593        <a href="{$attachmentUri}"><xsl:value-of select="@name" /></a>
594      </xsl:when>
595      <xsl:otherwise>
596        <xsl:value-of select="@name" /> (n/a)
597      </xsl:otherwise>
598    </xsl:choose>
599  </xsl:template>
600
601  <!--
602  <xsl:template name="icon">
603    <xsl:param name="kind" />
604
605    <img>
606      <xsl:choose>
607        <xsl:when test="$kind = 'Fixture'">
608          <xsl:attribute name="src">{$imgDir}Fixture.png</xsl:attribute>
609          <xsl:attribute name="alt">Fixture Icon</xsl:attribute>
610        </xsl:when>
611        <xsl:when test="$kind = 'Test'">
612          <xsl:attribute name="src">{$imgDir}Test.png</xsl:attribute>
613          <xsl:attribute name="alt">Test Icon</xsl:attribute>
614        </xsl:when>
615        <xsl:otherwise>
616          <xsl:attribute name="src">{$imgDir}Container.png</xsl:attribute>
617          <xsl:attribute name="alt">Container Icon</xsl:attribute>
618        </xsl:otherwise>
619      </xsl:choose>
620    </img>
621  </xsl:template>
622  -->
623
624  <!-- Toggle buttons -->
625  <xsl:template name="toggle">
626    <xsl:param name="href" />
627    
628    <img src="{$imgDir}Minus.gif" class="toggle" id="toggle-{$href}" onclick="toggle('{$href}');" alt="Toggle Button" />
629  </xsl:template>
630  
631  <xsl:template name="toggle-stop">
632    <img src="{$imgDir}FullStop.gif" class="toggle" alt="Toggle Placeholder" />
633  </xsl:template>
634  
635  <xsl:template name="toggle-autoclose">
636    <xsl:param name="href" />
637    
638    <!-- Auto-close certain toggles by default when JavaScript is available -->
639    <script type="text/javascript">toggle('<xsl:value-of select="$href"/>');</script>
640  </xsl:template>
641  
642  <!-- Displays visual statistics using a status bar and outcome icons -->
643  <xsl:template name="outcome-bar">
644    <xsl:param name="outcome" />
645    <xsl:param name="statistics"/>
646    <xsl:param name="small" select="0" />
647
648    <table class="outcome-bar">
649      <tr>
650        <td>
651          <div>
652            <xsl:attribute name="class">outcome-bar status-<xsl:value-of select="$outcome/@status"/><xsl:if test="$small"> condensed</xsl:if></xsl:attribute>
653            <xsl:attribute name="title">
654              <xsl:choose>
655                <xsl:when test="$outcome/@category"><xsl:value-of select="$outcome/@category"/></xsl:when>
656                <xsl:otherwise><xsl:value-of select="$outcome/@status"/></xsl:otherwise>
657              </xsl:choose>
658            </xsl:attribute>
659          </div>
660        </td>
661      </tr>
662    </table>
663    
664    <xsl:if test="not($small)">
665      <span class="outcome-icons">
666        <img src="{$imgDir}Passed.gif" alt="Passed"/>
667        <xsl:value-of select="$statistics/@passedCount"/>
668        <img src="{$imgDir}Failed.gif" alt="Failed"/>
669        <xsl:value-of select="$statistics/@failedCount"/>
670        <img src="{$imgDir}Ignored.gif" alt="Inconclusive or Skipped"/>
671        <xsl:value-of select="$statistics/@inconclusiveCount + $statistics/@skippedCount" />            
672      </span>
673    </xsl:if>
674  </xsl:template>
675  
676  <xsl:template name="status-from-statistics">
677    <xsl:param name="statistics"/>
678    
679    <xsl:choose>
680      <xsl:when test="$statistics/@failedCount > 0">status-failed</xsl:when>
681      <xsl:when test="$statistics/@inconclusiveCount > 0">status-inconclusive</xsl:when>
682      <xsl:when test="$statistics/@passedCount > 0">status-passed</xsl:when>
683      <xsl:otherwise>status-skipped</xsl:otherwise>
684    </xsl:choose>
685  </xsl:template>
686  
687  <!-- Include the common report template -->
688  <xsl:include href="Gallio-Report.common.xsl" />  
689</xsl:stylesheet>