public async Task Success()
        {
            // Arrange
            var    options = DatabaseSetup.CreateContextOptions();
            string userId  = new Guid().ToString();

            // Act
            var games = new GameService(options);
            var first = await games.AddCampaign("A campaign", userId);

            Assert.NotNull(first);

            var second = await games.AddCampaign("Another campaign", userId);

            Assert.NotNull(second);

            // Assert
            using (var db = new DatabaseContext(options))
            {
                Assert.Equal(2, db.Campaigns.Count());

                var firstCampaign = await db.Campaigns.FirstAsync();

                Assert.Equal("A campaign", firstCampaign.Name);
                Assert.Equal(userId, firstCampaign.GmUserId);

                var secondCampaign = await db.Campaigns.LastAsync();

                Assert.Equal("Another campaign", secondCampaign.Name);
                Assert.Equal(userId, secondCampaign.GmUserId);
            }
        }
        public async Task Success_IsGM()
        {
            // Arrange
            var          options      = DatabaseSetup.CreateContextOptions();
            const string expectedUser = "******";
            var          campaigns    = new List <Campaign>
            {
                new Campaign
                {
                    Name     = "A campaign",
                    GmUserId = expectedUser
                },
                new Campaign
                {
                    Name     = "Another campaign",
                    GmUserId = expectedUser
                }
            };

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.AddRange(campaigns);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(campaigns.Count, changes);
            }

            // Act
            var games  = new GameService(options);
            var result = await games.ListCampaigns(expectedUser);

            // Assert
            Assert.Equal(campaigns.Count, result.Count());
        }
        public async Task Success_HasCharacter()
        {
            // Arrange
            var          options      = DatabaseSetup.CreateContextOptions();
            const string expectedUser = "******";
            var          campaigns    = new List <Campaign>
            {
                new Campaign
                {
                    Name       = "A campaign",
                    GmUserId   = "Some random dude",
                    Characters = new List <Character>
                    {
                        new Character
                        {
                            BaseStrength  = 10,
                            BaseDexterity = 10,
                            BaseMind      = 10,
                            Class         = Micro20ClassType.Cleric,
                            Race          = Micro20RaceType.Dwarf,
                            Level         = 1,
                            UserId        = expectedUser
                        }
                    }
                },
                new Campaign
                {
                    Name       = "Another campaign",
                    GmUserId   = "Some random dude",
                    Characters = new List <Character>
                    {
                        new Character
                        {
                            BaseStrength  = 10,
                            BaseDexterity = 10,
                            BaseMind      = 10,
                            Class         = Micro20ClassType.Cleric,
                            Race          = Micro20RaceType.Dwarf,
                            Level         = 1,
                            UserId        = expectedUser
                        }
                    }
                }
            };

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.AddRange(campaigns);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(4, changes);
            }

            // Act
            var games  = new GameService(options);
            var result = await games.ListCampaigns(expectedUser);

            // Assert
            Assert.Equal(campaigns.Count, result.Count());
        }
        public async Task Success_InvalidUser()
        {
            // Arrange
            var          options      = DatabaseSetup.CreateContextOptions();
            const string creator      = "A User ID";
            const string unauthorized = "A different ID";
            var          campaigns    = new List <Campaign>
            {
                new Campaign
                {
                    Name     = "A campaign",
                    GmUserId = creator
                },
                new Campaign
                {
                    Name     = "Another campaign",
                    GmUserId = creator
                }
            };

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.AddRange(campaigns);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(campaigns.Count, changes);
            }

            // Act
            var games  = new GameService(options);
            var result = await games.ListCampaigns(unauthorized);

            // Assert
            Assert.Equal(0, result.Count());
        }
        public async Task Success_WithCampaign()
        {
            // Arrange
            var          options  = DatabaseSetup.CreateContextOptions();
            const string userId   = "The Best ID";
            const string name     = "My Character";
            var          campaign = new Campaign
            {
                GmUserId   = userId,
                Name       = "A campaign",
                Characters = new List <Character>
                {
                    new Character
                    {
                        Name          = name,
                        UserId        = userId,
                        BaseStrength  = 10,
                        BaseDexterity = 10,
                        BaseMind      = 10,
                        Class         = Micro20ClassType.Fighter,
                        Race          = Micro20RaceType.Human,
                        Level         = 1
                    }
                }
            };
            IEnumerable <CharacterSheet> sheets = null;
            Type eType = null;

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.Add(campaign);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(2, changes);
            }

            // Act
            var games = new GameService(options);

            try
            {
                using (var db = new DatabaseContext(options))
                {
                    sheets = await games.ListCharacters(userId);
                }
            }
            catch (DataNotCreatedException e)
            {
                eType = e.GetType();
            }

            // Assert
            Assert.NotNull(sheets);
            Assert.Null(eType);
            Assert.Equal(1, sheets.Count());
        }
        public async Task Success_HasCharacter()
        {
            // Arrange
            var          options      = DatabaseSetup.CreateContextOptions();
            const string expectedUser = "******";
            CampaignView result       = null;
            Type         eType        = null;

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.Add(new Campaign
                {
                    Name       = "A campaign",
                    GmUserId   = "Some random dude",
                    Characters = new List <Character>
                    {
                        new Character
                        {
                            BaseStrength  = 10,
                            BaseDexterity = 10,
                            BaseMind      = 10,
                            Class         = Micro20ClassType.Cleric,
                            Race          = Micro20RaceType.Dwarf,
                            Level         = 1,
                            UserId        = expectedUser
                        }
                    }
                });
                int changes = await db.SaveChangesAsync();

                Assert.Equal(2, changes);
            }

            // Act
            using (var db = new DatabaseContext(options))
            {
                var games      = new GameService(options);
                var campaignId = (await db.Campaigns.FirstAsync()).CampaignId;

                try
                {
                    result = await games.GetCampaign(campaignId, expectedUser);
                }
                catch (Exception e)
                {
                    eType = e.GetType();
                }
            }


            // Assert
            Assert.NotNull(result);
            Assert.Null(eType);
        }
        public async Task Success_WithoutCampaign()
        {
            // Arrange
            var          options = DatabaseSetup.CreateContextOptions();
            const string userId  = "The Best ID";
            const string name    = "My Character";
            Guid?        result  = null;
            Type         eType   = null;

            // Act
            var games     = new GameService(options);
            var character = new NewCharacter
            {
                Name       = name,
                Strength   = 10,
                Dexterity  = 10,
                Mind       = 10,
                CampaignId = null,
                Class      = Micro20ClassType.Fighter,
                Race       = Micro20RaceType.Human
            };

            try
            {
                result = await games.CreateCharacter(character, userId, true);
            }
            catch (DataNotCreatedException e)
            {
                eType = e.GetType();
            }

            // Assert
            Assert.NotNull(result);
            Assert.Null(eType);
            using (var db = new DatabaseContext(options))
            {
                Assert.Equal(1, db.Characters.Count());

                var dbCharacter = await db.Characters.SingleAsync();

                Assert.Equal(result, dbCharacter.CharacterId);
                Assert.Equal(character.Strength, dbCharacter.BaseStrength);
                Assert.Equal(character.Dexterity, dbCharacter.BaseDexterity);
                Assert.Equal(character.Mind, dbCharacter.BaseMind);
                Assert.Equal(character.Race, dbCharacter.Race);
                Assert.Equal(character.Class, dbCharacter.Class);
                Assert.Null(dbCharacter.CampaignId);
                Assert.Equal(userId, dbCharacter.UserId);
                Assert.Equal(1, dbCharacter.Level);
            }
        }
        public async Task Fail_BadCharacterData(string name, int str, int dex, int mind, int classType, int raceType)
        {
            // Arrange
            var          options  = DatabaseSetup.CreateContextOptions();
            const string userId   = "A user id";
            var          campaign = new Campaign
            {
                GmUserId = userId,
                Name     = "A campaign"
            };
            Type ex     = null;
            Guid?result = null;

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.Add(campaign);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(1, changes);
            }

            // Act
            var games     = new GameService(options);
            var character = new NewCharacter
            {
                Name       = name,
                Strength   = str,
                Dexterity  = dex,
                Mind       = mind,
                CampaignId = campaign.CampaignId,
                Class      = (Micro20ClassType)classType,
                Race       = (Micro20RaceType)raceType
            };

            try
            {
                result = await games.CreateCharacter(character, userId, true);
            }
            catch (ValidationException e)
            {
                ex = e.GetType();
            }

            // Assert
            Assert.Null(result);
            Assert.NotNull(ex);
            using (var db = new DatabaseContext(options))
            {
                Assert.False(db.Characters.Any());
            }
        }
        public async Task Success_InvalidUser()
        {
            // Arrange
            var          options      = DatabaseSetup.CreateContextOptions();
            const string expectedUser = "******";
            const string unauthorized = "A different ID";
            CampaignView result       = null;
            Type         eType        = null;
            var          campaigns    = new List <Campaign>
            {
                new Campaign
                {
                    Name     = "A campaign",
                    GmUserId = expectedUser
                },
                new Campaign
                {
                    Name     = "Another campaign",
                    GmUserId = expectedUser
                }
            };

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.AddRange(campaigns);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(campaigns.Count, changes);
            }

            // Act
            using (var db = new DatabaseContext(options))
            {
                var games      = new GameService(options);
                var campaignId = (await db.Campaigns.FirstAsync()).CampaignId;

                try
                {
                    result = await games.GetCampaign(campaignId, unauthorized);
                }
                catch (Exception e)
                {
                    eType = e.GetType();
                }
            }

            // Assert
            Assert.Null(result);
            Assert.NotNull(eType);
            Assert.Equal(typeof(UnauthorizedException), eType);
        }
        public async Task GM_RemoveCharacters()
        {
            // Arrange
            var          options        = DatabaseSetup.CreateContextOptions();
            const string gm             = "User1";
            const string pleb           = "User2";
            var          games          = new GameService(options);
            var          user1Campaigns = await InsertTestCampaigns(options, gm);

            var campaign   = user1Campaigns.First();
            var characters = new List <Character>();

            characters.AddRange(await InsertTestCharacters(options, campaign.CampaignId, gm));
            characters.AddRange(await InsertTestCharacters(options, campaign.CampaignId, pleb));
            var removals = characters.Where(c => c.CampaignId == campaign.CampaignId).ToList();

            // Act
            // lonelyCharacters will contain two characters with null campaigns, only one belongs to pleb
            var change = await games.ModifyCampaign(campaign.CampaignId, gm, new CampaignModification
            {
                RemoveCharacters = removals.Select(c => c.CharacterId).ToList()
            });

            // Assert
            using (var db = new DatabaseContext(options))
            {
                // characters got moved to new campaign
                var camChars = await db.Characters.Where(c => c.CampaignId == campaign.CampaignId).ToListAsync();

                Assert.Equal(0, camChars.Count);

                // characters were removed from past campaigns
                var nullChars = await db.Characters.Where(c => c.CampaignId == null).ToListAsync();

                Assert.Equal(4, nullChars.Count);

                // Name is not modified
                string camName = (await db.Campaigns.SingleAsync(c => c.CampaignId == campaign.CampaignId)).Name;
                Assert.Equal(campaign.Name, camName);

                // correct view is returned
                Assert.Equal(campaign.CampaignId, change.CampaignId);
            }
        }
        public async Task Success_WithCampaign()
        {
            // Arrange
            var          options  = DatabaseSetup.CreateContextOptions();
            const string userId   = "The Best ID";
            const string name     = "My Character";
            var          campaign = new Campaign
            {
                GmUserId   = userId,
                Name       = "A campaign",
                Characters = new List <Character>
                {
                    new Character
                    {
                        Name          = name,
                        UserId        = userId,
                        BaseStrength  = 10,
                        BaseDexterity = 10,
                        BaseMind      = 10,
                        Class         = Micro20ClassType.Fighter,
                        Race          = Micro20RaceType.Human,
                        Level         = 1
                    }
                }
            };
            CharacterSheet sheet = null;
            Type           eType = null;

            using (var db = new DatabaseContext(options))
            {
                db.Campaigns.Add(campaign);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(2, changes);
            }

            // Act
            var games = new GameService(options);

            try
            {
                using (var db = new DatabaseContext(options))
                {
                    var character = await db.Characters.SingleAsync();

                    sheet = await games.GetCharacter(character.CharacterId, userId);
                }
            }
            catch (DataNotCreatedException e)
            {
                eType = e.GetType();
            }

            // Assert
            Assert.NotNull(sheet);
            Assert.Null(eType);
            using (var db = new DatabaseContext(options))
            {
                Assert.Equal(1, db.Characters.Count());

                var character = await db.Characters.SingleAsync();

                Assert.Equal(character.CharacterId, sheet.Details.CharacterId);
                Assert.Equal(character.BaseStrength, sheet.BaseStats.Strength);
                Assert.Equal(1, sheet.Modifiers.Strength);
                Assert.Equal(character.BaseDexterity, sheet.BaseStats.Dexterity);
                Assert.Equal(1, sheet.Modifiers.Dexterity);
                Assert.Equal(character.BaseMind, sheet.BaseStats.Mind);
                Assert.Equal(1, sheet.Modifiers.Mind);
                Assert.Equal(character.Race, sheet.Details.Race);
                Assert.Equal(character.Class, sheet.Details.Class);
                Assert.Equal(userId, sheet.Details.UserId);
                Assert.Equal(1, sheet.Details.Level);
            }
        }
        public async Task Success()
        {
            // Arrange
            var          options   = DatabaseSetup.CreateContextOptions();
            const string userId    = "The Best ID";
            const string hairColor = "Brown";
            var          character = new Character
            {
                BaseStrength  = 10,
                BaseDexterity = 10,
                BaseMind      = 10,
                Class         = Micro20ClassType.Cleric,
                Race          = Micro20RaceType.Dwarf,
                Level         = 1,
                UserId        = userId
            };
            bool?result = null;
            Type eType  = null;

            using (var db = new DatabaseContext(options))
            {
                db.Characters.Add(character);
                int changes = await db.SaveChangesAsync();

                Assert.Equal(1, changes);
            }

            // Act
            var games = new GameService(options);

            try
            {
                var m1 = new CharacterModification {
                    Dexterity = 12
                };
                result = await games.ModifyCharacter(character.CharacterId, m1, userId, true);

                Assert.True(result);

                var m2 = new CharacterModification {
                    HairColor = hairColor
                };
                result = await games.ModifyCharacter(character.CharacterId, m2, userId, true);

                Assert.True(result);
            }
            catch (Exception e) when(e is DataNotFoundException || e is ValidationException)
            {
                eType = e.GetType();
            }

            // Assert
            Assert.NotNull(result);
            Assert.Null(eType);
            using (var db = new DatabaseContext(options))
            {
                Assert.Equal(1, db.Characters.Count());

                var dbCharacter = await db.Characters.SingleAsync();

                Assert.Equal(hairColor, dbCharacter.HairColor);
                Assert.Equal(10, dbCharacter.BaseStrength);
                Assert.Equal(12, dbCharacter.BaseDexterity);
                Assert.Equal(10, dbCharacter.BaseMind);
                Assert.Equal(Micro20RaceType.Dwarf, dbCharacter.Race);
                Assert.Equal(Micro20ClassType.Cleric, dbCharacter.Class);
                Assert.Equal(userId, dbCharacter.UserId);
                Assert.Equal(1, dbCharacter.Level);
            }
        }