Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
mvvm start
Browse files Browse the repository at this point in the history
  • Loading branch information
PureWeen committed Jun 15, 2019
1 parent ab11060 commit 1edd6c6
Show file tree
Hide file tree
Showing 11 changed files with 989 additions and 389 deletions.
44 changes: 44 additions & 0 deletions Xamarin.Forms.Core.UnitTests/ShellNavigationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Core.UnitTests
{
[TestFixture]
public class ShellNavigationTests : ShellTestBase
{
[Test]
public async Task NavigationWithQueryStringWhenPageMatchesBindingContext()
{
var shell = new Shell();

var one = new ShellItem { Route = "one" };
var two = new ShellItem { Route = "two" };

var tabone = MakeSimpleShellSection("tabone", "content");
var tabfour = MakeSimpleShellSection("tabfour", "content", null);

one.Items.Add(tabone);
two.Items.Add(tabfour);

shell.Items.Add(one);
shell.Items.Add(two);

ShellTestPage pagetoTest = new ShellTestPage();
await shell.GoToAsync(new ShellNavigationState($"//two/tabfour/content?{nameof(ShellTestPage.SomeQueryParameter)}=1234&two.rabbit=monkey"));
two.CurrentItem.CurrentItem.ContentTemplate = new DataTemplate(() =>
{
pagetoTest = new ShellTestPage();
pagetoTest.BindingContext = pagetoTest;
return pagetoTest;
});


var page = (two.CurrentItem.CurrentItem as IShellContentController).GetOrCreateContent();
Assert.AreEqual("1234", (page as ShellTestPage).SomeQueryParameter);

}
}
}
46 changes: 33 additions & 13 deletions Xamarin.Forms.Core.UnitTests/ShellUriHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public async Task GlobalRegisterAbsoluteMatching()
Routing.RegisterRoute("/seg1/seg2/seg3", typeof(object));
var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("/seg1/seg2/seg3"));

Assert.AreEqual("app://shell/IMPL_shell/seg1/seg2/seg3", request.Request.FullUri.ToString());
Assert.AreEqual("app://shell/IMPL_shell/seg1/seg2/seg3", request.CurrentRoute.FullUriWithImplicit.ToString());
}

[Test]
Expand Down Expand Up @@ -120,8 +120,8 @@ public async Task ShellRelativeGlobalRegistration()
await shell.GoToAsync("//item1/section1/rootlevelcontent1");
var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("section1/edit"), true);

Assert.AreEqual(1, request.Request.GlobalRoutes.Count);
Assert.AreEqual("item1/section1/edit", request.Request.GlobalRoutes.First());
Assert.AreEqual(4, request.CurrentRoute.PathParts.Count);
Assert.AreEqual("item1/section1/edit", request.CurrentRoute.PathParts[3].Path);
}

[Test]
Expand All @@ -137,9 +137,9 @@ public async Task ShellSectionWithRelativeEditUpOneLevelMultiple()

var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("//rootlevelcontent1/add/edit"));

Assert.AreEqual(2, request.Request.GlobalRoutes.Count);
Assert.AreEqual("section1/add", request.Request.GlobalRoutes.First());
Assert.AreEqual("section1/edit", request.Request.GlobalRoutes.Skip(1).First());
Assert.AreEqual(5, request.CurrentRoute.PathParts.Count);
Assert.AreEqual("section1/add", request.CurrentRoute.PathParts[3].Path);
Assert.AreEqual("section1/edit", request.CurrentRoute.PathParts[4].Path);
}

[Test]
Expand All @@ -154,8 +154,8 @@ public async Task ShellSectionWithGlobalRouteAbsolute()

var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("//rootlevelcontent1/edit"));

Assert.AreEqual(1, request.Request.GlobalRoutes.Count);
Assert.AreEqual("edit", request.Request.GlobalRoutes.First());
Assert.AreEqual(4, request.CurrentRoute.PathParts.Count);
Assert.AreEqual("edit", request.CurrentRoute.PathParts[3].Path);
}

