/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codenarc.report

import org.codenarc.results.FileResults
import org.codenarc.rule.Rule
import org.codenarc.rule.StubRule
import org.codenarc.rule.unnecessary.UnnecessaryBooleanInstantiationRule
import org.codenarc.ruleset.ListRuleSet
import org.junit.Before
import org.junit.Test

import static org.codenarc.test.TestUtil.assertContainsAllInOrder

/**
 * Tests for HtmlReportWriter
 *
 * @author Chris Mair
 */
@SuppressWarnings('LineLength')
class HtmlReportWriterTest extends AbstractHtmlReportWriterTestCase {

    @Test
    void testDefaultProperties() {
        def newReportWriter = new HtmlReportWriter()
        assert newReportWriter.includeSummaryByPackage
        assert newReportWriter.includeRuleDescriptions
        assert newReportWriter.maxPriority == 3
        assert newReportWriter.defaultOutputFile == HtmlReportWriter.DEFAULT_OUTPUT_FILE
    }

    @Test
    void testWriteReport_DoesNotIncludeRuleDescriptionsForDisabledRules() {
        ruleSet = new ListRuleSet([
                new StubRule(name:'MyRuleXX', enabled:false),
                new StubRule(name:'MyRuleYY'),
                new StubRule(name:'MyRuleZZ', enabled:false)])
        analysisContext.ruleSet = ruleSet
        def reportText = getReportText()
        assert !reportText.contains('MyRuleXX')
        assert !reportText.contains('MyRuleZZ')
    }

    @Test
    void testWriteReport_IncludesRuleThatDoesNotSupportGetDescription() {
        analysisContext.ruleSet = new ListRuleSet([ [getName:{ 'RuleABC' }, getPriority: { 2 } ] as Rule])
        assertContainsAllInOrder(getReportText(), ['RuleABC', 'No description'])
    }

