using NUnit.Framework;
using Meyn.TestLink;
using CookComputing.XmlRpc;

namespace BTS.Trac.Test
{
    [TestFixture]
    [TestLinkFixture(
        Url = TestLinkConnect.Url,
        ProjectName = TestLinkConnect.ProjectName,
        UserId = TestLinkConnect.UserId,
        TestPlan = TestLinkConnect.TestPlan,
        TestSuite = TestLinkConnect.TestSuite,
        DevKey = TestLinkConnect.DevKey )]
    public class ComponentTest
    {
        [SetUp]
        public void SetUp()
        {
            Trac.Connect( TracConnect.Url, TracConnect.UserName, TracConnect.Password );

            // 最初にすべて削除しておく
            string[] componentNames = Component.GetAll();
            foreach ( string componentName in componentNames ) {
                Component.Delete( componentName );
            }
        }

        [TearDown]
        public void TearDown()
        {
            Trac.Close();
        }

        [Test]
        public void コンポーネントの項目を取得する()
        {
            int count = 10;

            // 作成
            for ( int i = 0; i < count; ++i ) {
                string componentName = "Test" + i.ToString();
                Component component = new Component();
                component.Owner = "担当者" + i.ToString();
                component.Description = "詳細" + i.ToString();
                component.Create( componentName );
            }

            string[] componentNames = Component.GetAll();
            Assert.AreEqual( componentNames.Length, count );
        }

        [Test]
        public void コンポーネントの各項目を取得する()
        {
            int count = 10;
            string componentNameBase = "Test";

            // 作成
            for ( int i = 0; i < count; ++i ) {
                string componentName = componentNameBase + i.ToString();
                Component component = new Component();
                component.Owner = "担当者" + i.ToString();
                component.Description = "詳細" + i.ToString();
                component.Create( componentName );
            }

            // 作成数を確認
            string[] componentNames = Component.GetAll();
            Assert.AreEqual( componentNames.Length, count );

            for ( int i = 0; i < count; ++i ) {
                string componentName = componentNameBase + i.ToString();
                Component component = new Component( componentName );

                // 作成したものと取得したものが一致する
                Assert.AreEqual( component.Name, componentName );
                Assert.AreEqual( component.Owner, "担当者" + i.ToString() );
                Assert.AreEqual( component.Description, "詳細" + i.ToString() );
            }
        }

        [Test]
        public void コンポーネントを作成する()
        {
            string[] before = Component.GetAll();

            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            // コンポーネントの数が増えていること
            Assert.AreEqual( before.Length + 1, Component.GetAll().Length );

            // 取得したコンポーネントと一致すること
            Component getComponent = new Component( componentName );
            Assert.AreEqual( component.Name, getComponent.Name );
            Assert.AreEqual( component.Owner, getComponent.Owner );
            Assert.AreEqual( component.Description, getComponent.Description );
        }

        [Test]
        public void コンポーネントを詳細を更新する()
        {
            string[] before = Component.GetAll();

            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            // コンポーネントの数が増えていること
            Assert.AreEqual( before.Length + 1, Component.GetAll().Length );

            // 更新
            Component getComponent = new Component( componentName );
            component.Owner = "担当者更新";
            component.Description = "詳細更新";
            getComponent.Update();

            // 更新したコンポーネントと一致すること
            Component updateComponent = new Component( componentName );
            Assert.AreEqual( getComponent.Name, updateComponent.Name );
            Assert.AreEqual( getComponent.Owner, updateComponent.Owner );
            Assert.AreEqual( getComponent.Description, updateComponent.Description );
        }

        [Test]
        public void コンポーネントの名称を更新する()
        {
            string[] before = Component.GetAll();

            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            // コンポーネントの数が増えていること
            Assert.AreEqual( before.Length + 1, Component.GetAll().Length );

            // 更新
            string updateName = "名称を変更";
            Component getComponent = new Component( componentName );
            getComponent.Update( updateName );

            // 更新したコンポーネントと一致すること
            Component updateComponent = new Component( updateName );
            Assert.AreEqual( getComponent.Name, updateComponent.Name );
            Assert.AreEqual( getComponent.Owner, updateComponent.Owner );
            Assert.AreEqual( getComponent.Description, updateComponent.Description );
        }

        [Test]
        public void コンポーネントを削除する()
        {
            string[] before = Component.GetAll();

            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            // コンポーネントの数が増えていること
            Assert.AreEqual( before.Length + 1, Component.GetAll().Length );

            component.Delete();

            // コンポーネントの数が戻っていること
            Assert.AreEqual( before.Length, Component.GetAll().Length );
        }

        [Test]
        public void コンポーネントを削除するstatic版()
        {
            string[] before = Component.GetAll();

            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            // コンポーネントの数が増えていること
            Assert.AreEqual( before.Length + 1, Component.GetAll().Length );

            Component.Delete( componentName );

            // コンポーネントの数が戻っていること
            Assert.AreEqual( before.Length, Component.GetAll().Length );
        }

        [Test]
        [ExpectedException( typeof( XmlRpcFaultException ) )]
        public void 同じ名称のコンポーネントを作成すると例外が発生する()
        {
            // 作成
            string componentName = "Test";
            Component component = new Component();
            component.Owner = "担当者";
            component.Description = "詳細";
            component.Create( componentName );

            component.Owner = "担当者2";
            component.Description = "詳細2";
            component.Create( componentName );

            // 同じ名称のコンポーネントを作成すると例外が発生する
            Assert.Fail();
        }

        [Test]
        [ExpectedException( typeof( XmlRpcFaultException ) )]
        public void 登録されていない名称のコンポーネントを取得すると例外が発生する()
        {
            Component component = new Component( "存在しないコンポーネント" );

            // 登録されていない名称のコンポーネントを取得すると例外が発生する
            Assert.Fail();
        }

        [Test]
        [ExpectedException( typeof( XmlRpcFaultException ) )]
        public void 登録されていない名称のコンポーネントを更新すると例外が発生する()
        {
            Component component = new Component();
            component.Update();

            // 登録されていない名称のコンポーネントを更新すると例外が発生する
            Assert.Fail();
        }

        [Test]
        [ExpectedException( typeof( XmlRpcFaultException ) )]
        public void 登録されていない名称のコンポーネントを削除すると例外が発生する()
        {
            Component.Delete( "存在しないコンポーネント" );

            // 登録されていない名称のコンポーネントを削除すると例外が発生する
            Assert.Fail();
        }
    }
}