[Test]
Expand All @@ -171,8 +171,8 @@ public async Task ShellSectionWithGlobalRouteRelative()
await shell.GoToAsync("//rootlevelcontent1");
var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("edit"));

Assert.AreEqual(1, request.Request.GlobalRoutes.Count);
Assert.AreEqual("edit", request.Request.GlobalRoutes.First());
Assert.AreEqual(4, request.CurrentRoute.PathParts.Count);
Assert.AreEqual("edit", request.CurrentRoute.PathParts[3].Path);
}


Expand All @@ -189,7 +189,7 @@ public async Task ShellSectionWithRelativeEditUpOneLevel()
await shell.GoToAsync("//rootlevelcontent1");
var request = ShellUriHandler.GetNavigationRequest(shell, CreateUri("edit"), true);

Assert.AreEqual("section1/edit", request.Request.GlobalRoutes.First());
Assert.AreEqual("section1/edit", request.CurrentRoute.PathParts[3].Path);
}

[Test]
Expand All @@ -205,6 +205,7 @@ public async Task ShellSectionWithRelativeEdit()

await shell.GoToAsync("//rootlevelcontent1");
var location = shell.CurrentState.FullLocation;

await shell.GoToAsync("edit", false, true);

Assert.AreEqual(editShellContent, shell.CurrentItem.CurrentItem.CurrentItem);
Expand Down Expand Up @@ -275,6 +276,25 @@ public async Task ShellItemAndContentOnly()
Assert.IsTrue(builders.Contains("//item2/rootlevelcontent"));
}

[Test]
public async Task PoppingRemovesRouteFromStack()
{
var shell = new Shell();
var item1 = CreateShellItem(asImplicit: true, shellSectionRoute: "domestic", shellContentRoute: "cats", shellItemRoute: "animals");

shell.Items.Add(item1);

Routing.RegisterRoute("catdetails", typeof(ContentPage));
await shell.GoToAsync($"catdetails");
await shell.Navigation.PopAsync();
await shell.GoToAsync($"catdetails");

Assert.AreEqual(
"//animals/domestic/cats/catdetails",
shell.CurrentState.FullLocation.ToString()
);
}


[Test]
public async Task AbsoluteNavigationToRelativeWithGlobal()
Expand Down Expand Up @@ -350,12 +370,12 @@ public async Task ConvertToStandardFormat()

