// Copyright (c) 2007 Omer Rauchwerger (a.k.a rauchy) (omer@rauchy.net)
// All rights reserved.
//
// This file is part of Regionerate.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Rauchy.Regionerate.Domain.Entities;
using Rhino.Mocks;
namespace Rauchy.Regionerate.Shared.Components.Rendering.Tests
{
///
/// Tests the class.
///
public abstract class RegionRendererTests
{
#region Data Members (10)
private CodeLayout.Configuration _defaultConfiguration;
private CodeLayout.RenderingOptions _defaultRenderingOptions;
private Symbol _defaultSymbolParameter;
private MockRepository _mockRepository;
private const bool DefaultShowCountParameter = true;
private const int DefaultTabAmountParameter = 2;
private const bool DefaultUseTabsParameter = true;
private const int DefaultSpaceAmountParameter = 0;
protected const string RegionTitle = "My Region";
protected Region Region
{
get;
set;
}
#endregion Data Members
#region Initialization (2)
// [rgn] Public Methods (10)
[ TestFixtureSetUp ]
public void Initialize()
{
_defaultSymbolParameter = new HiddenDragon();
_defaultRenderingOptions = new CodeLayout.RenderingOptions( DefaultShowCountParameter,
DefaultTabAmountParameter,
DefaultUseTabsParameter,
DefaultSpaceAmountParameter);
_defaultConfiguration = new CodeLayout.Configuration(_defaultSymbolParameter, _defaultRenderingOptions,
null );
}
[ SetUp ]
public void SetUp()
{
_mockRepository = new MockRepository();
Region = new Region {Title = RegionTitle, PadFirstChild = 1, PadLastChild = 1};
}
#endregion Initialization
#region Tests (8)
///
/// Region children should be counted recursively. In this test, two Field objects
/// will be a memebers of an inner region and the result of the outer region count should be 2.
///
[ Test ]
public void RecursivelyCountsChildrenCorrectly()
{
const int expectedChildrenCount = 2;
Region innerRegion = new Region {Title = "Inner Region", PadFirstChild = 1, PadLastChild = 1};
Field field1 = new Field();
field1.SetStringRepresentation( "public int _myField1;" );
innerRegion.Children.Add( field1 );
Field field2 = new Field();
field2.SetStringRepresentation( "public int _myField2;" );
innerRegion.Children.Add( field2 );
Region.Children.Add( innerRegion );
string renderedRegion = Render( Region, expectedChildrenCount );
IList lines = renderedRegion.GetLines();
VerifyHeader( lines, expectedChildrenCount );
VerifyFooter( lines );
}
[ Test ]
public void RendersAnEmptyRegion()
{
const int expectedChildrenCount = 0;
string renderedRegion = Render( Region, expectedChildrenCount );
IList lines = renderedRegion.GetLines();
VerifyHeader( lines, expectedChildrenCount );
VerifyFooter( lines );
}
[ Test ]
public void RendersARegionWithASingleChild()
{
const int expectedChildrenCount = 1;
Field field = new Field();
field.SetStringRepresentation( "public int _myField" );
Region.Children.Add( field );
string renderedRegion = Render( Region, expectedChildrenCount );
IList lines = renderedRegion.GetLines();
VerifyHeader( lines, expectedChildrenCount );
VerifyBody( lines, Region.Children );
VerifyFooter( lines );
}
[ Test ]
public void RendersARegionWithMultipleChildren()
{
const int expectedChildrenCount = 2;
Field field = new Field();
field.SetStringRepresentation( "public int _myField" );
Region.Children.Add( field );
Property property = new Property();
property.SetStringRepresentation( "public int Foo { get; set; }" );
Region.Children.Add( property );
string renderedRegion = Render( Region, expectedChildrenCount );
IList lines = renderedRegion.GetLines();
VerifyHeader( lines, expectedChildrenCount );
VerifyBody( lines, Region.Children );
VerifyFooter( lines );
}
[ Test ]
[ ExpectedException( typeof ( ArgumentOutOfRangeException ) ) ]
public void ShouldNotAcceptNegativeTabAmount()
{
CodeLayout.Configuration configuration = new CodeLayout.Configuration( _defaultSymbolParameter,
new CodeLayout.RenderingOptions(
DefaultShowCountParameter, -1,
DefaultUseTabsParameter,
DefaultSpaceAmountParameter),
null);
CreateConcreteRenderer( configuration );
}
[ Test ]
[ ExpectedException( typeof ( ArgumentNullException ) ) ]
public void ShouldNotAttemptToRenderNulls()
{
RegionRenderer renderer = CreateConcreteRenderer( _defaultConfiguration );
renderer.Render( null );
}
///
/// Since non-functional code (such as separators) should not be counted, this test
/// adds two code blocks (one functional and the other non-functional) and verifies that
/// the counts only the functional one.
///
[ Test ]
public void ShouldNotCountNonFunctionalCode()
{
const int expectedChildrenCount = 1;
Field field = new Field();
field.SetStringRepresentation( "public int _myField;" );
Region.Children.Add( field );
UnrecognizedCode unrecognizedCode = new UnrecognizedCode();
unrecognizedCode.SetStringRepresentation( "I am so non-functional!" );
Region.Children.Add( unrecognizedCode );
string renderedRegion = Render( Region, expectedChildrenCount );
IList lines = renderedRegion.GetLines();
VerifyHeader( lines, expectedChildrenCount );
VerifyBody( lines, Region.Children );
VerifyFooter( lines );
}
[ Test ]
public void TabifiesDeclarations()
{
bool showCount = true;
int numberOfTabs = 3;
bool useTabs = true;
int spaces = 9;
CodeLayout.RenderingOptions renderingOptions = new CodeLayout.RenderingOptions( showCount, numberOfTabs, useTabs, spaces );
const int expectedChildrenCount = 0;
string renderedRegion = Render(Region, expectedChildrenCount, renderingOptions);
IList lines = renderedRegion.GetLines();
VerifyHeader(lines, expectedChildrenCount, renderingOptions);
VerifyFooter(lines, renderingOptions);
}
[Test]
public void SpacifiesDeclarations()
{
bool showCount = true;
int numberOfTabs = 3;
bool useTabs = false;
int spaces = 9;
CodeLayout.RenderingOptions renderingOptions = new CodeLayout.RenderingOptions(showCount, numberOfTabs, useTabs, spaces);
const int expectedChildrenCount = 0;
string renderedRegion = Render(Region, expectedChildrenCount, renderingOptions);
IList lines = renderedRegion.GetLines();
VerifyHeader(lines, expectedChildrenCount, renderingOptions);
VerifyFooter(lines, renderingOptions);
}
#endregion Tests
#region Helper Methods (9)
// [rgn] Protected Methods (8)
protected abstract RegionRenderer CreateConcreteRenderer( CodeLayout.Configuration configuration );
///
/// Extracts the lines that are not region headers or footers.
///
protected abstract IList ExtractBody( IList lines );
protected string Render( Region region, int expectedMemberCount )
{
return Render( region, expectedMemberCount, _defaultRenderingOptions );
}
// [rgn] Private Methods (1)
private string Render(Region region, int expectedMemberCount, CodeLayout.RenderingOptions renderingOptions)
{
Symbol mockedSymbol = _mockRepository.Stub();
using ( _mockRepository.Record() )
{
// Setup an expectation for the header to be embedded.
string expectedRegionTitle = RegionTitle + string.Format( " ({0})", expectedMemberCount );
Expect.Call( mockedSymbol.Embed( expectedRegionTitle ) ).Return( " " + expectedRegionTitle );
// Setup an expectation for the footer to be embedded.
// (Does not contain children count like the last expectation).
Expect.Call( mockedSymbol.Embed( RegionTitle ) ).Return( " " + RegionTitle );
}
CodeLayout.Configuration configuration = new CodeLayout.Configuration( mockedSymbol, renderingOptions, null);
RegionRenderer renderer = CreateConcreteRenderer(configuration);
string renderedRegion;
using ( _mockRepository.Playback() )
{
renderedRegion = renderer.Render( region );
}
_mockRepository.Verify( mockedSymbol );
return renderedRegion;
}
protected void VerifyBody( IList lines, IList code )
{
IList body = ExtractBody( lines );
// Assuming all Code objects in "code" are one-liners.
Assert.AreEqual( code.Count, body.Count );
for ( int i = 0; i < body.Count; i++ )
{
Assert.AreEqual( body[ i ], code[ i ] + Environment.NewLine );
}
}
protected void VerifyFooter( IList lines )
{
VerifyFooter( lines, _defaultRenderingOptions );
}
protected abstract void VerifyFooter(IList lines, CodeLayout.RenderingOptions renderingOptions);
protected void VerifyHeader( IList lines, int? expectedChildrenCount )
{
VerifyHeader(lines, expectedChildrenCount, _defaultRenderingOptions);
}
protected abstract void VerifyHeader(IList lines, int? expectedChildrenCount, CodeLayout.RenderingOptions renderingOptions);
#endregion Helper Methods
}
}