    @Test
    void testWriteReport() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'> </a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'> </a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'> </a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
            """
        assertReportFileContents(NEW_REPORT_FILE, EXPECTED)
    }

    @Test
    void testWriteReport_IncludeSummaryByPackage_False() {
        //<html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><a name='src/main'> </a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'> </a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'> </a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr></table></div><div class='summary'><a name='src/main'> </a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'> </a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'> </a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
            """
        reportWriter.includeSummaryByPackage = false
        assertReportFileContents(NEW_REPORT_FILE, EXPECTED)
    }

    @Test
    void testWriteReport_IncludeRuleDescriptions_False() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'> </a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'> </a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'> </a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div></body></html>
            """
        reportWriter.includeRuleDescriptions = false
        assertReportFileContents(NEW_REPORT_FILE, EXPECTED)
    }

    @Test
    void testWriteReport_SetTitle() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report: $TITLE</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td>$TITLE</td></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'> </a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'> </a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'> </a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
            """
        reportWriter.title = TITLE
        assertReportFileContents(NEW_REPORT_FILE, EXPECTED)
    }

    @Test
    void testWriteReport_MaxPriority1() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>2</td><td class='priority1'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td></tr><tr><td>src/main/code</td><td class='number'>2</td><td class='number'>-</td><td class='priority1'>-</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td></tr></table></div><div class='summary'><a name='src/main'></a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'></a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
            """
        reportWriter.maxPriority = 1
        assertReportContents(EXPECTED)
    }

    @Test
    void testWriteReport_Priority4() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th><th>Priority 4</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>4</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td><td class='priority4'>1</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>2</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td><td class='priority4'>1</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td><td class='priority4'>-</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td><td class='priority4'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td><td class='priority4'>-</td></tr></table></div><div class='summary'><a name='src/main'></a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'></a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'></a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE4'>RULE4</a></td><td class='priority4'>4</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='DuplicateImport'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority3'>DuplicateImport</td><td>Duplicate import statements are unnecessary.</td></tr><tr class='ruleDescriptions'><td><a name='ReturnFromFinallyBlock'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority2'>ReturnFromFinallyBlock</td><td>Returning from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='ThrowExceptionFromFinallyBlock'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority2'>ThrowExceptionFromFinallyBlock</td><td>Throwing an exception from a <em>finally</em> block is confusing and can hide the original exception.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>4</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryStringInstantiation'></a><span class='ruleIndex'>5</span></td><td class='ruleName priority3'>UnnecessaryStringInstantiation</td><td>Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.</td></tr></table></div></body></html>
            """
        def fileResults4 = new FileResults('src/main/MyActionTest.groovy', [VIOLATION4])
        dirResultsMain.addChild(fileResults4)
        reportWriter.maxPriority = 4
        assertReportContents(EXPECTED)
    }

    @Test
    void testWriteReport_NoDescriptionsForRuleIds() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'></a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'></a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'></a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='MyRuleXX'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority0'>MyRuleXX</td><td>No description provided for rule named [MyRuleXX]</td></tr><tr class='ruleDescriptions'><td><a name='MyRuleYY'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority0'>MyRuleYY</td><td>No description provided for rule named [MyRuleYY]</td></tr></table></div></body></html>
            """
        ruleSet = new ListRuleSet([new StubRule(name:'MyRuleXX'), new StubRule(name:'MyRuleYY')])
        reportWriter.customMessagesBundleName = 'DoesNotExist'
        analysisContext.ruleSet = ruleSet
        assertReportContents(EXPECTED)
    }

    @Test
    void testWriteReport_RuleDescriptionsProvidedInCodeNarcMessagesFile() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'></a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'></a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'></a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='MyRuleXX'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority0'>MyRuleXX</td><td>HTML Rule XX</td></tr><tr class='ruleDescriptions'><td><a name='MyRuleYY'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority0'>MyRuleYY</td><td>My Rule YY</td></tr><tr class='ruleDescriptions'><td><a name='UnnecessaryBooleanInstantiation'></a><span class='ruleIndex'>3</span></td><td class='ruleName priority3'>UnnecessaryBooleanInstantiation</td><td>Use <em>Boolean.valueOf()</em> for variable values or <em>Boolean.TRUE</em> and <em>Boolean.FALSE</em> for constant values instead of calling the <em>Boolean()</em> constructor directly or calling <em>Boolean.valueOf(true)</em> or <em>Boolean.valueOf(false)</em>.</td></tr></table></div></body></html>
            """
        def biRule = new UnnecessaryBooleanInstantiationRule()
        ruleSet = new ListRuleSet([new StubRule(name:'MyRuleXX'), new StubRule(name:'MyRuleYY'), biRule])
        analysisContext.ruleSet = ruleSet
        assertReportContents(EXPECTED)
    }

    @Test
    void testWriteReport_RuleDescriptionsSetDirectlyOnTheRule() {
        final EXPECTED = """
            <html><head><title>CodeNarc Report</title><style type='text/css'>$cssFileContents</style></head><body><img class='logo' src='$LOGO_FILE' alt='CodeNarc' align='right'/><h1>CodeNarc Report</h1><div class='metadata'><table><tr><td class='em'>Report title:</td><td/></tr><tr><td class='em'>Date:</td><td>Feb 24, 2011 9:32:38 PM</td></tr><tr><td class='em'>Generated with:</td><td><a href='${CODENARC_URL}'>CodeNarc v0.12</a></td></tr></table></div><div class='summary'><h2>Summary</h2><table><tr class='tableHeader'><th>Package</th><th>Total Files</th><th>Files with Violations</th><th>Priority 1</th><th>Priority 2</th><th>Priority 3</th></tr><tr><td class='allPackages'>All Packages</td><td class='number'>10</td><td class='number'>3</td><td class='priority1'>3</td><td class='priority2'>2</td><td class='priority3'>3</td></tr><tr><td><a href='#src/main'>src/main</a></td><td class='number'>1</td><td class='number'>1</td><td class='priority1'>2</td><td class='priority2'>1</td><td class='priority3'>2</td></tr><tr><td><a href='#src/main/code'>src/main/code</a></td><td class='number'>2</td><td class='number'>1</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>1</td></tr><tr><td><a href='#src/main/test'>src/main/test</a></td><td class='number'>3</td><td class='number'>1</td><td class='priority1'>1</td><td class='priority2'>1</td><td class='priority3'>-</td></tr><tr><td>src/main/test/noviolations</td><td class='number'>4</td><td class='number'>-</td><td class='priority1'>-</td><td class='priority2'>-</td><td class='priority3'>-</td></tr></table></div><div class='summary'><a name='src/main'></a><h2 class='packageHeader'>Package: src.main</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;MyAction.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/code'></a><h2 class='packageHeader'>Package: src.main.code</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyAction2.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE3'>RULE3</a></td><td class='priority3'>3</td><td class='number'>333</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>throw new Exception() // Some very long message 12345678..901234567890</span></p><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>Other info</span></p></td></tr></table></div><div class='summary'><a name='src/main/test'></a><h2 class='packageHeader'>Package: src.main.test</h2></div><div class='summary'><h3 class='fileHeader'>&#x27A5;&nbsp;src/main/MyActionTest.groovy</h3><table border='1'><tr class='tableHeader'><th>Rule Name</th><th>Priority</th><th>Line #</th><th>Source Line / Message</th></tr><tr><td><a href='#RULE1'>RULE1</a></td><td class='priority1'>1</td><td class='number'>111</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[SRC]</span><span class='sourceCode'>if (file) {</span></p></td></tr><tr><td><a href='#RULE2'>RULE2</a></td><td class='priority2'>2</td><td class='number'>222</td><td><p class='violationInfo'><span class='violationInfoPrefix'>[MSG]</span><span class='violationMessage'>bad stuff</span></p></td></tr></table></div><div class='summary'><h2>Rule Descriptions</h2><table border='1'><tr class='tableHeader'><th class='ruleDescriptions'>#</th><th class='ruleDescriptions'>Rule Name</th><th class='ruleDescriptions'>Description</th></tr><tr class='ruleDescriptions'><td><a name='MyRuleXX'></a><span class='ruleIndex'>1</span></td><td class='ruleName priority0'>MyRuleXX</td><td>description77</td></tr><tr class='ruleDescriptions'><td><a name='MyRuleYY'></a><span class='ruleIndex'>2</span></td><td class='ruleName priority0'>MyRuleYY</td><td>description88</td></tr></table></div></body></html>
            """
        ruleSet = new ListRuleSet([
            new StubRule(name:'MyRuleXX', description:'description77'),
            new StubRule(name:'MyRuleYY', description:'description88')])
        analysisContext.ruleSet = ruleSet
        assertReportContents(EXPECTED)
    }

    //------------------------------------------------------------------------------------
    // Setup and helper methods
    //------------------------------------------------------------------------------------

    @Before
    void setUpHtmlReportWriterTest() {
        reportWriter = new HtmlReportWriter(outputFile:NEW_REPORT_FILE)
        reportWriter.metaClass.getFormattedTimestamp << { 'Feb 24, 2011 9:32:38 PM' }
        reportWriter.metaClass.getCodeNarcVersion << { '0.12' }
    }

}