foreach(var uri in TestUris)
{
Assert.AreEqual(new Uri("app://shell/IMPL_shell/path"), ShellUriHandler.ConvertToStandardFormat(shell, uri), $"{uri}");
Assert.AreEqual(new Uri("app://shell/IMPL_shell/path"), ShellUriHandler.ConvertToStandardFormat(uri), $"{uri}");

if(!uri.IsAbsoluteUri)
{
var reverse = new Uri(uri.OriginalString.Replace("/", "\\"), UriKind.Relative);
Assert.AreEqual(new Uri("app://shell/IMPL_shell/path"), ShellUriHandler.ConvertToStandardFormat(shell, reverse));
Assert.AreEqual(new Uri("app://shell/IMPL_shell/path"), ShellUriHandler.ConvertToStandardFormat(reverse));
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="CommandTests.cs" />
<Compile Include="DependencyResolutionTests.cs" />
<Compile Include="EffectiveFlowDirectionExtensions.cs" />
<Compile Include="ShellNavigationTests.cs" />
<Compile Include="ShellTestBase.cs" />
<Compile Include="ShellUriHandlerTests.cs" />
<Compile Include="CheckBoxUnitTests.cs" />
Expand Down
157 changes: 157 additions & 0 deletions Xamarin.Forms.Core/Shell/RouteRequestBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Xamarin.Forms
{
/// <summary>
/// This attempts to locate the intended route trying to be navigated to
/// </summary>
internal class RouteRequestBuilder
{
readonly List<string> _globalRouteMatches = new List<string>();
readonly List<string> _matchedSegments = new List<string>();
readonly List<string> _fullSegments = new List<string>();
readonly string[] _allSegments = null;
readonly static string _uriSeparator = "/";
public Shell Shell { get; private set; }
public ShellItem Item { get; private set; }
public ShellSection Section { get; private set; }
public ShellContent Content { get; private set; }
public object LowestChild =>
(object)Content ?? (object)Section ?? (object)Item ?? (object)Shell;

public RouteRequestBuilder(string shellSegment, string userSegment, object node, string[] allSegments)
{
_allSegments = allSegments;
if (node != null)
AddMatch(shellSegment, userSegment, node);
else
AddGlobalRoute(userSegment, shellSegment);
}

public RouteRequestBuilder(RouteRequestBuilder builder)
{
_allSegments = builder._allSegments;
_matchedSegments.AddRange(builder._matchedSegments);
_fullSegments.AddRange(builder._fullSegments);
_globalRouteMatches.AddRange(builder._globalRouteMatches);
Shell = builder.Shell;
Item = builder.Item;
Section = builder.Section;
Content = builder.Content;
}

public void AddGlobalRoute(string routeName, string segment)
{
_globalRouteMatches.Add(routeName);
_fullSegments.Add(segment);
_matchedSegments.Add(segment);
}


public void AddMatch(string shellSegment, string userSegment, object node)
{
if (node == null)
throw new ArgumentNullException(nameof(node));

switch (node)
{
case ShellUriHandler.GlobalRouteItem globalRoute:
if (globalRoute.IsFinished)
{
_globalRouteMatches.Add(globalRoute.SourceRoute);
}
break;
case Shell shell:
Shell = shell;
break;
case ShellItem item:
Item = item;
break;
case ShellSection section:
Section = section;

if (Item == null)
{
Item = Section.Parent as ShellItem;
_fullSegments.Add(Item.Route);
}

break;
case ShellContent content:
Content = content;
if (Section == null)
{
Section = Content.Parent as ShellSection;
_fullSegments.Add(Section.Route);
}

if (Item == null)
{
Item = Section.Parent as ShellItem;
_fullSegments.Insert(0, Item.Route);
}

break;

}

// if shellSegment == userSegment it means the implicit route is part of the request
if (!Routing.IsImplicit(shellSegment) || shellSegment == userSegment)
_matchedSegments.Add(shellSegment);

_fullSegments.Add(shellSegment);
}

public string NextSegment
{
get
{
var nextMatch = _matchedSegments.Count;
if (nextMatch >= _allSegments.Length)
return null;

return _allSegments[nextMatch];
}
}

public string RemainingPath
{
get
{
var nextMatch = _matchedSegments.Count;
if (nextMatch >= _allSegments.Length)
return null;

return Routing.FormatRoute(String.Join(_uriSeparator, _allSegments.Skip(nextMatch)));
}
}
public string[] RemainingSegments
{
get
{
var nextMatch = _matchedSegments.Count;
if (nextMatch >= _allSegments.Length)
return null;

return _allSegments.Skip(nextMatch).ToArray();
}
}

string MakeUriString(List<string> segments)
{
if (segments[0].StartsWith(_uriSeparator, StringComparison.Ordinal) || segments[0].StartsWith("\\", StringComparison.Ordinal))
return String.Join(_uriSeparator, segments);

return $"//{String.Join(_uriSeparator, segments)}";
}

public string PathNoImplicit => MakeUriString(_matchedSegments);
public string PathFull => MakeUriString(_fullSegments);

public bool IsFullMatch => _matchedSegments.Count == _allSegments.Length;
public List<string> GlobalRouteMatches => _globalRouteMatches;
public List<string> SegmentsMatched => _matchedSegments;
}
}
Loading

0 comments on commit 1edd6c6

Please sign in to comment.