mirror of
https://github.com/osukey/osukey.git
synced 2025-08-03 22:56:36 +09:00
Merge branch 'master' into remove-comments-page
This commit is contained in:
@ -1,11 +1,16 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.AccountCreation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
@ -13,13 +18,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public class TestSceneAccountCreationOverlay : OsuTestScene
|
||||
{
|
||||
private readonly Container userPanelArea;
|
||||
private readonly AccountCreationOverlay accountCreation;
|
||||
|
||||
private Bindable<User> localUser;
|
||||
private IBindable<User> localUser;
|
||||
|
||||
public TestSceneAccountCreationOverlay()
|
||||
{
|
||||
AccountCreationOverlay accountCreation;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
accountCreation = new AccountCreationOverlay(),
|
||||
@ -31,19 +35,29 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
};
|
||||
|
||||
AddStep("show", () => accountCreation.Show());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
API.Logout();
|
||||
|
||||
localUser = API.LocalUser.GetBoundCopy();
|
||||
localUser.BindValueChanged(user => { userPanelArea.Child = new UserGridPanel(user.NewValue) { Width = 200 }; }, true);
|
||||
}
|
||||
|
||||
AddStep("logout", API.Logout);
|
||||
[Test]
|
||||
public void TestOverlayVisibility()
|
||||
{
|
||||
AddStep("start hidden", () => accountCreation.Hide());
|
||||
AddStep("log out", () => API.Logout());
|
||||
|
||||
AddStep("show manually", () => accountCreation.Show());
|
||||
AddUntilStep("overlay is visible", () => accountCreation.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("click button", () => accountCreation.ChildrenOfType<SettingsButton>().Single().TriggerClick());
|
||||
AddUntilStep("warning screen is present", () => accountCreation.ChildrenOfType<ScreenWarning>().SingleOrDefault()?.IsPresent == true);
|
||||
|
||||
AddStep("log back in", () => API.Login("dummy", "password"));
|
||||
AddUntilStep("overlay is hidden", () => accountCreation.State.Value == Visibility.Hidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,248 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Overlays;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapListing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneBeatmapListingOverlay : OsuTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
private readonly List<APIBeatmapSet> setsForResponse = new List<APIBeatmapSet>();
|
||||
|
||||
private readonly BeatmapListingOverlay overlay;
|
||||
private BeatmapListingOverlay overlay;
|
||||
|
||||
public TestSceneBeatmapListingOverlay()
|
||||
private BeatmapListingSearchControl searchControl => overlay.ChildrenOfType<BeatmapListingSearchControl>().Single();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(overlay = new BeatmapListingOverlay());
|
||||
Child = overlay = new BeatmapListingOverlay { State = { Value = Visibility.Visible } };
|
||||
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
if (!(req is SearchBeatmapSetsRequest searchBeatmapSetsRequest)) return false;
|
||||
|
||||
searchBeatmapSetsRequest.TriggerSuccess(new SearchBeatmapSetsResponse
|
||||
{
|
||||
BeatmapSets = setsForResponse,
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
AddStep("initialize dummy", () =>
|
||||
{
|
||||
// non-supporter user
|
||||
((DummyAPIAccess)API).LocalUser.Value = new User
|
||||
{
|
||||
Username = "TestBot",
|
||||
Id = API.LocalUser.Value.Id + 1,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestShow()
|
||||
public void TestNoBeatmapsPlaceholder()
|
||||
{
|
||||
AddStep("Show", overlay.Show);
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
|
||||
AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet));
|
||||
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any());
|
||||
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
|
||||
// fetch once more to ensure nothing happens in displaying placeholder again when it already is present.
|
||||
AddStep("fetch for 0 beatmaps again", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHide()
|
||||
public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithoutResults()
|
||||
{
|
||||
AddStep("Hide", overlay.Hide);
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddStep("set dummy as non-supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = false);
|
||||
|
||||
// only Rank Achieved filter
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
// only Played filter
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
// both RankAchieved and Played filters
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
notFoundPlaceholderShown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithSupporterUsesSupporterOnlyFiltersWithoutResults()
|
||||
{
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddStep("set dummy as supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = true);
|
||||
|
||||
// only Rank Achieved filter
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
// only Played filter
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
// both Rank Achieved and Played filters
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
notFoundPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
notFoundPlaceholderShown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithResults()
|
||||
{
|
||||
AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet));
|
||||
AddStep("set dummy as non-supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = false);
|
||||
|
||||
// only Rank Achieved filter
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
noPlaceholderShown();
|
||||
|
||||
// only Played filter
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
noPlaceholderShown();
|
||||
|
||||
// both Rank Achieved and Played filters
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
supporterRequiredPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
noPlaceholderShown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithSupporterUsesSupporterOnlyFiltersWithResults()
|
||||
{
|
||||
AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet));
|
||||
AddStep("set dummy as supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = true);
|
||||
|
||||
// only Rank Achieved filter
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
noPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
noPlaceholderShown();
|
||||
|
||||
// only Played filter
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
noPlaceholderShown();
|
||||
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
noPlaceholderShown();
|
||||
|
||||
// both Rank Achieved and Played filters
|
||||
setRankAchievedFilter(new[] { ScoreRank.XH });
|
||||
setPlayedFilter(SearchPlayed.Played);
|
||||
noPlaceholderShown();
|
||||
|
||||
setRankAchievedFilter(Array.Empty<ScoreRank>());
|
||||
setPlayedFilter(SearchPlayed.Any);
|
||||
noPlaceholderShown();
|
||||
}
|
||||
|
||||
private void fetchFor(params BeatmapSetInfo[] beatmaps)
|
||||
{
|
||||
setsForResponse.Clear();
|
||||
setsForResponse.AddRange(beatmaps.Select(b => new TestAPIBeatmapSet(b)));
|
||||
|
||||
// trigger arbitrary change for fetching.
|
||||
searchControl.Query.TriggerChange();
|
||||
}
|
||||
|
||||
private void setRankAchievedFilter(ScoreRank[] ranks)
|
||||
{
|
||||
AddStep($"set Rank Achieved filter to [{string.Join(',', ranks)}]", () =>
|
||||
{
|
||||
searchControl.Ranks.Clear();
|
||||
searchControl.Ranks.AddRange(ranks);
|
||||
});
|
||||
}
|
||||
|
||||
private void setPlayedFilter(SearchPlayed played)
|
||||
{
|
||||
AddStep($"set Played filter to {played}", () => searchControl.Played.Value = played);
|
||||
}
|
||||
|
||||
private void supporterRequiredPlaceholderShown()
|
||||
{
|
||||
AddUntilStep("\"supporter required\" placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.SupporterRequiredDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
}
|
||||
|
||||
private void notFoundPlaceholderShown()
|
||||
{
|
||||
AddUntilStep("\"no maps found\" placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
}
|
||||
|
||||
private void noPlaceholderShown()
|
||||
{
|
||||
AddUntilStep("no placeholder shown", () =>
|
||||
!overlay.ChildrenOfType<BeatmapListingOverlay.SupporterRequiredDrawable>().Any()
|
||||
&& !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any());
|
||||
}
|
||||
|
||||
private class TestAPIBeatmapSet : APIBeatmapSet
|
||||
{
|
||||
private readonly BeatmapSetInfo beatmapSet;
|
||||
|
||||
public TestAPIBeatmapSet(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
this.beatmapSet = beatmapSet;
|
||||
}
|
||||
|
||||
public override BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) => beatmapSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,8 +231,19 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
});
|
||||
|
||||
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
||||
AddAssert("left-most beatmap selected", () => overlay.Header.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
||||
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.HeaderContent.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
||||
AddAssert("left-most beatmap selected", () => overlay.Header.HeaderContent.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExplicitBeatmap()
|
||||
{
|
||||
AddStep("show explicit map", () =>
|
||||
{
|
||||
var beatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||
beatmapSet.OnlineInfo.HasExplicitContent = true;
|
||||
overlay.ShowBeatmapSet(beatmapSet);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -299,12 +310,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private void downloadAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.DownloadButtonsVisible == shown);
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.HeaderContent.DownloadButtonsVisible == shown);
|
||||
}
|
||||
|
||||
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
||||
{
|
||||
public new Header Header => base.Header;
|
||||
public new BeatmapSetHeader Header => base.Header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
@ -72,6 +74,32 @@ namespace osu.Game.Tests.Visual.Online
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOnlyFailMetrics()
|
||||
{
|
||||
AddStep("set beatmap", () => successRate.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).ToArray(),
|
||||
}
|
||||
});
|
||||
AddAssert("graph max values correct",
|
||||
() => successRate.ChildrenOfType<BarGraph>().All(graph => graph.MaxValue == 100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyMetrics()
|
||||
{
|
||||
AddStep("set beatmap", () => successRate.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Metrics = new BeatmapMetrics()
|
||||
});
|
||||
|
||||
AddAssert("graph max values correct",
|
||||
() => successRate.ChildrenOfType<BarGraph>().All(graph => graph.MaxValue == 0));
|
||||
}
|
||||
|
||||
private class GraphExposingSuccessRate : SuccessRate
|
||||
{
|
||||
public new FailRetryGraph Graph => base.Graph;
|
||||
|
@ -1,8 +1,14 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Humanizer;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Changelog;
|
||||
@ -12,13 +18,63 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestFixture]
|
||||
public class TestSceneChangelogOverlay : OsuTestScene
|
||||
{
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
private readonly Dictionary<string, APIUpdateStream> streams;
|
||||
private readonly Dictionary<string, APIChangelogBuild> builds;
|
||||
|
||||
private APIChangelogBuild requestedBuild;
|
||||
private TestChangelogOverlay changelog;
|
||||
|
||||
protected override bool UseOnlineAPI => true;
|
||||
public TestSceneChangelogOverlay()
|
||||
{
|
||||
streams = APIUpdateStream.KNOWN_STREAMS.Keys.Select((stream, id) => new APIUpdateStream
|
||||
{
|
||||
Id = id + 1,
|
||||
Name = stream,
|
||||
DisplayName = stream.Humanize(), // not quite there, but good enough.
|
||||
}).ToDictionary(stream => stream.Name);
|
||||
|
||||
string version = DateTimeOffset.Now.ToString("yyyy.Mdd.0");
|
||||
builds = APIUpdateStream.KNOWN_STREAMS.Keys.Select(stream => new APIChangelogBuild
|
||||
{
|
||||
Version = version,
|
||||
DisplayVersion = version,
|
||||
UpdateStream = streams[stream],
|
||||
ChangelogEntries = new List<APIChangelogEntry>()
|
||||
}).ToDictionary(build => build.UpdateStream.Name);
|
||||
|
||||
foreach (var stream in streams.Values)
|
||||
stream.LatestBuild = builds[stream.Name];
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
requestedBuild = null;
|
||||
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case GetChangelogRequest changelogRequest:
|
||||
var changelogResponse = new APIChangelogIndex
|
||||
{
|
||||
Streams = streams.Values.ToList(),
|
||||
Builds = builds.Values.ToList()
|
||||
};
|
||||
changelogRequest.TriggerSuccess(changelogResponse);
|
||||
return true;
|
||||
|
||||
case GetChangelogBuildRequest buildRequest:
|
||||
if (requestedBuild != null)
|
||||
buildRequest.TriggerSuccess(requestedBuild);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Child = changelog = new TestChangelogOverlay();
|
||||
});
|
||||
|
||||
@ -40,65 +96,107 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert(@"no stream selected", () => changelog.Header.Streams.Current.Value == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShowWithBuild()
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void ShowWithBuild(bool isSupporter)
|
||||
{
|
||||
AddStep(@"Show with Lazer 2018.712.0", () =>
|
||||
AddStep(@"set supporter", () => dummyAPI.LocalUser.Value.IsSupporter = isSupporter);
|
||||
showBuild(() => new APIChangelogBuild
|
||||
{
|
||||
changelog.ShowBuild(new APIChangelogBuild
|
||||
Version = "2018.712.0",
|
||||
DisplayVersion = "2018.712.0",
|
||||
UpdateStream = streams[OsuGameBase.CLIENT_STREAM_NAME],
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
{
|
||||
Version = "2018.712.0",
|
||||
DisplayVersion = "2018.712.0",
|
||||
UpdateStream = new APIUpdateStream { Id = 7, Name = OsuGameBase.CLIENT_STREAM_NAME },
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
new APIChangelogEntry
|
||||
{
|
||||
new APIChangelogEntry
|
||||
Type = ChangelogEntryType.Fix,
|
||||
Category = "osu!",
|
||||
Title = "Fix thing",
|
||||
MessageHtml = "Additional info goes here.",
|
||||
Repository = "osu",
|
||||
GithubPullRequestId = 11100,
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
Category = "Test",
|
||||
Title = "Title",
|
||||
MessageHtml = "Message",
|
||||
OsuUsername = "smoogipoo",
|
||||
UserId = 1040328
|
||||
}
|
||||
},
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Type = ChangelogEntryType.Add,
|
||||
Category = "osu!",
|
||||
Title = "Add thing",
|
||||
Major = true,
|
||||
Repository = "ppy/osu-framework",
|
||||
GithubPullRequestId = 4444,
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
DisplayName = "frenzibyte",
|
||||
GithubUrl = "https://github.com/frenzibyte"
|
||||
}
|
||||
},
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Type = ChangelogEntryType.Misc,
|
||||
Category = "Code quality",
|
||||
Title = "Clean up thing",
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
DisplayName = "some dude"
|
||||
}
|
||||
},
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Type = ChangelogEntryType.Misc,
|
||||
Category = "Code quality",
|
||||
Title = "Clean up another thing"
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
AddUntilStep(@"wait for streams", () => changelog.Streams?.Count > 0);
|
||||
AddAssert(@"correct build displayed", () => changelog.Current.Value.Version == "2018.712.0");
|
||||
AddAssert(@"correct stream selected", () => changelog.Header.Streams.Current.Value.Id == 7);
|
||||
AddAssert(@"correct stream selected", () => changelog.Header.Streams.Current.Value.Id == 5);
|
||||
AddUntilStep(@"wait for content load", () => changelog.ChildrenOfType<ChangelogSupporterPromo>().Any());
|
||||
AddAssert(@"supporter promo showed", () => changelog.ChildrenOfType<ChangelogSupporterPromo>().First().Alpha == (isSupporter ? 0 : 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHTMLUnescaping()
|
||||
{
|
||||
AddStep(@"Ensure HTML string unescaping", () =>
|
||||
showBuild(() => new APIChangelogBuild
|
||||
{
|
||||
changelog.ShowBuild(new APIChangelogBuild
|
||||
Version = "2019.920.0",
|
||||
DisplayVersion = "2019.920.0",
|
||||
UpdateStream = new APIUpdateStream
|
||||
{
|
||||
Version = "2019.920.0",
|
||||
DisplayVersion = "2019.920.0",
|
||||
UpdateStream = new APIUpdateStream
|
||||
Name = "Test",
|
||||
DisplayName = "Test"
|
||||
},
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
{
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Name = "Test",
|
||||
DisplayName = "Test"
|
||||
},
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
{
|
||||
new APIChangelogEntry
|
||||
Category = "Testing HTML strings unescaping",
|
||||
Title = "Ensuring HTML strings are being unescaped",
|
||||
MessageHtml = """"This text should appear triple-quoted""" >_<",
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
Category = "Testing HTML strings unescaping",
|
||||
Title = "Ensuring HTML strings are being unescaped",
|
||||
MessageHtml = """"This text should appear triple-quoted""" >_<",
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
DisplayName = "Dummy",
|
||||
OsuUsername = "Dummy",
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
DisplayName = "Dummy",
|
||||
OsuUsername = "Dummy",
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showBuild(Func<APIChangelogBuild> build)
|
||||
{
|
||||
AddStep("set up build", () => requestedBuild = build.Invoke());
|
||||
AddStep("show build", () => changelog.ShowBuild(requestedBuild));
|
||||
}
|
||||
|
||||
private class TestChangelogOverlay : ChangelogOverlay
|
||||
{
|
||||
public new List<APIUpdateStream> Streams => base.Streams;
|
||||
|
@ -0,0 +1,35 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Changelog;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneChangelogSupporterPromo : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
public TestSceneChangelogSupporterPromo()
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background4,
|
||||
},
|
||||
new ChangelogSupporterPromo(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -103,26 +103,26 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private void testLinksGeneral()
|
||||
{
|
||||
addMessageWithChecks("test!");
|
||||
addMessageWithChecks("osu.ppy.sh!");
|
||||
addMessageWithChecks("https://osu.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("dev.ppy.sh!");
|
||||
addMessageWithChecks("https://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("00:12:345 (1,2) - Test?", 1, expectedActions: LinkAction.OpenEditorTimestamp);
|
||||
addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(osu forums)[https://osu.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://osu.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("is now listening to [https://osu.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmapSet);
|
||||
addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3,
|
||||
addMessageWithChecks("(osu forums)[https://dev.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmapSet);
|
||||
addMessageWithChecks("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", 3,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External });
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://osu.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
// note that there's 0 links here (they get removed if a channel is not found)
|
||||
addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).");
|
||||
addMessageWithChecks("I am important!", 0, false, true);
|
||||
addMessageWithChecks("feels important", 0, true, true);
|
||||
addMessageWithChecks("likes to post this [https://osu.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("likes to post this [https://dev.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("Join my multiplayer game osump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my [multiplayer game](osump://12346).", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my [#english](osu://chan/#english).", 1, expectedActions: LinkAction.OpenChannel);
|
||||
@ -136,9 +136,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
int echoCounter = 0;
|
||||
|
||||
addEchoWithWait("sent!", "received!");
|
||||
addEchoWithWait("https://osu.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://osu.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://osu.ppy.sh/home]", null, 5000);
|
||||
addEchoWithWait("https://dev.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://dev.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://dev.ppy.sh/home]", null, 5000);
|
||||
|
||||
void addEchoWithWait(string text, string completeText = null, double delay = 250)
|
||||
{
|
||||
|
@ -9,8 +9,12 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Chat.Selection;
|
||||
@ -34,6 +38,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private Channel previousChannel => joinedChannels.ElementAt(joinedChannels.ToList().IndexOf(currentChannel) - 1);
|
||||
private Channel channel1 => channels[0];
|
||||
private Channel channel2 => channels[1];
|
||||
private Channel channel3 => channels[2];
|
||||
|
||||
[Resolved]
|
||||
private GameHost host { get; set; }
|
||||
|
||||
public TestSceneChatOverlay()
|
||||
{
|
||||
@ -42,7 +50,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
Name = $"Channel no. {index}",
|
||||
Topic = index == 3 ? null : $"We talk about the number {index} here",
|
||||
Type = index % 2 == 0 ? ChannelType.PM : ChannelType.Temporary
|
||||
Type = index % 2 == 0 ? ChannelType.PM : ChannelType.Temporary,
|
||||
Id = index
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
@ -64,6 +73,25 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("register request handling", () =>
|
||||
{
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case JoinChannelRequest joinChannel:
|
||||
joinChannel.TriggerSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHideOverlay()
|
||||
{
|
||||
@ -103,11 +131,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestChannelShortcutKeys()
|
||||
{
|
||||
AddStep("Join channels", () => channels.ForEach(channel => channelManager.JoinChannel(channel)));
|
||||
AddStep("Close channel selector", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.Escape);
|
||||
InputManager.ReleaseKey(Key.Escape);
|
||||
});
|
||||
AddStep("Close channel selector", () => InputManager.Key(Key.Escape));
|
||||
AddUntilStep("Wait for close", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
|
||||
for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex)
|
||||
@ -212,15 +236,106 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("All channels closed", () => !channelManager.JoinedChannels.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCloseTabShortcut()
|
||||
{
|
||||
AddStep("Join 2 channels", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel1);
|
||||
channelManager.JoinChannel(channel2);
|
||||
});
|
||||
|
||||
// Want to close channel 2
|
||||
AddStep("Select channel 2", () => clickDrawable(chatOverlay.TabMap[channel2]));
|
||||
AddStep("Close tab via shortcut", pressCloseDocumentKeys);
|
||||
|
||||
// Channel 2 should be closed
|
||||
AddAssert("Channel 1 open", () => channelManager.JoinedChannels.Contains(channel1));
|
||||
AddAssert("Channel 2 closed", () => !channelManager.JoinedChannels.Contains(channel2));
|
||||
|
||||
// Want to close channel 1
|
||||
AddStep("Select channel 1", () => clickDrawable(chatOverlay.TabMap[channel1]));
|
||||
|
||||
AddStep("Close tab via shortcut", pressCloseDocumentKeys);
|
||||
// Channel 1 and channel 2 should be closed
|
||||
AddAssert("All channels closed", () => !channelManager.JoinedChannels.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewTabShortcut()
|
||||
{
|
||||
AddStep("Join 2 channels", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel1);
|
||||
channelManager.JoinChannel(channel2);
|
||||
});
|
||||
|
||||
// Want to join another channel
|
||||
AddStep("Press new tab shortcut", pressNewTabKeys);
|
||||
|
||||
// Selector should be visible
|
||||
AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRestoreTabShortcut()
|
||||
{
|
||||
AddStep("Join 3 channels", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel1);
|
||||
channelManager.JoinChannel(channel2);
|
||||
channelManager.JoinChannel(channel3);
|
||||
});
|
||||
|
||||
// Should do nothing
|
||||
AddStep("Restore tab via shortcut", pressRestoreTabKeys);
|
||||
AddAssert("All channels still open", () => channelManager.JoinedChannels.Count == 3);
|
||||
|
||||
// Close channel 1
|
||||
AddStep("Select channel 1", () => clickDrawable(chatOverlay.TabMap[channel1]));
|
||||
AddStep("Click normal close button", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel1]).CloseButton.Child));
|
||||
AddAssert("Channel 1 closed", () => !channelManager.JoinedChannels.Contains(channel1));
|
||||
AddAssert("Other channels still open", () => channelManager.JoinedChannels.Count == 2);
|
||||
|
||||
// Reopen channel 1
|
||||
AddStep("Restore tab via shortcut", pressRestoreTabKeys);
|
||||
AddAssert("All channels now open", () => channelManager.JoinedChannels.Count == 3);
|
||||
AddAssert("Current channel is channel 1", () => currentChannel == channel1);
|
||||
|
||||
// Close two channels
|
||||
AddStep("Select channel 1", () => clickDrawable(chatOverlay.TabMap[channel1]));
|
||||
AddStep("Close channel 1", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel1]).CloseButton.Child));
|
||||
AddStep("Select channel 2", () => clickDrawable(chatOverlay.TabMap[channel2]));
|
||||
AddStep("Close channel 2", () => clickDrawable(((TestPrivateChannelTabItem)chatOverlay.TabMap[channel2]).CloseButton.Child));
|
||||
AddAssert("Only one channel open", () => channelManager.JoinedChannels.Count == 1);
|
||||
AddAssert("Current channel is channel 3", () => currentChannel == channel3);
|
||||
|
||||
// Should first re-open channel 2
|
||||
AddStep("Restore tab via shortcut", pressRestoreTabKeys);
|
||||
AddAssert("Channel 1 still closed", () => !channelManager.JoinedChannels.Contains(channel1));
|
||||
AddAssert("Channel 2 now open", () => channelManager.JoinedChannels.Contains(channel2));
|
||||
AddAssert("Current channel is channel 2", () => currentChannel == channel2);
|
||||
|
||||
// Should then re-open channel 1
|
||||
AddStep("Restore tab via shortcut", pressRestoreTabKeys);
|
||||
AddAssert("All channels now open", () => channelManager.JoinedChannels.Count == 3);
|
||||
AddAssert("Current channel is channel 1", () => currentChannel == channel1);
|
||||
}
|
||||
|
||||
private void pressChannelHotkey(int number)
|
||||
{
|
||||
var channelKey = Key.Number0 + number;
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.PressKey(channelKey);
|
||||
InputManager.Key(channelKey);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
InputManager.ReleaseKey(channelKey);
|
||||
}
|
||||
|
||||
private void pressCloseDocumentKeys() => InputManager.Keys(PlatformAction.DocumentClose);
|
||||
|
||||
private void pressNewTabKeys() => InputManager.Keys(PlatformAction.TabNew);
|
||||
|
||||
private void pressRestoreTabKeys() => InputManager.Keys(PlatformAction.TabRestore);
|
||||
|
||||
private void clickDrawable(Drawable d)
|
||||
{
|
||||
InputManager.MoveMouseTo(d);
|
||||
|
@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestMultipleLoads()
|
||||
{
|
||||
var comments = exampleComments;
|
||||
int topLevelCommentCount = exampleComments.Comments.Count(comment => comment.IsTopLevel);
|
||||
int topLevelCommentCount = exampleComments.Comments.Count;
|
||||
|
||||
AddStep("hide container", () => commentsContainer.Hide());
|
||||
setUpCommentsResponse(comments);
|
||||
@ -85,9 +85,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
if (!(request is GetCommentsRequest getCommentsRequest))
|
||||
return;
|
||||
return false;
|
||||
|
||||
getCommentsRequest.TriggerSuccess(commentBundle);
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
|
100
osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs
Normal file
100
osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Overlays.Dashboard;
|
||||
using osu.Game.Tests.Visual.Spectator;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneCurrentlyPlayingDisplay : OsuTestScene
|
||||
{
|
||||
private readonly User streamingUser = new User { Id = 2, Username = "Test user" };
|
||||
|
||||
private TestSpectatorClient spectatorClient;
|
||||
private CurrentlyPlayingDisplay currentlyPlaying;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("add streaming client", () =>
|
||||
{
|
||||
spectatorClient = new TestSpectatorClient();
|
||||
var lookupCache = new TestUserLookupCache();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
lookupCache,
|
||||
spectatorClient,
|
||||
new DependencyProvidingContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CachedDependencies = new (Type, object)[]
|
||||
{
|
||||
(typeof(SpectatorClient), spectatorClient),
|
||||
(typeof(UserLookupCache), lookupCache)
|
||||
},
|
||||
Child = currentlyPlaying = new CurrentlyPlayingDisplay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBasicDisplay()
|
||||
{
|
||||
AddStep("Add playing user", () => spectatorClient.StartPlay(streamingUser.Id, 0));
|
||||
AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType<UserGridPanel>()?.FirstOrDefault()?.User.Id == 2);
|
||||
AddStep("Remove playing user", () => spectatorClient.EndPlay(streamingUser.Id));
|
||||
AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType<UserGridPanel>().Any());
|
||||
}
|
||||
|
||||
internal class TestUserLookupCache : UserLookupCache
|
||||
{
|
||||
private static readonly string[] usernames =
|
||||
{
|
||||
"fieryrage",
|
||||
"Kerensa",
|
||||
"MillhioreF",
|
||||
"Player01",
|
||||
"smoogipoo",
|
||||
"Ephemeral",
|
||||
"BTMC",
|
||||
"Cilvery",
|
||||
"m980",
|
||||
"HappyStick",
|
||||
"LittleEndu",
|
||||
"frenzibyte",
|
||||
"Zallius",
|
||||
"BanchoBot",
|
||||
"rocketminer210",
|
||||
"pishifat"
|
||||
};
|
||||
|
||||
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default)
|
||||
{
|
||||
// tests against failed lookups
|
||||
if (lookup == 13)
|
||||
return Task.FromResult<User>(null);
|
||||
|
||||
return Task.FromResult(new User
|
||||
{
|
||||
Id = lookup,
|
||||
Username = usernames[lookup % usernames.Length],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -42,8 +42,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
ensureSoleilyRemoved();
|
||||
createButtonWithBeatmap(createSoleily());
|
||||
AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded);
|
||||
AddStep("import soleily", () => beatmaps.Import(new[] { TestResources.GetTestBeatmapForImport() }));
|
||||
AddStep("import soleily", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()));
|
||||
|
||||
AddUntilStep("wait for beatmap import", () => beatmaps.GetAllUsableBeatmapSets().Any(b => b.OnlineBeatmapSetID == 241526));
|
||||
AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable);
|
||||
|
||||
createButtonWithBeatmap(createSoleily());
|
||||
AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable);
|
||||
ensureSoleilyRemoved();
|
||||
|
@ -99,13 +99,16 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
var normal = CreateWorkingBeatmap(Ruleset.Value).BeatmapSetInfo;
|
||||
var normal = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||
normal.OnlineInfo.HasVideo = true;
|
||||
normal.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
var undownloadable = getUndownloadableBeatmapSet();
|
||||
var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets);
|
||||
|
||||
var explicitMap = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||
explicitMap.OnlineInfo.HasExplicitContent = true;
|
||||
|
||||
Child = new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -121,9 +124,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
new GridBeatmapPanel(normal),
|
||||
new GridBeatmapPanel(undownloadable),
|
||||
new GridBeatmapPanel(manyDifficulties),
|
||||
new GridBeatmapPanel(explicitMap),
|
||||
new ListBeatmapPanel(normal),
|
||||
new ListBeatmapPanel(undownloadable),
|
||||
new ListBeatmapPanel(manyDifficulties),
|
||||
new ListBeatmapPanel(explicitMap)
|
||||
},
|
||||
},
|
||||
};
|
||||
|
87
osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs
Normal file
87
osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Comments;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneDrawableComment : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
private Container container;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background4,
|
||||
},
|
||||
container = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
[TestCaseSource(nameof(comments))]
|
||||
public void TestComment(string description, string text)
|
||||
{
|
||||
AddStep(description, () =>
|
||||
{
|
||||
comment.Message = text;
|
||||
container.Add(new DrawableComment(comment));
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly Comment comment = new Comment
|
||||
{
|
||||
Id = 1,
|
||||
LegacyName = "Test User",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 0,
|
||||
};
|
||||
|
||||
private static object[] comments =
|
||||
{
|
||||
new[] { "Plain", "This is plain comment" },
|
||||
new[] { "Link", "Please visit https://osu.ppy.sh" },
|
||||
|
||||
new[]
|
||||
{
|
||||
"Heading", @"# Heading 1
|
||||
## Heading 2
|
||||
### Heading 3
|
||||
#### Heading 4
|
||||
##### Heading 5
|
||||
###### Heading 6"
|
||||
},
|
||||
|
||||
// Taken from https://github.com/ppy/osu/issues/13993#issuecomment-885994077
|
||||
new[]
|
||||
{
|
||||
"Problematic", @"My tablet doesn't work :(
|
||||
It's a Huion 420 and it's apparently incompatible with OpenTablet Driver. The warning I get is: ""DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"" and it repeats 4 times on the notification before logging subsequent warnings.
|
||||
Checking the logs, it looks for other Huion tablets before sending the notification (e.g.
|
||||
""2021-07-23 03:52:33 [verbose]: Detect: Searching for tablet 'Huion WH1409 V2'
|
||||
20 2021-07-23 03:52:33 [error]: DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"")
|
||||
I use an Arch based installation of Linux and the tablet runs perfectly with Digimend kernel driver, with area configuration, pen pressure, etc. On osu!lazer the cursor disappears until I set it to ""Borderless"" instead of ""Fullscreen"" and even after it shows up, it goes to the bottom left corner as soon as a map starts.
|
||||
I have honestly 0 idea of whats going on at this point."
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -3,14 +3,13 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.Dashboard.Friends;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Allocation;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Dashboard.Friends;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -21,7 +20,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
private TestFriendDisplay display;
|
||||
private FriendDisplay display;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
@ -29,20 +28,20 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Child = new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = display = new TestFriendDisplay()
|
||||
Child = display = new FriendDisplay()
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestOffline()
|
||||
{
|
||||
AddStep("Populate", () => display.Users = getUsers());
|
||||
AddStep("Populate with offline test users", () => display.Users = getUsers());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOnline()
|
||||
{
|
||||
AddStep("Fetch online", () => display?.Fetch());
|
||||
// No need to do anything, fetch is performed automatically.
|
||||
}
|
||||
|
||||
private List<User> getUsers() => new List<User>
|
||||
@ -52,7 +51,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Username = "flyte",
|
||||
Id = 3103765,
|
||||
IsOnline = true,
|
||||
CurrentModeRank = 1111,
|
||||
Statistics = new UserStatistics { GlobalRank = 1111 },
|
||||
Country = new Country { FlagName = "JP" },
|
||||
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
||||
},
|
||||
@ -61,7 +60,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Username = "peppy",
|
||||
Id = 2,
|
||||
IsOnline = false,
|
||||
CurrentModeRank = 2222,
|
||||
Statistics = new UserStatistics { GlobalRank = 2222 },
|
||||
Country = new Country { FlagName = "AU" },
|
||||
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||
IsSupporter = true,
|
||||
@ -77,17 +76,5 @@ namespace osu.Game.Tests.Visual.Online
|
||||
LastVisit = DateTimeOffset.Now
|
||||
}
|
||||
};
|
||||
|
||||
private class TestFriendDisplay : FriendDisplay
|
||||
{
|
||||
public void Fetch()
|
||||
{
|
||||
base.APIStateChanged(API, APIState.Online);
|
||||
}
|
||||
|
||||
public override void APIStateChanged(IAPIProvider api, APIState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestFixture]
|
||||
public class TestSceneFullscreenOverlay : OsuTestScene
|
||||
{
|
||||
private FullscreenOverlay overlay;
|
||||
private FullscreenOverlay<OverlayHeader> overlay;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("fire count 3", () => fireCount == 3);
|
||||
}
|
||||
|
||||
private class TestFullscreenOverlay : FullscreenOverlay
|
||||
private class TestFullscreenOverlay : FullscreenOverlay<OverlayHeader>
|
||||
{
|
||||
public TestFullscreenOverlay()
|
||||
: base(OverlayColourScheme.Pink)
|
||||
@ -52,6 +52,17 @@ namespace osu.Game.Tests.Visual.Online
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override OverlayHeader CreateHeader() => new TestHeader();
|
||||
|
||||
internal class TestHeader : OverlayHeader
|
||||
{
|
||||
protected override OverlayTitle CreateTitle() => new TestTitle();
|
||||
|
||||
internal class TestTitle : OverlayTitle
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
61
osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs
Normal file
61
osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
using System;
|
||||
using osu.Game.Overlays.Dashboard.Home.News;
|
||||
using osuTK;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneHomeNewsPanel : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
public TestSceneHomeNewsPanel()
|
||||
{
|
||||
Add(new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Width = 500,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FeaturedNewsItemPanel(new APINewsPost
|
||||
{
|
||||
Title = "This post has an image which starts with \"/\" and has many authors!",
|
||||
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
|
||||
PublishedAt = DateTimeOffset.Now,
|
||||
Slug = "2020-07-16-summer-theme-park-2020-voting-open"
|
||||
}),
|
||||
new NewsItemGroupPanel(new List<APINewsPost>
|
||||
{
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "Title 1",
|
||||
Slug = "2020-07-16-summer-theme-park-2020-voting-open",
|
||||
PublishedAt = DateTimeOffset.Now,
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "Title of this post is Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
Slug = "2020-07-16-summer-theme-park-2020-voting-open",
|
||||
PublishedAt = DateTimeOffset.Now,
|
||||
}
|
||||
}),
|
||||
new ShowMoreNewsPanel()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -45,14 +46,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
args.NewItems.Cast<Mod>().ForEach(mod => selectedMods.Add(new OsuSpriteText
|
||||
args.NewItems.AsNonNull().Cast<Mod>().ForEach(mod => selectedMods.Add(new OsuSpriteText
|
||||
{
|
||||
Text = mod.Acronym,
|
||||
}));
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
args.OldItems.Cast<Mod>().ForEach(mod =>
|
||||
args.OldItems.AsNonNull().Cast<Mod>().ForEach(mod =>
|
||||
{
|
||||
foreach (var selected in selectedMods)
|
||||
{
|
||||
|
240
osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs
Normal file
240
osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs
Normal file
@ -0,0 +1,240 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneMessageNotifier : OsuManualInputManagerTestScene
|
||||
{
|
||||
private User friend;
|
||||
private Channel publicChannel;
|
||||
private Channel privateMessageChannel;
|
||||
private TestContainer testContainer;
|
||||
|
||||
private int messageIdCounter;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
if (API is DummyAPIAccess daa)
|
||||
{
|
||||
daa.HandleRequest = dummyAPIHandleRequest;
|
||||
}
|
||||
|
||||
friend = new User { Id = 0, Username = "Friend" };
|
||||
publicChannel = new Channel { Id = 1, Name = "osu" };
|
||||
privateMessageChannel = new Channel(friend) { Id = 2, Name = friend.Username, Type = ChannelType.PM };
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
Child = testContainer = new TestContainer(new[] { publicChannel, privateMessageChannel })
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
|
||||
testContainer.ChatOverlay.Show();
|
||||
});
|
||||
}
|
||||
|
||||
private bool dummyAPIHandleRequest(APIRequest request)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case GetMessagesRequest messagesRequest:
|
||||
messagesRequest.TriggerSuccess(new List<Message>(0));
|
||||
return true;
|
||||
|
||||
case CreateChannelRequest createChannelRequest:
|
||||
var apiChatChannel = new APIChatChannel
|
||||
{
|
||||
RecentMessages = new List<Message>(0),
|
||||
ChannelID = (int)createChannelRequest.Channel.Id
|
||||
};
|
||||
createChannelRequest.TriggerSuccess(apiChatChannel);
|
||||
return true;
|
||||
|
||||
case ListChannelsRequest listChannelsRequest:
|
||||
listChannelsRequest.TriggerSuccess(new List<Channel>(1) { publicChannel });
|
||||
return true;
|
||||
|
||||
case GetUpdatesRequest updatesRequest:
|
||||
updatesRequest.TriggerSuccess(new GetUpdatesResponse
|
||||
{
|
||||
Messages = new List<Message>(0),
|
||||
Presence = new List<Channel>(0)
|
||||
});
|
||||
return true;
|
||||
|
||||
case JoinChannelRequest joinChannelRequest:
|
||||
joinChannelRequest.TriggerSuccess();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPublicChannelMention()
|
||||
{
|
||||
AddStep("switch to PMs", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
|
||||
|
||||
AddStep("receive public message", () => receiveMessage(friend, publicChannel, "Hello everyone"));
|
||||
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
|
||||
|
||||
AddStep("receive message containing mention", () => receiveMessage(friend, publicChannel, $"Hello {API.LocalUser.Value.Username.ToLowerInvariant()}!"));
|
||||
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
|
||||
|
||||
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
|
||||
AddStep("click notification", clickNotification<MessageNotifier.MentionNotification>);
|
||||
|
||||
AddAssert("chat overlay is open", () => testContainer.ChatOverlay.State.Value == Visibility.Visible);
|
||||
AddAssert("public channel is selected", () => testContainer.ChannelManager.CurrentChannel.Value == publicChannel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPrivateMessageNotification()
|
||||
{
|
||||
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
|
||||
|
||||
AddStep("receive PM", () => receiveMessage(friend, privateMessageChannel, $"Hello {API.LocalUser.Value.Username}"));
|
||||
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
|
||||
|
||||
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
|
||||
AddStep("click notification", clickNotification<MessageNotifier.PrivateMessageNotification>);
|
||||
|
||||
AddAssert("chat overlay is open", () => testContainer.ChatOverlay.State.Value == Visibility.Visible);
|
||||
AddAssert("PM channel is selected", () => testContainer.ChannelManager.CurrentChannel.Value == privateMessageChannel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoNotificationWhenPMChannelOpen()
|
||||
{
|
||||
AddStep("switch to PMs", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
|
||||
|
||||
AddStep("receive PM", () => receiveMessage(friend, privateMessageChannel, "you're reading this, right?"));
|
||||
|
||||
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoNotificationWhenMentionedInOpenPublicChannel()
|
||||
{
|
||||
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
|
||||
|
||||
AddStep("receive mention", () => receiveMessage(friend, publicChannel, $"{API.LocalUser.Value.Username.ToUpperInvariant()} has been reading this"));
|
||||
|
||||
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoNotificationOnSelfMention()
|
||||
{
|
||||
AddStep("switch to PM channel", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
|
||||
|
||||
AddStep("receive self-mention", () => receiveMessage(API.LocalUser.Value, publicChannel, $"my name is {API.LocalUser.Value.Username}"));
|
||||
|
||||
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoNotificationOnPMFromSelf()
|
||||
{
|
||||
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
|
||||
|
||||
AddStep("receive PM from self", () => receiveMessage(API.LocalUser.Value, privateMessageChannel, "hey hey"));
|
||||
|
||||
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNotificationsNotFiredTwice()
|
||||
{
|
||||
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
|
||||
|
||||
AddStep("receive same PM twice", () =>
|
||||
{
|
||||
var message = createMessage(friend, privateMessageChannel, "hey hey");
|
||||
privateMessageChannel.AddNewMessages(message, message);
|
||||
});
|
||||
|
||||
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
|
||||
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
|
||||
}
|
||||
|
||||
private void receiveMessage(User sender, Channel channel, string content) => channel.AddNewMessages(createMessage(sender, channel, content));
|
||||
|
||||
private Message createMessage(User sender, Channel channel, string content) => new Message(messageIdCounter++)
|
||||
{
|
||||
Content = content,
|
||||
Sender = sender,
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
|
||||
private void clickNotification<T>() where T : Notification
|
||||
{
|
||||
var notification = testContainer.NotificationOverlay.ChildrenOfType<T>().Single();
|
||||
|
||||
InputManager.MoveMouseTo(notification);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
}
|
||||
|
||||
private class TestContainer : Container
|
||||
{
|
||||
[Cached]
|
||||
public ChannelManager ChannelManager { get; } = new ChannelManager();
|
||||
|
||||
[Cached]
|
||||
public NotificationOverlay NotificationOverlay { get; } = new NotificationOverlay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
};
|
||||
|
||||
[Cached]
|
||||
public ChatOverlay ChatOverlay { get; } = new ChatOverlay();
|
||||
|
||||
private readonly MessageNotifier messageNotifier = new MessageNotifier();
|
||||
|
||||
private readonly Channel[] channels;
|
||||
|
||||
public TestContainer(Channel[] channels)
|
||||
{
|
||||
this.channels = channels;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
ChannelManager,
|
||||
ChatOverlay,
|
||||
NotificationOverlay,
|
||||
messageNotifier,
|
||||
};
|
||||
|
||||
((BindableList<Channel>)ChannelManager.AvailableChannels).AddRange(channels);
|
||||
|
||||
foreach (var channel in channels)
|
||||
ChannelManager.JoinChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,15 +31,16 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
new NewsCard(new APINewsPost
|
||||
{
|
||||
Title = "This post has an image which starts with \"/\" and has many authors!",
|
||||
Title = "This post has an image which starts with \"/\" and has many authors! (clickable)",
|
||||
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
Author = "someone, someone1, someone2, someone3, someone4",
|
||||
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
PublishedAt = DateTimeOffset.Now,
|
||||
Slug = "2020-07-16-summer-theme-park-2020-voting-open"
|
||||
}),
|
||||
new NewsCard(new APINewsPost
|
||||
{
|
||||
Title = "This post has a full-url image! (HTML entity: &)",
|
||||
Title = "This post has a full-url image! (HTML entity: &) (non-clickable)",
|
||||
Preview = "boom (HTML entity: &)",
|
||||
Author = "user (HTML entity: &)",
|
||||
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
|
||||
|
53
osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs
Normal file
53
osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Overlays.News;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneNewsHeader : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
private TestHeader header;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
Child = header = new TestHeader
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestControl()
|
||||
{
|
||||
AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
|
||||
AddAssert("1 tab total", () => header.TabCount == 1);
|
||||
|
||||
AddStep("Set article 1", () => header.SetArticle("1"));
|
||||
AddAssert("Article 1 selected", () => header.Current.Value == "1");
|
||||
AddAssert("2 tabs total", () => header.TabCount == 2);
|
||||
|
||||
AddStep("Set article 2", () => header.SetArticle("2"));
|
||||
AddAssert("Article 2 selected", () => header.Current.Value == "2");
|
||||
AddAssert("2 tabs total", () => header.TabCount == 2);
|
||||
|
||||
AddStep("Set front page", () => header.SetFrontPage());
|
||||
AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
|
||||
AddAssert("1 tab total", () => header.TabCount == 1);
|
||||
}
|
||||
|
||||
private class TestHeader : NewsHeader
|
||||
{
|
||||
public int TabCount => TabControl.Items.Count;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,65 +2,113 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.News;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneNewsOverlay : OsuTestScene
|
||||
{
|
||||
private TestNewsOverlay news;
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
protected override void LoadComplete()
|
||||
private NewsOverlay overlay;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() => Child = overlay = new NewsOverlay());
|
||||
|
||||
[Test]
|
||||
public void TestRequest()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Add(news = new TestNewsOverlay());
|
||||
AddStep(@"Show", news.Show);
|
||||
AddStep(@"Hide", news.Hide);
|
||||
|
||||
AddStep(@"Show front page", () => news.ShowFrontPage());
|
||||
AddStep(@"Custom article", () => news.Current.Value = "Test Article 101");
|
||||
|
||||
AddStep(@"Article covers", () => news.LoadAndShowContent(new NewsCoverTest()));
|
||||
setUpNewsResponse(responseExample);
|
||||
AddStep("Show", () => overlay.Show());
|
||||
AddStep("Show article", () => overlay.ShowArticle("article"));
|
||||
}
|
||||
|
||||
private class TestNewsOverlay : NewsOverlay
|
||||
[Test]
|
||||
public void TestCursorRequest()
|
||||
{
|
||||
public new void LoadAndShowContent(NewsContent content) => base.LoadAndShowContent(content);
|
||||
setUpNewsResponse(responseWithCursor, "Set up cursor response");
|
||||
AddStep("Show", () => overlay.Show());
|
||||
AddUntilStep("Show More button is visible", () => showMoreButton?.Alpha == 1);
|
||||
setUpNewsResponse(responseWithNoCursor, "Set up no cursor response");
|
||||
AddStep("Click Show More", () => showMoreButton?.TriggerClick());
|
||||
AddUntilStep("Show More button is hidden", () => showMoreButton?.Alpha == 0);
|
||||
}
|
||||
|
||||
private class NewsCoverTest : NewsContent
|
||||
{
|
||||
public NewsCoverTest()
|
||||
private ShowMoreButton showMoreButton => overlay.ChildrenOfType<ShowMoreButton>().FirstOrDefault();
|
||||
|
||||
private void setUpNewsResponse(GetNewsResponse r, string testName = "Set up response")
|
||||
=> AddStep(testName, () =>
|
||||
{
|
||||
Spacing = new osuTK.Vector2(0, 10);
|
||||
|
||||
var article = new NewsArticleCover.ArticleInfo
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
Author = "Ephemeral",
|
||||
CoverUrl = "https://assets.ppy.sh/artists/58/header.jpg",
|
||||
Time = new DateTime(2019, 12, 4),
|
||||
Title = "New Featured Artist: Kurokotei"
|
||||
};
|
||||
if (!(request is GetNewsRequest getNewsRequest))
|
||||
return false;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new NewsArticleCover(article)
|
||||
{
|
||||
Height = 200
|
||||
},
|
||||
new NewsArticleCover(article)
|
||||
{
|
||||
Height = 120
|
||||
},
|
||||
new NewsArticleCover(article)
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Size = new osuTK.Vector2(400, 200),
|
||||
}
|
||||
getNewsRequest.TriggerSuccess(r);
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
private static GetNewsResponse responseExample => new GetNewsResponse
|
||||
{
|
||||
NewsPosts = new[]
|
||||
{
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "This post has an image which starts with \"/\" and has many authors!",
|
||||
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
Author = "someone, someone1, someone2, someone3, someone4",
|
||||
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "This post has a full-url image! (HTML entity: &)",
|
||||
Preview = "boom (HTML entity: &)",
|
||||
Author = "user (HTML entity: &)",
|
||||
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static GetNewsResponse responseWithCursor => new GetNewsResponse
|
||||
{
|
||||
NewsPosts = new[]
|
||||
{
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "This post has an image which starts with \"/\" and has many authors!",
|
||||
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
Author = "someone, someone1, someone2, someone3, someone4",
|
||||
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
}
|
||||
},
|
||||
Cursor = new Cursor()
|
||||
};
|
||||
|
||||
private static GetNewsResponse responseWithNoCursor => new GetNewsResponse
|
||||
{
|
||||
NewsPosts = new[]
|
||||
{
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "This post has a full-url image! (HTML entity: &)",
|
||||
Preview = "boom (HTML entity: &)",
|
||||
Author = "user (HTML entity: &)",
|
||||
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
}
|
||||
},
|
||||
Cursor = null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
152
osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs
Normal file
152
osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.News.Sidebar;
|
||||
using static osu.Game.Overlays.News.Sidebar.YearsPanel;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneNewsSidebar : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
private TestNewsSidebar sidebar;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() => Child = sidebar = new TestNewsSidebar { YearChanged = onYearChanged });
|
||||
|
||||
[Test]
|
||||
public void TestBasic()
|
||||
{
|
||||
AddStep("Add metadata", () => sidebar.Metadata.Value = getMetadata(2021));
|
||||
AddUntilStep("Month sections exist", () => sidebar.ChildrenOfType<MonthSection>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMetadataWithNoPosts()
|
||||
{
|
||||
AddStep("Add data with no posts", () => sidebar.Metadata.Value = metadata_with_no_posts);
|
||||
AddUntilStep("No month sections were created", () => !sidebar.ChildrenOfType<MonthSection>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestYearsPanelVisibility()
|
||||
{
|
||||
AddUntilStep("Years panel is hidden", () => yearsPanel?.Alpha == 0);
|
||||
AddStep("Add data", () => sidebar.Metadata.Value = getMetadata(2021));
|
||||
AddUntilStep("Years panel is visible", () => yearsPanel?.Alpha == 1);
|
||||
}
|
||||
|
||||
private void onYearChanged(int year) => sidebar.Metadata.Value = getMetadata(year);
|
||||
|
||||
private YearsPanel yearsPanel => sidebar.ChildrenOfType<YearsPanel>().FirstOrDefault();
|
||||
|
||||
private APINewsSidebar getMetadata(int year) => new APINewsSidebar
|
||||
{
|
||||
CurrentYear = year,
|
||||
Years = new[]
|
||||
{
|
||||
2021,
|
||||
2020,
|
||||
2019,
|
||||
2018,
|
||||
2017,
|
||||
2016,
|
||||
2015,
|
||||
2014,
|
||||
2013
|
||||
},
|
||||
NewsPosts = new List<APINewsPost>
|
||||
{
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Mar) Short title",
|
||||
PublishedAt = new DateTime(year, 3, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Mar) Oh boy that's a long post title I wonder if it will break anything",
|
||||
PublishedAt = new DateTime(year, 3, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Mar) Medium title, nothing to see here",
|
||||
PublishedAt = new DateTime(year, 3, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Feb) Short title",
|
||||
PublishedAt = new DateTime(year, 2, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Feb) Oh boy that's a long post title I wonder if it will break anything",
|
||||
PublishedAt = new DateTime(year, 2, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "(Feb) Medium title, nothing to see here",
|
||||
PublishedAt = new DateTime(year, 2, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "Short title",
|
||||
PublishedAt = new DateTime(year, 1, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "Oh boy that's a long post title I wonder if it will break anything",
|
||||
PublishedAt = new DateTime(year, 1, 1)
|
||||
},
|
||||
new APINewsPost
|
||||
{
|
||||
Title = "Medium title, nothing to see here",
|
||||
PublishedAt = new DateTime(year, 1, 1)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly APINewsSidebar metadata_with_no_posts = new APINewsSidebar
|
||||
{
|
||||
CurrentYear = 2021,
|
||||
Years = new[]
|
||||
{
|
||||
2021,
|
||||
2020,
|
||||
2019,
|
||||
2018,
|
||||
2017,
|
||||
2016,
|
||||
2015,
|
||||
2014,
|
||||
2013
|
||||
},
|
||||
NewsPosts = Array.Empty<APINewsPost>()
|
||||
};
|
||||
|
||||
private class TestNewsSidebar : NewsSidebar
|
||||
{
|
||||
public Action<int> YearChanged;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Metadata.BindValueChanged(metadata =>
|
||||
{
|
||||
foreach (var b in this.ChildrenOfType<YearButton>())
|
||||
b.Action = () => YearChanged?.Invoke(b.Year);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
@ -18,6 +19,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached(typeof(IChannelPostTarget))]
|
||||
private PostTarget postTarget { get; set; }
|
||||
|
||||
private DummyAPIAccess api => (DummyAPIAccess)API;
|
||||
|
||||
public TestSceneNowPlayingCommand()
|
||||
{
|
||||
Add(postTarget = new PostTarget());
|
||||
@ -26,7 +29,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestGenericActivity()
|
||||
{
|
||||
AddStep("Set activity", () => API.Activity.Value = new UserActivity.InLobby());
|
||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null));
|
||||
|
||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
||||
|
||||
@ -36,7 +39,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestEditActivity()
|
||||
{
|
||||
AddStep("Set activity", () => API.Activity.Value = new UserActivity.Editing(new BeatmapInfo()));
|
||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo()));
|
||||
|
||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
||||
|
||||
@ -46,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestPlayActivity()
|
||||
{
|
||||
AddStep("Set activity", () => API.Activity.Value = new UserActivity.SoloGame(new BeatmapInfo(), new RulesetInfo()));
|
||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.SoloGame(new BeatmapInfo(), new RulesetInfo()));
|
||||
|
||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
||||
|
||||
@ -57,9 +60,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestCase(false)]
|
||||
public void TestLinkPresence(bool hasOnlineId)
|
||||
{
|
||||
AddStep("Set activity", () => API.Activity.Value = new UserActivity.InLobby());
|
||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null));
|
||||
|
||||
AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(null, null)
|
||||
AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null)
|
||||
{
|
||||
BeatmapInfo = { OnlineBeatmapID = hasOnlineId ? 1234 : (int?)null }
|
||||
});
|
||||
@ -67,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
||||
|
||||
if (hasOnlineId)
|
||||
AddAssert("Check link presence", () => postTarget.LastMessage.Contains("https://osu.ppy.sh/b/1234"));
|
||||
AddAssert("Check link presence", () => postTarget.LastMessage.Contains("/b/1234"));
|
||||
else
|
||||
AddAssert("Check link not present", () => !postTarget.LastMessage.Contains("https://"));
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Overlays;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[Description("uses online API")]
|
||||
public class TestSceneOnlineBeatmapListingOverlay : OsuTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
private readonly BeatmapListingOverlay overlay;
|
||||
|
||||
public TestSceneOnlineBeatmapListingOverlay()
|
||||
{
|
||||
Add(overlay = new BeatmapListingOverlay());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestShow()
|
||||
{
|
||||
AddStep("Show", overlay.Show);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHide()
|
||||
{
|
||||
AddStep("Hide", overlay.Hide);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestOnlineStateVisibility()
|
||||
{
|
||||
AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online);
|
||||
AddStep("set status to online", () => ((DummyAPIAccess)API).SetState(APIState.Online));
|
||||
|
||||
AddUntilStep("children are visible", () => onlineView.ViewTarget.IsPresent);
|
||||
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingSpinner.IsPresent);
|
||||
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestOfflineStateVisibility()
|
||||
{
|
||||
AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline);
|
||||
AddStep("set status to offline", () => ((DummyAPIAccess)API).SetState(APIState.Offline));
|
||||
|
||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingSpinner.IsPresent);
|
||||
@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestConnectingStateVisibility()
|
||||
{
|
||||
AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting);
|
||||
AddStep("set status to connecting", () => ((DummyAPIAccess)API).SetState(APIState.Connecting));
|
||||
|
||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||
AddUntilStep("loading animation is visible", () => onlineView.LoadingSpinner.IsPresent);
|
||||
@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestFailingStateVisibility()
|
||||
{
|
||||
AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing);
|
||||
AddStep("set status to failing", () => ((DummyAPIAccess)API).SetState(APIState.Failing));
|
||||
|
||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||
AddUntilStep("loading animation is visible", () => onlineView.LoadingSpinner.IsPresent);
|
||||
|
181
osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs
Normal file
181
osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs
Normal file
@ -0,0 +1,181 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Overlays.Profile.Sections.Historical;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Users;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Allocation;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using static osu.Game.Users.User;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestScenePlayHistorySubsection : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red);
|
||||
|
||||
private readonly Bindable<User> user = new Bindable<User>();
|
||||
private readonly PlayHistorySubsection section;
|
||||
|
||||
public TestScenePlayHistorySubsection()
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background4
|
||||
},
|
||||
section = new PlayHistorySubsection(user)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNullValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_null_values);
|
||||
AddAssert("Section is hidden", () => section.Alpha == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_empty_values);
|
||||
AddAssert("Section is hidden", () => section.Alpha == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOneValue()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_one_value);
|
||||
AddAssert("Section is hidden", () => section.Alpha == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTwoValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_two_values);
|
||||
AddAssert("Section is visible", () => section.Alpha == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConstantValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_constant_values);
|
||||
AddAssert("Section is visible", () => section.Alpha == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConstantZeroValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_zero_values);
|
||||
AddAssert("Section is visible", () => section.Alpha == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFilledValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_filled_values);
|
||||
AddAssert("Section is visible", () => section.Alpha == 1);
|
||||
AddAssert("Array length is the same", () => user_with_filled_values.MonthlyPlaycounts.Length == getChartValuesLength());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMissingValues()
|
||||
{
|
||||
AddStep("Load user", () => user.Value = user_with_missing_values);
|
||||
AddAssert("Section is visible", () => section.Alpha == 1);
|
||||
AddAssert("Array length is 7", () => getChartValuesLength() == 7);
|
||||
}
|
||||
|
||||
private int getChartValuesLength() => this.ChildrenOfType<ProfileLineChart>().Single().Values.Length;
|
||||
|
||||
private static readonly User user_with_null_values = new User
|
||||
{
|
||||
Id = 1
|
||||
};
|
||||
|
||||
private static readonly User user_with_empty_values = new User
|
||||
{
|
||||
Id = 2,
|
||||
MonthlyPlaycounts = Array.Empty<UserHistoryCount>()
|
||||
};
|
||||
|
||||
private static readonly User user_with_one_value = new User
|
||||
{
|
||||
Id = 3,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 100 }
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly User user_with_two_values = new User
|
||||
{
|
||||
Id = 4,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 1 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 6, 1), Count = 2 }
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly User user_with_constant_values = new User
|
||||
{
|
||||
Id = 5,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 5 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 6, 1), Count = 5 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 7, 1), Count = 5 }
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly User user_with_zero_values = new User
|
||||
{
|
||||
Id = 6,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 0 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 6, 1), Count = 0 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 7, 1), Count = 0 }
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly User user_with_filled_values = new User
|
||||
{
|
||||
Id = 7,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 1000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 6, 1), Count = 20 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 7, 1), Count = 20000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 8, 1), Count = 30 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 9, 1), Count = 50 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 10, 1), Count = 2000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 11, 1), Count = 2100 }
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly User user_with_missing_values = new User
|
||||
{
|
||||
Id = 8,
|
||||
MonthlyPlaycounts = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2020, 1, 1), Count = 100 },
|
||||
new UserHistoryCount { Date = new DateTime(2020, 7, 1), Count = 200 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Profile.Sections;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneProfileCounterPill : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red);
|
||||
|
||||
private readonly CounterPill pill;
|
||||
private readonly BindableInt value = new BindableInt();
|
||||
|
||||
public TestSceneProfileCounterPill()
|
||||
{
|
||||
Child = pill = new CounterPill
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Current = { BindTarget = value }
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVisibility()
|
||||
{
|
||||
AddStep("Set value to 0", () => value.Value = 0);
|
||||
AddAssert("Check hidden", () => !pill.IsPresent);
|
||||
AddStep("Set value to 10", () => value.Value = 10);
|
||||
AddAssert("Check visible", () => pill.IsPresent);
|
||||
}
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 123456 },
|
||||
GlobalRank = 123456,
|
||||
PP = 12345,
|
||||
};
|
||||
});
|
||||
@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
GlobalRank = 89000,
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
GlobalRank = 89000,
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
GlobalRank = 12000,
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
@ -118,7 +118,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
GlobalRank = 12000,
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Add(rankingsOverlay = new TestRankingsOverlay
|
||||
{
|
||||
Country = { BindTarget = countryBindable },
|
||||
Scope = { BindTarget = scope },
|
||||
Header = { Current = { BindTarget = scope } },
|
||||
});
|
||||
}
|
||||
|
||||
@ -65,8 +65,6 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private class TestRankingsOverlay : RankingsOverlay
|
||||
{
|
||||
public new Bindable<Country> Country => base.Country;
|
||||
|
||||
public new Bindable<RankingsScope> Scope => base.Scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,19 +4,22 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneShowMoreButton : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||
|
||||
public TestSceneShowMoreButton()
|
||||
{
|
||||
TestButton button = null;
|
||||
ShowMoreButton button = null;
|
||||
|
||||
int fireCount = 0;
|
||||
|
||||
Add(button = new TestButton
|
||||
Add(button = new ShowMoreButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -29,33 +32,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
AddStep("click button", () => button.TriggerClick());
|
||||
|
||||
AddAssert("action fired once", () => fireCount == 1);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
AddStep("click button", () => button.TriggerClick());
|
||||
|
||||
AddAssert("action not fired", () => fireCount == 1);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
|
||||
AddUntilStep("wait for loaded", () => !button.IsLoading);
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
AddStep("click button", () => button.TriggerClick());
|
||||
|
||||
AddAssert("action fired twice", () => fireCount == 2);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
}
|
||||
|
||||
private class TestButton : ShowMoreButton
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colors)
|
||||
{
|
||||
IdleColour = colors.YellowDark;
|
||||
HoverColour = colors.Yellow;
|
||||
ChevronIconColour = colors.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,16 +8,16 @@ using osu.Game.Users;
|
||||
using osuTK;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays.Chat;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneStandAloneChatDisplay : OsuTestScene
|
||||
public class TestSceneStandAloneChatDisplay : OsuManualInputManagerTestScene
|
||||
{
|
||||
private readonly Channel testChannel = new Channel();
|
||||
|
||||
private readonly User admin = new User
|
||||
{
|
||||
Username = "HappyStick",
|
||||
@ -46,92 +46,119 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private ChannelManager channelManager = new ChannelManager();
|
||||
|
||||
private readonly TestStandAloneChatDisplay chatDisplay;
|
||||
private readonly TestStandAloneChatDisplay chatDisplay2;
|
||||
private TestStandAloneChatDisplay chatDisplay;
|
||||
private int messageIdSequence;
|
||||
|
||||
private Channel testChannel;
|
||||
|
||||
public TestSceneStandAloneChatDisplay()
|
||||
{
|
||||
Add(channelManager);
|
||||
|
||||
Add(chatDisplay = new TestStandAloneChatDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 80)
|
||||
});
|
||||
|
||||
Add(chatDisplay2 = new TestStandAloneChatDisplay(true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 150)
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
base.LoadComplete();
|
||||
messageIdSequence = 0;
|
||||
channelManager.CurrentChannel.Value = testChannel = new Channel();
|
||||
|
||||
channelManager.CurrentChannel.Value = testChannel;
|
||||
Children = new[]
|
||||
{
|
||||
chatDisplay = new TestStandAloneChatDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 80),
|
||||
Channel = { Value = testChannel },
|
||||
},
|
||||
new TestStandAloneChatDisplay(true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 150),
|
||||
Channel = { Value = testChannel },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
chatDisplay.Channel.Value = testChannel;
|
||||
chatDisplay2.Channel.Value = testChannel;
|
||||
[Test]
|
||||
public void TestSystemMessageOrdering()
|
||||
{
|
||||
var standardMessage = new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I am a wang!"
|
||||
};
|
||||
|
||||
int sequence = 0;
|
||||
var infoMessage1 = new InfoMessage($"the system is calling {messageIdSequence++}");
|
||||
var infoMessage2 = new InfoMessage($"the system is calling {messageIdSequence++}");
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(standardMessage));
|
||||
AddStep("message from system", () => testChannel.AddNewMessages(infoMessage1));
|
||||
AddStep("message from system", () => testChannel.AddNewMessages(infoMessage2));
|
||||
|
||||
AddAssert("message order is correct", () => testChannel.Messages.Count == 3
|
||||
&& testChannel.Messages[0] == standardMessage
|
||||
&& testChannel.Messages[1] == infoMessage1
|
||||
&& testChannel.Messages[2] == infoMessage2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestManyMessages()
|
||||
{
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I am a wang!"
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I am team red."
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I plan to win!"
|
||||
}));
|
||||
|
||||
AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = blueUser,
|
||||
Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand."
|
||||
}));
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "Okay okay, calm down guys. Let's do this!"
|
||||
}));
|
||||
|
||||
AddStep("message from long username", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from long username", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Hi guys, my new username is lit!"
|
||||
}));
|
||||
|
||||
AddStep("message with new date", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message with new date", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Message from the future!",
|
||||
Timestamp = DateTimeOffset.Now
|
||||
}));
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
checkScrolledToBottom();
|
||||
|
||||
const int messages_per_call = 10;
|
||||
AddRepeatStep("add many messages", () =>
|
||||
{
|
||||
for (int i = 0; i < messages_per_call; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(sequence++)
|
||||
testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Many messages! " + Guid.NewGuid(),
|
||||
@ -153,9 +180,133 @@ namespace osu.Game.Tests.Visual.Online
|
||||
return true;
|
||||
});
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that when a message gets wrapped by the chat display getting contracted while scrolled to bottom, the chat will still keep scrolling down.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMessageWrappingKeepsAutoScrolling()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
// send message with short words for text wrapping to occur when contracting chat.
|
||||
sendMessage();
|
||||
|
||||
AddStep("contract chat", () => chatDisplay.Width -= 100);
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("send another message", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "As we were saying...",
|
||||
}));
|
||||
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserScrollOverride()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("User scroll up", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre + new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
checkNotScrolledToBottom();
|
||||
sendMessage();
|
||||
checkNotScrolledToBottom();
|
||||
|
||||
AddRepeatStep("User scroll to bottom", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre - new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
}, 5);
|
||||
|
||||
checkScrolledToBottom();
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalEchoMessageResetsScroll()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("User scroll up", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre + new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
checkNotScrolledToBottom();
|
||||
sendMessage();
|
||||
checkNotScrolledToBottom();
|
||||
|
||||
sendLocalMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
private void fillChat()
|
||||
{
|
||||
AddStep("fill chat", () =>
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = $"some stuff {Guid.NewGuid()}",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
private void sendMessage()
|
||||
{
|
||||
AddStep("send lorem ipsum", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce et bibendum velit.",
|
||||
}));
|
||||
}
|
||||
|
||||
private void sendLocalMessage()
|
||||
{
|
||||
AddStep("send local echo", () => testChannel.AddLocalEcho(new LocalEchoMessage
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "This is a local echo message.",
|
||||
}));
|
||||
}
|
||||
|
||||
private void checkScrolledToBottom() =>
|
||||
AddUntilStep("is scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
|
||||
private void checkNotScrolledToBottom() =>
|
||||
AddUntilStep("not scrolled to bottom", () => !chatDisplay.ScrolledToBottom);
|
||||
|
||||
private class TestStandAloneChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
public TestStandAloneChatDisplay(bool textbox = false)
|
||||
@ -165,7 +316,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
protected DrawableChannel DrawableChannel => InternalChildren.OfType<DrawableChannel>().First();
|
||||
|
||||
protected OsuScrollContainer ScrollContainer => (OsuScrollContainer)((Container)DrawableChannel.Child).Child;
|
||||
protected UserTrackingScrollContainer ScrollContainer => (UserTrackingScrollContainer)((Container)DrawableChannel.Child).Child;
|
||||
|
||||
public FillFlowContainer FillFlow => (FillFlowContainer)ScrollContainer.Child;
|
||||
|
||||
|
56
osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs
Normal file
56
osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Game.Overlays.Profile.Sections.Historical;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Allocation;
|
||||
using static osu.Game.Users.User;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneUserHistoryGraph : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||
|
||||
public TestSceneUserHistoryGraph()
|
||||
{
|
||||
UserHistoryGraph graph;
|
||||
|
||||
Add(graph = new UserHistoryGraph("Test")
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 200,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
|
||||
var values = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2000, 1, 1), Count = 10 },
|
||||
new UserHistoryCount { Date = new DateTime(2000, 2, 1), Count = 20 },
|
||||
new UserHistoryCount { Date = new DateTime(2000, 3, 1), Count = 100 },
|
||||
new UserHistoryCount { Date = new DateTime(2000, 4, 1), Count = 15 },
|
||||
new UserHistoryCount { Date = new DateTime(2000, 5, 1), Count = 30 }
|
||||
};
|
||||
|
||||
var moreValues = new[]
|
||||
{
|
||||
new UserHistoryCount { Date = new DateTime(2010, 5, 1), Count = 1000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 6, 1), Count = 20 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 7, 1), Count = 20000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 8, 1), Count = 30 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 9, 1), Count = 50 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 10, 1), Count = 2000 },
|
||||
new UserHistoryCount { Date = new DateTime(2010, 11, 1), Count = 2100 }
|
||||
};
|
||||
|
||||
AddStep("Set fake values", () => graph.Values = values);
|
||||
AddStep("Set more values", () => graph.Values = moreValues);
|
||||
AddStep("Set null values", () => graph.Values = null);
|
||||
AddStep("Set empty values", () => graph.Values = Array.Empty<UserHistoryCount>());
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
ProfileOrder = new[] { "me" },
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 },
|
||||
GlobalRank = 2148,
|
||||
CountryRank = 1,
|
||||
PP = 4567.89m,
|
||||
Level = new UserStatistics.LevelInfo
|
||||
{
|
||||
|
@ -7,6 +7,8 @@ using osu.Game.Overlays.Comments;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -16,33 +18,56 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
private VotePill votePill;
|
||||
[Cached]
|
||||
private LoginOverlay login;
|
||||
|
||||
private TestPill votePill;
|
||||
private readonly Container pillContainer;
|
||||
|
||||
public TestSceneVotePill()
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
pillContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both
|
||||
},
|
||||
login = new LoginOverlay()
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("User comment", () => addVotePill(getUserComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Background is transparent", () => votePill.Background.Alpha == 0);
|
||||
AddStep("Click", () => votePill.TriggerClick());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRandomCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Background is visible", () => votePill.Background.Alpha == 1);
|
||||
AddStep("Click", () => votePill.TriggerClick());
|
||||
AddAssert("Loading", () => votePill.IsLoading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOfflineRandomCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log out", API.Logout);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
AddStep("Click", () => votePill.TriggerClick());
|
||||
AddAssert("Login overlay is visible", () => login.State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
private void logIn() => API.Login("localUser", "password");
|
||||
@ -63,12 +88,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private void addVotePill(Comment comment)
|
||||
{
|
||||
Clear();
|
||||
Add(votePill = new VotePill(comment)
|
||||
pillContainer.Clear();
|
||||
pillContainer.Child = votePill = new TestPill(comment)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private class TestPill : VotePill
|
||||
{
|
||||
public new Box Background => base.Background;
|
||||
|
||||
public TestPill(Comment comment)
|
||||
: base(comment)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
103
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
103
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Wiki;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneWikiHeader : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||
|
||||
[Cached]
|
||||
private readonly Bindable<APIWikiPage> wikiPageData = new Bindable<APIWikiPage>(new APIWikiPage
|
||||
{
|
||||
Title = "Main Page",
|
||||
Path = "Main_Page",
|
||||
});
|
||||
|
||||
private TestHeader header;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Child = header = new TestHeader
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
ShowIndexPage = dummyShowIndexPage,
|
||||
ShowParentPage = dummyShowParentPage,
|
||||
};
|
||||
wikiPageData.BindTo(header.WikiPageData);
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestWikiHeader()
|
||||
{
|
||||
AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
|
||||
|
||||
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||
{
|
||||
Title = "Welcome",
|
||||
Path = "Welcome"
|
||||
});
|
||||
AddAssert("Current is welcome", () => checkCurrent("Welcome"));
|
||||
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||
|
||||
AddStep("Change current to index", () => header.Current.Value = WikiHeader.IndexPageString);
|
||||
AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
|
||||
|
||||
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||
{
|
||||
Title = "Developers",
|
||||
Path = "People/The_Team/Developers",
|
||||
Subtitle = "The Team",
|
||||
});
|
||||
AddAssert("Current is 'Developers'", () => checkCurrent("Developers"));
|
||||
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||
|
||||
AddStep("Change current to 'The Team'", () => header.Current.Value = "The Team");
|
||||
AddAssert("Current is 'The Team'", () => checkCurrent("The Team"));
|
||||
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||
}
|
||||
|
||||
private bool checkCurrent(LocalisableString expectedCurrent) => header.Current.Value == expectedCurrent;
|
||||
|
||||
private bool checkBreadcrumb()
|
||||
{
|
||||
var result = header.TabControlItems.Contains(wikiPageData.Value.Title);
|
||||
|
||||
if (wikiPageData.Value.Subtitle != null)
|
||||
result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void dummyShowIndexPage() => wikiPageData.SetDefault();
|
||||
|
||||
private void dummyShowParentPage()
|
||||
{
|
||||
wikiPageData.Value = new APIWikiPage
|
||||
{
|
||||
Path = "People/The_Team",
|
||||
Title = "The Team",
|
||||
Subtitle = "People"
|
||||
};
|
||||
}
|
||||
|
||||
private class TestHeader : WikiHeader
|
||||
{
|
||||
public IReadOnlyList<LocalisableString?> TabControlItems => TabControl.Items;
|
||||
}
|
||||
}
|
||||
}
|
43
osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs
Normal file
43
osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Wiki;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneWikiMainPage : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||
|
||||
public TestSceneWikiMainPage()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = overlayColour.Background5,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(20),
|
||||
Child = new WikiMainPage
|
||||
{
|
||||
Markdown = main_page_markdown
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// From https://osu.ppy.sh/api/v2/wiki/en/Main_Page
|
||||
private const string main_page_markdown =
|
||||
"---\nlayout: main_page\n---\n\n<!-- Do not add any empty lines inside this div. -->\n\n<div class=\"wiki-main-page__blurb\">\nWelcome to the osu! wiki, a project containing a wide range of osu! related information.\n</div>\n\n<div class=\"wiki-main-page__panels\">\n<div class=\"wiki-main-page-panel wiki-main-page-panel--full\">\n\n# Getting started\n\n[Welcome](/wiki/Welcome) • [Installation](/wiki/Installation) • [Registration](/wiki/Registration) • [Help Centre](/wiki/Help_Centre) • [FAQ](/wiki/FAQ)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Game client\n\n[Interface](/wiki/Interface) • [Options](/wiki/Options) • [Visual settings](/wiki/Visual_Settings) • [Shortcut key reference](/wiki/Shortcut_key_reference) • [Configuration file](/wiki/osu!_Program_Files/User_Configuration_File) • [Program files](/wiki/osu!_Program_Files)\n\n[File formats](/wiki/osu!_File_Formats): [.osz](/wiki/osu!_File_Formats/Osz_(file_format)) • [.osk](/wiki/osu!_File_Formats/Osk_(file_format)) • [.osr](/wiki/osu!_File_Formats/Osr_(file_format)) • [.osu](/wiki/osu!_File_Formats/Osu_(file_format)) • [.osb](/wiki/osu!_File_Formats/Osb_(file_format)) • [.db](/wiki/osu!_File_Formats/Db_(file_format))\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Gameplay\n\n[Game modes](/wiki/Game_mode): [osu!](/wiki/Game_mode/osu!) • [osu!taiko](/wiki/Game_mode/osu!taiko) • [osu!catch](/wiki/Game_mode/osu!catch) • [osu!mania](/wiki/Game_mode/osu!mania)\n\n[Beatmap](/wiki/Beatmap) • [Hit object](/wiki/Hit_object) • [Mods](/wiki/Game_modifier) • [Score](/wiki/Score) • [Replay](/wiki/Replay) • [Multi](/wiki/Multi)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# [Beatmap editor](/wiki/Beatmap_Editor)\n\nSections: [Compose](/wiki/Beatmap_Editor/Compose) • [Design](/wiki/Beatmap_Editor/Design) • [Timing](/wiki/Beatmap_Editor/Timing) • [Song setup](/wiki/Beatmap_Editor/Song_Setup)\n\nComponents: [AiMod](/wiki/Beatmap_Editor/AiMod) • [Beat snap divisor](/wiki/Beatmap_Editor/Beat_Snap_Divisor) • [Distance snap](/wiki/Beatmap_Editor/Distance_Snap) • [Menu](/wiki/Beatmap_Editor/Menu) • [SB load](/wiki/Beatmap_Editor/SB_Load) • [Timelines](/wiki/Beatmap_Editor/Timelines)\n\n[Beatmapping](/wiki/Beatmapping) • [Difficulty](/wiki/Beatmap/Difficulty) • [Mapping techniques](/wiki/Mapping_Techniques) • [Storyboarding](/wiki/Storyboarding)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Beatmap submission and ranking\n\n[Submission](/wiki/Submission) • [Modding](/wiki/Modding) • [Ranking procedure](/wiki/Beatmap_ranking_procedure) • [Mappers' Guild](/wiki/Mappers_Guild) • [Project Loved](/wiki/Project_Loved)\n\n[Ranking criteria](/wiki/Ranking_Criteria): [osu!](/wiki/Ranking_Criteria/osu!) • [osu!taiko](/wiki/Ranking_Criteria/osu!taiko) • [osu!catch](/wiki/Ranking_Criteria/osu!catch) • [osu!mania](/wiki/Ranking_Criteria/osu!mania)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Community\n\n[Tournaments](/wiki/Tournaments) • [Skinning](/wiki/Skinning) • [Projects](/wiki/Projects) • [Guides](/wiki/Guides) • [osu!dev Discord server](/wiki/osu!dev_Discord_server) • [How you can help](/wiki/How_You_Can_Help!) • [Glossary](/wiki/Glossary)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# People\n\n[The Team](/wiki/People/The_Team): [Developers](/wiki/People/The_Team/Developers) • [Global Moderation Team](/wiki/People/The_Team/Global_Moderation_Team) • [Support Team](/wiki/People/The_Team/Support_Team) • [Nomination Assessment Team](/wiki/People/The_Team/Nomination_Assessment_Team) • [Beatmap Nominators](/wiki/People/The_Team/Beatmap_Nominators) • [osu! Alumni](/wiki/People/The_Team/osu!_Alumni) • [Project Loved Team](/wiki/People/The_Team/Project_Loved_Team)\n\nOrganisations: [osu! UCI](/wiki/Organisations/osu!_UCI)\n\n[Community Contributors](/wiki/People/Community_Contributors) • [Users with unique titles](/wiki/People/Users_with_unique_titles)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# For developers\n\n[API](/wiki/osu!api) • [Bot account](/wiki/Bot_account) • [Brand identity guidelines](/wiki/Brand_identity_guidelines)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# About the wiki\n\n[Sitemap](/wiki/Sitemap) • [Contribution guide](/wiki/osu!_wiki_Contribution_Guide) • [Article styling criteria](/wiki/Article_Styling_Criteria) • [News styling criteria](/wiki/News_Styling_Criteria)\n\n</div>\n</div>\n";
|
||||
}
|
||||
}
|
214
osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs
Normal file
214
osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs
Normal file
@ -0,0 +1,214 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Containers.Markdown;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Containers.Markdown;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Wiki.Markdown;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneWikiMarkdownContainer : OsuTestScene
|
||||
{
|
||||
private TestMarkdownContainer markdownContainer;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = overlayColour.Background5,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(20),
|
||||
Child = markdownContainer = new TestMarkdownContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestLink()
|
||||
{
|
||||
AddStep("set current path", () => markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Article_styling_criteria/");
|
||||
|
||||
AddStep("set '/wiki/Main_Page''", () => markdownContainer.Text = "[wiki main page](/wiki/Main_Page)");
|
||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Main_Page");
|
||||
|
||||
AddStep("set '../FAQ''", () => markdownContainer.Text = "[FAQ](../FAQ)");
|
||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/FAQ");
|
||||
|
||||
AddStep("set './Writing''", () => markdownContainer.Text = "[wiki writing guidline](./Writing)");
|
||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Article_styling_criteria/Writing");
|
||||
|
||||
AddStep("set 'Formatting''", () => markdownContainer.Text = "[wiki formatting guidline](Formatting)");
|
||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Article_styling_criteria/Formatting");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOutdatedNoticeBox()
|
||||
{
|
||||
AddStep("Add outdated yaml header", () =>
|
||||
{
|
||||
markdownContainer.Text = @"---
|
||||
outdated: true
|
||||
---";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNeedsCleanupNoticeBox()
|
||||
{
|
||||
AddStep("Add needs cleanup yaml header", () =>
|
||||
{
|
||||
markdownContainer.Text = @"---
|
||||
needs_cleanup: true
|
||||
---";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOnlyShowOutdatedNoticeBox()
|
||||
{
|
||||
AddStep("Add outdated and needs cleanup yaml", () =>
|
||||
{
|
||||
markdownContainer.Text = @"---
|
||||
outdated: true
|
||||
needs_cleanup: true
|
||||
---";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAbsoluteImage()
|
||||
{
|
||||
AddStep("Add absolute image", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh";
|
||||
markdownContainer.Text = "";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRelativeImage()
|
||||
{
|
||||
AddStep("Add relative image", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/";
|
||||
markdownContainer.Text = "";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockImage()
|
||||
{
|
||||
AddStep("Add paragraph with block image", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/";
|
||||
markdownContainer.Text = @"Line before image
|
||||
|
||||

|
||||
|
||||
Line after image";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInlineImage()
|
||||
{
|
||||
AddStep("Add inline image", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh";
|
||||
markdownContainer.Text = " osu!";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTableWithImageContent()
|
||||
{
|
||||
AddStep("Add Table", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh";
|
||||
markdownContainer.Text = @"
|
||||
| Image | Name | Effect |
|
||||
| :-: | :-: | :-- |
|
||||
|  | 300 | A possible score when tapping a hit circle precisely on time, completing a Slider and keeping the cursor over every tick, or completing a Spinner with the Spinner Metre full. A score of 300 appears in an blue score by default. Scoring nothing except 300s in a beatmap will award the player with the SS or SSH grade. |
|
||||
|  | (激) Geki | A term from Ouendan, called Elite Beat! in EBA. Appears when playing the last element in a combo in which the player has scored only 300s. Getting a Geki will give a sizable boost to the Life Bar. By default, it is blue. |
|
||||
|  | 100 | A possible score one can get when tapping a Hit Object slightly late or early, completing a Slider and missing a number of ticks, or completing a Spinner with the Spinner Meter almost full. A score of 100 appears in a green score by default. When very skilled players test a beatmap and they get a lot of 100s, this may mean that the beatmap does not have correct timing. |
|
||||
|   | (喝) Katu or Katsu | A term from Ouendan, called Beat! in EBA. Appears when playing the last element in a combo in which the player has scored at least one 100, but no 50s or misses. Getting a Katu will give a small boost to the Life Bar. By default, it is coloured green or blue depending on whether the Katu itself is a 100 or a 300. |
|
||||
|  | 50 | A possible score one can get when tapping a hit circle rather early or late but not early or late enough to cause a miss, completing a Slider and missing a lot of ticks, or completing a Spinner with the Spinner Metre close to full. A score of 50 appears in a orange score by default. Scoring a 50 in a combo will prevent the appearance of a Katu or a Geki at the combo's end. |
|
||||
|  | Miss | A possible score one can get when not tapping a hit circle or too early (based on OD and AR, it may *shake* instead), not tapping or holding the Slider at least once, or completing a Spinner with low Spinner Metre fill. Scoring a Miss will reset the current combo to 0 and will prevent the appearance of a Katu or a Geki at the combo's end. |
|
||||
";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWideImageNotExceedContainer()
|
||||
{
|
||||
AddStep("Add image", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/";
|
||||
markdownContainer.Text = "";
|
||||
});
|
||||
|
||||
AddUntilStep("Wait image to load", () => markdownContainer.ChildrenOfType<DelayedLoadWrapper>().First().DelayedLoadCompleted);
|
||||
|
||||
AddStep("Change container width", () =>
|
||||
{
|
||||
markdownContainer.Width = 0.5f;
|
||||
});
|
||||
|
||||
AddAssert("Image not exceed container width", () =>
|
||||
{
|
||||
var spriteImage = markdownContainer.ChildrenOfType<Sprite>().First();
|
||||
return Precision.DefinitelyBigger(markdownContainer.DrawWidth, spriteImage.DrawWidth);
|
||||
});
|
||||
}
|
||||
|
||||
private class TestMarkdownContainer : WikiMarkdownContainer
|
||||
{
|
||||
public LinkInline Link;
|
||||
|
||||
public override MarkdownTextFlowContainer CreateTextFlow() => new TestMarkdownTextFlowContainer
|
||||
{
|
||||
UrlAdded = link => Link = link,
|
||||
};
|
||||
|
||||
private class TestMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer
|
||||
{
|
||||
public Action<LinkInline> UrlAdded;
|
||||
|
||||
protected override void AddLinkText(string text, LinkInline linkInline)
|
||||
{
|
||||
base.AddLinkText(text, linkInline);
|
||||
|
||||
UrlAdded?.Invoke(linkInline);
|
||||
}
|
||||
|
||||
protected override void AddImage(LinkInline linkInline) => AddDrawable(new WikiMarkdownImage(linkInline));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
84
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
File diff suppressed because one or more lines are too long
65
osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs
Normal file
65
osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using Markdig.Parsers;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics.Containers.Markdown;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Wiki;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneWikiSidebar : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayScrollContainer scrollContainer = new OverlayScrollContainer();
|
||||
|
||||
private WikiSidebar sidebar;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() => Child = sidebar = new WikiSidebar());
|
||||
|
||||
[Test]
|
||||
public void TestNoContent()
|
||||
{
|
||||
AddStep("No Content", () => { });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOnlyMainTitle()
|
||||
{
|
||||
AddStep("Add TOC", () =>
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
addTitle($"This is a very long title {i + 1}");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWithSubtitle()
|
||||
{
|
||||
AddStep("Add TOC", () =>
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
addTitle($"This is a very long title {i + 1}", i % 4 != 0);
|
||||
});
|
||||
}
|
||||
|
||||
private void addTitle(string text, bool subtitle = false)
|
||||
{
|
||||
var headingBlock = new HeadingBlock(new HeadingBlockParser())
|
||||
{
|
||||
Inline = new ContainerInline().AppendChild(new LiteralInline(text)),
|
||||
Level = subtitle ? 3 : 2,
|
||||
};
|
||||
var heading = new OsuMarkdownHeading(headingBlock);
|
||||
sidebar.AddEntry(headingBlock, heading);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user