Skip to content

Commit

Permalink
Add VerifySortingOptions UI Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
brminnick committed Mar 16, 2020
1 parent b1a013a commit b2f16d5
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 31 deletions.
2 changes: 2 additions & 0 deletions GitTrends.Shared/Constants/SortingConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace GitTrends.Shared
{
class SortingConstants
{
public const SortingOption DefaultSortingOption = SortingOption.Stars;

readonly static Lazy<Dictionary<SortingOption, string>> _sortingOptionsDictionaryHolder = new Lazy<Dictionary<SortingOption, string>>(CreateSortingDictionary);

public static Dictionary<SortingOption, string> SortingOptionsDictionary => _sortingOptionsDictionaryHolder.Value;
Expand Down
8 changes: 5 additions & 3 deletions GitTrends.Shared/Models/Interfaces/IRepository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Collections.Generic;

namespace GitTrends.Shared
namespace GitTrends.Shared
{
interface IRepository
{
Expand All @@ -12,5 +10,9 @@ interface IRepository
string Description { get; }
long ForkCount { get; }
string Url { get; }
public long TotalViews { get; }
public long TotalUniqueViews { get; }
public long TotalClones { get; }
public long TotalUniqueClones { get; }
}
}
3 changes: 1 addition & 2 deletions GitTrends.Shared/Models/Repository.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
Expand Down
8 changes: 8 additions & 0 deletions GitTrends.UITests/Models/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ public class Repository : IRepository
public string OwnerAvatarUrl { get; set; } = string.Empty;

public string Url { get; set; } = string.Empty;

public long TotalViews { get; set; }

public long TotalUniqueViews { get; set; }

public long TotalClones { get; set; }

public long TotalUniqueClones { get; set; }
}
}
18 changes: 17 additions & 1 deletion GitTrends.UITests/Pages/RepositoryPage.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using GitTrends.Mobile.Shared;
using GitTrends.Shared;
using Newtonsoft.Json;
using Xamarin.UITest;
using Query = System.Func<Xamarin.UITest.Queries.AppQuery, Xamarin.UITest.Queries.AppQuery>;
Expand All @@ -10,12 +11,13 @@ namespace GitTrends.UITests
class RepositoryPage : BasePage
{
readonly Query _searchBar, _settingsButton, _collectionView, _refreshView,
_androidContextMenuOverflowButton, _androidSearchBarButton;
_androidContextMenuOverflowButton, _androidSearchBarButton, _sortButton;

public RepositoryPage(IApp app) : base(app, PageTitles.RepositoryPage)
{
_searchBar = GenerateMarkedQuery(RepositoryPageAutomationIds.SearchBar);
_settingsButton = GenerateMarkedQuery(RepositoryPageAutomationIds.SettingsButton);
_sortButton = GenerateMarkedQuery(RepositoryPageAutomationIds.SortButton);
_collectionView = GenerateMarkedQuery(RepositoryPageAutomationIds.CollectionView);
_refreshView = GenerateMarkedQuery(RepositoryPageAutomationIds.RefreshView);
_androidContextMenuOverflowButton = x => x.Class("androidx.appcompat.widget.ActionMenuPresenter$OverflowMenuButton");
Expand All @@ -24,6 +26,20 @@ public RepositoryPage(IApp app) : base(app, PageTitles.RepositoryPage)

public void TriggerPullToRefresh() => App.InvokeBackdoorMethod(BackdoorMethodConstants.TriggerPullToRefresh);

public void SetSortingOption(SortingOption sortingOption)
{
if (App.Query(_androidContextMenuOverflowButton).Any())
{
App.Tap(_androidContextMenuOverflowButton);
App.Screenshot("Tapped Android Search Bar Button");
}

App.Tap(_sortButton);
App.Screenshot("Sort Button Tapped");

App.Tap(SortingConstants.SortingOptionsDictionary[sortingOption]);
}

public void TapRepository(string repositoryName)
{
App.ScrollDownTo(repositoryName);
Expand Down
63 changes: 62 additions & 1 deletion GitTrends.UITests/Tests/RepositoriesTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GitTrends.Mobile.Shared;
using GitTrends.Shared;
using NUnit.Framework;
using Xamarin.UITest;

Expand All @@ -17,6 +19,65 @@ public RepositoriesTests(Platform platform, UserType userType) : base(platform,
{
}

[TestCase(SortingConstants.DefaultSortingOption)]
[TestCase(SortingOption.Clones)]
[TestCase(SortingOption.Forks)]
[TestCase(SortingOption.Issues)]
[TestCase(SortingOption.Stars)]
[TestCase(SortingOption.UniqueClones)]
[TestCase(SortingOption.UniqueViews)]
[TestCase(SortingOption.Views)]
public void VerifySortingOptions(SortingOption sortingOption)
{
//Arrange
Repository finalTopRepository;
Repository finalSecondTopRepository;
Repository initialTopRepository = RepositoryPage.GetVisibleRepositoryList().First();
Repository initialSecondTopRepository = RepositoryPage.GetVisibleRepositoryList().Skip(1).First();

//Act
RepositoryPage.SetSortingOption(sortingOption);

//Assert
finalTopRepository = RepositoryPage.GetVisibleRepositoryList().First();
finalSecondTopRepository = RepositoryPage.GetVisibleRepositoryList().Skip(1).First();

Assert.GreaterOrEqual(initialTopRepository.StarCount, initialSecondTopRepository.StarCount);

Assert.AreNotEqual(initialTopRepository, finalTopRepository);
Assert.AreNotEqual(initialSecondTopRepository, finalSecondTopRepository);
Assert.AreNotEqual(initialTopRepository, initialSecondTopRepository);
Assert.AreNotEqual(finalTopRepository, finalSecondTopRepository);

switch (sortingOption)
{
case SortingOption.Stars:
Assert.LessOrEqual(finalTopRepository.StarCount, finalSecondTopRepository.StarCount);
break;
case SortingOption.Clones:
Assert.GreaterOrEqual(finalTopRepository.TotalClones, finalSecondTopRepository.TotalClones);
break;
case SortingOption.Forks:
Assert.GreaterOrEqual(finalTopRepository.ForkCount, finalSecondTopRepository.ForkCount);
break;
case SortingOption.Issues:
Assert.GreaterOrEqual(finalTopRepository.IssuesCount, finalSecondTopRepository.IssuesCount);
break;
case SortingOption.UniqueClones:
Assert.GreaterOrEqual(finalTopRepository.TotalUniqueClones, finalSecondTopRepository.TotalUniqueClones);
break;
case SortingOption.UniqueViews:
Assert.GreaterOrEqual(finalTopRepository.TotalUniqueViews, finalSecondTopRepository.TotalUniqueViews);
break;
case SortingOption.Views:
Assert.GreaterOrEqual(finalTopRepository.TotalViews, finalSecondTopRepository.TotalViews);
break;
default:
throw new NotSupportedException();

};
}

[Test]
public async Task VerifyRepositoriesAfterLogin()
{
Expand Down
14 changes: 13 additions & 1 deletion GitTrends/Database/RepositoryDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ class RepositoryDatabaseModel : IRepository

public bool IsFork { get; set; }

public long TotalViews { get; set; }

public long TotalUniqueViews { get; set; }

public long TotalClones { get; set; }

public long TotalUniqueClones { get; set; }

public static explicit operator Repository(RepositoryDatabaseModel repositoryDatabaseModel)
{
return new Repository(repositoryDatabaseModel.Name,
Expand All @@ -110,7 +118,11 @@ public static implicit operator RepositoryDatabaseModel(Repository repository)
Name = repository.Name,
OwnerAvatarUrl = repository.OwnerAvatarUrl,
OwnerLogin = repository.OwnerLogin,
IsFork = repository.IsFork
IsFork = repository.IsFork,
TotalClones = repository.TotalClones,
TotalUniqueClones = repository.TotalUniqueClones,
TotalViews = repository.TotalViews,
TotalUniqueViews = repository.TotalUniqueViews,
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion GitTrends/Pages/RepositoryPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public RepositoryPage(RepositoryViewModel repositoryViewModel,
Text = "Sort",
IconImageSource = "Sort",
Order = Device.RuntimePlatform is Device.Android ? ToolbarItemOrder.Secondary : ToolbarItemOrder.Default,
AutomationId = RepositoryPageAutomationIds.SettingsButton,
AutomationId = RepositoryPageAutomationIds.SortButton,
};
sortToolbarItem.Clicked += HandleSortToolbarItemCliked;
ToolbarItems.Add(sortToolbarItem);
Expand Down
2 changes: 1 addition & 1 deletion GitTrends/Services/SortingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public bool IsReversed

public SortingOption CurrentOption
{
get => (SortingOption)Preferences.Get(nameof(CurrentOption), (int)SortingOption.Stars);
get => (SortingOption)Preferences.Get(nameof(CurrentOption), (int)SortingConstants.DefaultSortingOption);
set => Preferences.Set(nameof(CurrentOption), (int)value);
}

Expand Down
39 changes: 23 additions & 16 deletions GitTrends/ViewModels/RepositoryViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
using Autofac;
using GitTrends.Shared;
using Refit;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace GitTrends
{
Expand Down Expand Up @@ -57,6 +59,8 @@ public event EventHandler<PullToRefreshFailedEventArgs> PullToRefreshFailed
public ICommand FilterRepositoriesCommand { get; }
public ICommand SortRepositoriesCommand { get; }

public bool IsNotRefreshing => !IsRefreshing;

public IReadOnlyList<Repository> VisibleRepositoryList
{
get => _visibleRepositoryList;
Expand All @@ -66,7 +70,7 @@ public IReadOnlyList<Repository> VisibleRepositoryList
public bool IsRefreshing
{
get => _isRefreshing;
set => SetProperty(ref _isRefreshing, value);
set => SetProperty(ref _isRefreshing, value, () => MainThread.InvokeOnMainThreadAsync(() => OnPropertyChanged(nameof(IsNotRefreshing))));
}

async Task ExecutePullToRefreshCommand(string repositoryOwner)
Expand All @@ -77,24 +81,26 @@ async Task ExecutePullToRefreshCommand(string repositoryOwner)
{
await foreach (var retrievedRepositories in _gitHubGraphQLApiService.GetRepositories(repositoryOwner, repositoriesPerFetch).ConfigureAwait(false))
{
var completedRepoitories = new List<Repository>();
AddRepositoriesToCollection(retrievedRepositories, _searchBarText);
}

var completedRepoitories = new List<Repository>();
await foreach (var retrievedRepositoriesWithViewsAndClonesData in GetRepositoryWithViewsAndClonesData(_repositoryList.ToList()).ConfigureAwait(false))
{
_repositoryDatabase.SaveRepository(retrievedRepositoriesWithViewsAndClonesData).SafeFireAndForget();
completedRepoitories.Add(retrievedRepositoriesWithViewsAndClonesData);

await foreach (var retrievedRepositoriesWithViewsAndClonesData in GetRepositoryWithViewsAndClonesData(retrievedRepositories.ToList()).ConfigureAwait(false))
//Limit the VisibleRepositoryList Updates to avoid overworking the UI Thread
if (!GitHubAuthenticationService.IsDemoUser
&& completedRepoitories.Count > repositoriesPerFetch / 20)
{
_repositoryDatabase.SaveRepository(retrievedRepositoriesWithViewsAndClonesData).SafeFireAndForget();
completedRepoitories.Add(retrievedRepositoriesWithViewsAndClonesData);

//Limit the VisibleRepositoryList Updates to avoid overworking the UI Thread
if (completedRepoitories.Count > repositoriesPerFetch / 10)
{
AddRepositoriesToCollection(completedRepoitories, _searchBarText);
completedRepoitories.Clear();
}
AddRepositoriesToCollection(completedRepoitories, _searchBarText);
completedRepoitories.Clear();
}

//Add Any Remaining Repositories to VisibleRepositoryList
AddRepositoriesToCollection(completedRepoitories, _searchBarText);
}

//Add Any Remaining Repositories to VisibleRepositoryList
AddRepositoriesToCollection(completedRepoitories, _searchBarText);
}
catch (ApiException e) when (e.StatusCode is HttpStatusCode.Unauthorized)
{
Expand Down Expand Up @@ -189,7 +195,8 @@ void AddRepositoriesToCollection(IEnumerable<Repository> repositories, string se

UpdateVisibleRepositoryList(searchBarText, _sortingService.CurrentOption, _sortingService.IsReversed);

static IEnumerable<Repository> RemoveForksAndDuplicates(in IEnumerable<Repository> repositoriesList) => repositoriesList.Where(x => !x.IsFork).GroupBy(x => x.Name).Select(x => x.First());
static IEnumerable<Repository> RemoveForksAndDuplicates(in IEnumerable<Repository> repositoriesList) =>
repositoriesList.Where(x => !x.IsFork).OrderByDescending(x => x.TotalViews).GroupBy(x => x.Name).Select(x => x.FirstOrDefault(x => x.DailyViewsList.Any()) ?? x.First());
}

void UpdateVisibleRepositoryList(in string searchBarText, in SortingOption sortingOption, in bool isReversed)
Expand Down
38 changes: 33 additions & 5 deletions GitTrends/Views/Repository/RepositoryDataTemplateSelector.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using FFImageLoading.Svg.Forms;
using GitTrends.Shared;
Expand Down Expand Up @@ -81,20 +83,46 @@ enum Column { Avatar, AvatarPadding, Emoji1, Statistic1, Emoji2, Statistic2, Emo
{
new AvatarImage().Row(Row.TopPadding).Column(Column.Avatar).RowSpan(6)
.Bind(Image.SourceProperty, nameof(Repository.OwnerAvatarUrl)),

new RepositoryNameLabel(repository.Name).Row(Row.Title).Column(Column.Emoji1).ColumnSpan(9),

new RepositoryDescriptionLabel(repository.Description).Row(Row.Description).Column(Column.Emoji1).ColumnSpan(9),

new SmallNavyBlueSVGImage(shouldShowStarsForksIssues ? "star.svg" : "total_views.svg").Row(Row.Statistics).Column(Column.Emoji1),
new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.StarCount.ToString() : repository.TotalViews.ToString()).Row(Row.Statistics).Column(Column.Statistic1),

//Only display the value when the Repository Data finishes loading. This avoid showing '0' while the data is loading.
shouldDisplayValue(repository.DailyClonesList)
? new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.StarCount.ToString() : repository.TotalViews.ToString()).Row(Row.Statistics).Column(Column.Statistic1)
: new Label(),

new SmallNavyBlueSVGImage(shouldShowStarsForksIssues ? "repo_forked.svg" : "unique_views.svg").Row(Row.Statistics).Column(Column.Emoji2),
new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.ForkCount.ToString() : repository.TotalUniqueViews.ToString()).Row(Row.Statistics).Column(Column.Statistic2),

//Only display the value when the Repository Data finishes loading. This avoid showing '0' while the data is loading.
shouldDisplayValue(repository.DailyClonesList)
? new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.ForkCount.ToString() : repository.TotalUniqueViews.ToString()).Row(Row.Statistics).Column(Column.Statistic2)
: new Label(),

new SmallNavyBlueSVGImage(shouldShowStarsForksIssues ? "issue_opened.svg" : "total_clones.svg").Row(Row.Statistics).Column(Column.Emoji3),
new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.IssuesCount.ToString() : repository.TotalClones.ToString()).Row(Row.Statistics).Column(Column.Statistic3),

//Only display the value when the Repository Data finishes loading. This avoid showing '0' while the data is loading.
shouldDisplayValue(repository.DailyClonesList)
? new DarkBlueLabel(_smallFontSize - 1, shouldShowStarsForksIssues ? repository.IssuesCount.ToString() : repository.TotalClones.ToString()).Row(Row.Statistics).Column(Column.Statistic3)
: new Label(),

//Column.Emoji4 & Column.Statistic4 are not needed for StarsForksIssues
shouldShowStarsForksIssues ? new SvgCachedImage() : new SmallNavyBlueSVGImage("unique_clones.svg").Row(Row.Statistics).Column(Column.Emoji4),
shouldShowStarsForksIssues ? new Label() : new DarkBlueLabel(_smallFontSize - 1, repository.TotalUniqueClones.ToString()).Row(Row.Statistics).Column(Column.Statistic4)
!shouldShowStarsForksIssues
? new SmallNavyBlueSVGImage("unique_clones.svg").Row(Row.Statistics).Column(Column.Emoji4)
: new SvgCachedImage(),

//Column.Emoji4 & Column.Statistic4 are not needed for StarsForksIssues
//Only display the value when the Repository Data finishes loading. This avoid showing '0' while the data is loading.
!shouldShowStarsForksIssues && shouldDisplayValue(repository.DailyClonesList)
? new DarkBlueLabel(_smallFontSize - 1, repository.TotalUniqueClones.ToString()).Row(Row.Statistics).Column(Column.Statistic4)
: new Label()
}
};

static bool shouldDisplayValue<T>(IList<T> list) where T : BaseDailyModel => list.Any();
}

class AvatarImage : CircleImage
Expand Down

0 comments on commit b2f16d5

Please sign in to comment.