Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0f6c76b7677c532458e1a8efec3b2c76
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,594 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Structures;
namespace Unity.Cloud.Collaborate.Tests.Models
{
public class ChangesModelTests
{
class TestableChangesModel : ChangesModel
{
public TestSourceControlProvider Provider => (TestSourceControlProvider)m_Provider;
public TestableChangesModel() : base (new TestSourceControlProvider())
{
}
public void SetToggled([CanBeNull] Dictionary<string, bool> toggled = null)
{
if (toggled != null)
{
toggledEntries = toggled;
}
}
internal override void UpdateChangeList(IReadOnlyList<IChangeEntry> list)
{
base.UpdateChangeList(list);
ValidateData();
}
public override bool UpdateEntryToggle(string path, bool value)
{
var refresh = base.UpdateEntryToggle(path, value);
ValidateData();
return refresh;
}
void ValidateData()
{
var toggledCount = 0;
foreach (var x in entryData.Select(entry => entry.Value))
{
Assert.IsTrue(toggledEntries.TryGetValue(x.Entry.Path, out var toggled) && x.Toggled == toggled);
if (!x.All && toggled) toggledCount++;
}
Assert.AreEqual(toggledCount, ToggledCount);
}
}
[Test]
public void ChangesModel_NullSourceControlEntries_EmptyResultLists()
{
var model = new TestableChangesModel();
model.OnStart();
model.UpdateChangeList(new List<IChangeEntry>());
var fullList = model.GetAllEntries();
Assert.AreEqual(1, fullList.Count);
Assert.IsTrue(fullList[0].All);
Assert.AreEqual(0, model.GetToggledEntries().Count);
Assert.AreEqual(0, model.GetUntoggledEntries().Count);
Assert.AreEqual(0, model.ToggledCount);
}
[Test]
public void ChangesModel_EmptySourceControlEntries_EmptyResultLists()
{
var model = new TestableChangesModel();
model.OnStart();
model.UpdateChangeList(new List<IChangeEntry>());
var fullList = model.GetAllEntries();
Assert.AreEqual(1, fullList.Count);
Assert.IsTrue(fullList[0].All);
Assert.AreEqual(0, model.GetToggledEntries().Count);
Assert.AreEqual(0, model.GetUntoggledEntries().Count);
Assert.AreEqual(0, model.ToggledCount);
}
[Test]
public void ChangesModel_SingleSourceControlEntries_SingleUntoggledResult()
{
var model = new TestableChangesModel();
model.OnStart();
var changes = BuildChangesList(1);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(2, fullList.Count);
Assert.IsTrue(fullList[0].All);
Assert.IsFalse(fullList[0].Toggled);
Assert.IsFalse(fullList[1].All);
Assert.IsFalse(fullList[1].Toggled);
var toggledList = model.GetToggledEntries();
Assert.AreEqual(0, toggledList.Count);
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(1, untoggledList.Count);
Assert.IsFalse(untoggledList[0].All);
Assert.IsFalse(untoggledList[0].Toggled);
Assert.AreEqual(0, model.ToggledCount);
}
[Test]
public void ChangesModel_MultipleSourceControlEntries_ToggleSingle()
{
const int entryCount = 5;
var model = new TestableChangesModel();
model.OnStart();
var changes = BuildChangesList(entryCount);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(entryCount, model.TotalCount);
Assert.AreEqual(entryCount + 1, fullList.Count);
Assert.IsTrue(fullList[0].All);
var toggledEntry = fullList[entryCount / 2 + 1];
model.UpdateEntryToggle(toggledEntry.Entry.Path, true);
Assert.IsTrue(toggledEntry.Toggled);
fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
foreach (var entry in fullList)
{
if (entry == fullList[0])
{
Assert.IsTrue(entry.All);
}
else
{
Assert.IsFalse(entry.All);
}
if (entry == toggledEntry)
{
Assert.IsTrue(entry.Toggled);
}
else
{
Assert.IsFalse(entry.Toggled);
}
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(1, toggledList.Count);
Assert.AreEqual(toggledEntry, toggledList[0]);
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(entryCount -1, untoggledList.Count);
foreach (var entry in untoggledList)
{
Assert.IsFalse(entry.All);
Assert.AreNotEqual(toggledEntry, entry);
}
Assert.AreEqual(1, model.ToggledCount);
}
[Test]
public void ChangesModel_MultipleSourceControlEntries_ToggleAll()
{
const int entryCount = 5;
var model = new TestableChangesModel();
model.OnStart();
var changes = BuildChangesList(entryCount);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
Assert.IsTrue(fullList[0].All);
model.UpdateEntryToggle(fullList[0].Entry.Path, true);
fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
foreach (var entry in fullList)
{
if (entry == fullList[0])
{
Assert.IsTrue(entry.All);
}
else
{
Assert.IsFalse(entry.All);
}
Assert.IsTrue(entry.Toggled);
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(entryCount, toggledList.Count);
foreach (var entry in toggledList)
{
Assert.IsFalse(entry.All);
}
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(0, untoggledList.Count);
Assert.AreEqual(entryCount, model.ToggledCount);
}
[Test]
public void ChangesModel_MultipleSourceControlEntries_ToggleAllIndividually()
{
const int entryCount = 5;
var model = new TestableChangesModel();
model.OnStart();
var changes = BuildChangesList(entryCount);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
Assert.IsTrue(fullList[0].All);
fullList = model.GetAllEntries();
foreach (var entry in fullList.Where(entry => !entry.All))
{
model.UpdateEntryToggle(entry.Entry.Path, true);
}
Assert.AreEqual(entryCount + 1, fullList.Count);
foreach (var entry in fullList)
{
if (entry == fullList[0])
{
Assert.IsTrue(entry.All);
}
else
{
Assert.IsFalse(entry.All);
}
Assert.IsTrue(entry.Toggled);
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(entryCount, toggledList.Count);
foreach (var entry in toggledList)
{
Assert.IsFalse(entry.All);
}
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(0, untoggledList.Count);
Assert.AreEqual(entryCount, model.ToggledCount);
}
[Test]
public void ChangesModel_MultipleSourceControlEntries_UntoggleSingleFromAll()
{
const int entryCount = 5;
var model = new TestableChangesModel();
model.OnStart();
var changes = BuildChangesList(entryCount);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
Assert.IsTrue(fullList[0].All);
model.UpdateEntryToggle(fullList[0].Entry.Path, true);
var untoggledEntry = fullList[entryCount / 2 + 1];
model.UpdateEntryToggle(untoggledEntry.Entry.Path, false);
Assert.IsFalse(untoggledEntry.Toggled);
fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
foreach (var entry in fullList)
{
if (entry == fullList[0])
{
Assert.IsTrue(entry.All);
}
else
{
Assert.IsFalse(entry.All);
}
if (entry == untoggledEntry || entry.All)
{
Assert.IsFalse(entry.Toggled);
}
else
{
Assert.IsTrue(entry.Toggled);
}
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(entryCount - 1, toggledList.Count);
foreach (var entry in toggledList)
{
Assert.IsFalse(entry.All);
Assert.AreNotEqual(untoggledEntry, entry);
}
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(1, untoggledList.Count);
Assert.AreEqual(untoggledEntry, untoggledList[0]);
Assert.AreEqual(entryCount - 1, model.ToggledCount);
}
[Test]
public void ChangesModel_MultipleSourceControlEntries_SomeConflicted()
{
const string conflictedPrefix = "conflicted-path";
var model = new TestableChangesModel();
model.OnStart();
var changes = new List<IChangeEntry>();
AddEntry(changes, "path1", ChangeEntryStatus.Modified, false);
AddEntry(changes, "path2", ChangeEntryStatus.Modified, false);
AddEntry(changes, "path3", ChangeEntryStatus.Modified, false);
AddEntry(changes, $"{conflictedPrefix}4", ChangeEntryStatus.Modified, false, true);
AddEntry(changes, $"{conflictedPrefix}5", ChangeEntryStatus.Modified, false, true);
model.UpdateChangeList(changes);
var conflictedList = model.GetConflictedEntries();
model.Provider.ConflictedState = true;
Assert.IsTrue(model.Conflicted);
Assert.AreEqual(2, model.ConflictedCount);
Assert.AreEqual(2, conflictedList.Count);
Assert.IsFalse(conflictedList[0].All);
Assert.IsFalse(conflictedList[1].All);
Assert.IsTrue(conflictedList[0].Conflicted);
Assert.IsTrue(conflictedList[1].Conflicted);
Assert.IsTrue(conflictedList[0].Entry.Path.StartsWith(conflictedPrefix));
Assert.IsTrue(conflictedList[1].Entry.Path.StartsWith(conflictedPrefix));
}
[Test]
public void ChangesModel_InitializeFromDictionary_TransfersToggledFlag()
{
const int entryCount = 5;
const int toggledCount = 2;
const int toggledIndex1 = 0;
const int toggledIndex2 = entryCount / 2 + 1;
const int untoggledIndex = entryCount - 1;
var changes = BuildChangesList(entryCount);
var dictionary = new Dictionary<string, bool>();
changes.ForEach( (x) => dictionary[x.Path] = false );
dictionary[changes[toggledIndex1].Path] = true;
dictionary[changes[toggledIndex2].Path] = true;
dictionary[changes[untoggledIndex].Path] = false;
var model = new TestableChangesModel();
model.OnStart();
model.SetToggled(dictionary);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(entryCount + 1, fullList.Count);
foreach (var entry in fullList)
{
if (entry == fullList[0])
{
Assert.IsTrue(entry.All);
}
else
{
Assert.IsFalse(entry.All);
}
if (entry.Entry.Path == changes[toggledIndex1].Path || entry.Entry.Path == changes[toggledIndex2].Path)
{
Assert.IsTrue(entry.Toggled);
}
else
{
Assert.IsFalse(entry.Toggled);
}
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(toggledCount, toggledList.Count);
foreach (var entry in toggledList)
{
Assert.IsTrue(entry.Entry.Path == changes[toggledIndex1].Path || entry.Entry.Path == changes[toggledIndex2].Path);
Assert.IsFalse(entry.All);
Assert.IsTrue(entry.Toggled);
}
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(entryCount - toggledCount, untoggledList.Count);
foreach (var entry in untoggledList)
{
Assert.IsTrue(entry.Entry.Path != changes[toggledIndex1].Path && entry.Entry.Path != changes[toggledIndex2].Path);
Assert.IsFalse(entry.All);
Assert.IsFalse(entry.Toggled);
}
}
[Test]
public void ChangesModel_SearchFilters_CaseInsensitive()
{
var changes = new List<IChangeEntry>();
AddEntry(changes, "alpha1", ChangeEntryStatus.Modified, false);
AddEntry(changes, "alpha2", ChangeEntryStatus.Modified, false);
AddEntry(changes, "bravo", ChangeEntryStatus.Modified, false);
AddEntry(changes, "charlie", ChangeEntryStatus.Modified, false);
AddEntry(changes, "Delta3", ChangeEntryStatus.Modified, false);
AddEntry(changes, "delta4", ChangeEntryStatus.Modified, false);
AddEntry(changes, "delta5", ChangeEntryStatus.Modified, false);
AddEntry(changes, "echo", ChangeEntryStatus.Modified, false);
AddEntry(changes, "Foxtrot6", ChangeEntryStatus.Modified, false);
AddEntry(changes, "Foxtrot7", ChangeEntryStatus.Modified, false);
AddEntry(changes, "golf", ChangeEntryStatus.Modified, false);
var dictionary = new Dictionary<string, bool>
{
["delta5"] = true, ["Foxtrot6"] = true, ["Foxtrot7"] = true, ["golf"] = true
};
var model = new TestableChangesModel();
model.OnStart();
model.SetToggled(dictionary);
model.UpdateChangeList(changes);
var fullList = model.GetAllEntries();
Assert.AreEqual(changes.Count, model.TotalCount);
Assert.AreEqual(changes.Count + 1, fullList.Count);
Assert.IsTrue(fullList[0].All);
var searchFullList = model.GetAllEntries("alpha");
Assert.AreEqual(2, searchFullList.Count);
foreach (var entry in searchFullList)
{
Assert.IsFalse(entry.All);
Assert.IsFalse(entry.Toggled);
}
var toggledList = model.GetToggledEntries();
Assert.AreEqual(dictionary.Count, toggledList.Count);
foreach (var entry in toggledList)
{
Assert.IsFalse(entry.All);
}
var searchToggledList = model.GetToggledEntries("fox");
Assert.AreEqual(2, searchToggledList.Count);
foreach (var entry in searchToggledList)
{
Assert.IsTrue(entry.Entry.Path.ToLower().Contains("fox"));
Assert.IsFalse(entry.All);
Assert.IsTrue(entry.Toggled);
}
var untoggledList = model.GetUntoggledEntries();
Assert.AreEqual(changes.Count - dictionary.Count, untoggledList.Count);
var searchUntoggledList = model.GetUntoggledEntries("Del");
Assert.AreEqual(2, searchUntoggledList.Count);
foreach (var entry in searchUntoggledList)
{
Assert.IsTrue(entry.Entry.Path.ToLower().Contains("del"));
Assert.AreNotEqual("delta5", entry.Entry.Path);
Assert.IsFalse(entry.All);
Assert.IsFalse(entry.Toggled);
}
Assert.AreEqual(dictionary.Count, model.ToggledCount);
}
[Test]
public void TestRequestInitialData()
{
var provider = new TestSourceControlProvider();
var model = new ChangesModel(provider);
model.OnStart();
var callCount = 0;
bool? callValue = null;
model.BusyStatusUpdated += b =>
{
callCount++;
callValue = b;
};
Assert.IsFalse(model.Busy);
model.RequestInitialData();
Assert.AreEqual(1, provider.RequestedChangeListCount);
Assert.IsNotNull(provider.RequestedChangeListCallback);
Assert.IsTrue(model.Busy);
Assert.IsTrue(callValue);
provider.RequestedChangeListCallback.Invoke(new List<IChangeEntry>());
Assert.IsFalse(model.Busy);
Assert.IsFalse(callValue);
Assert.AreEqual(2, callCount);
}
[Test]
public void TestReceiveUpdatedChangeListEvent()
{
var provider = new TestSourceControlProvider();
var model = new ChangesModel(provider);
model.OnStart();
var callCount = 0;
bool? callValue = null;
model.BusyStatusUpdated += b =>
{
callCount++;
callValue = b;
};
Assert.IsFalse(model.Busy);
provider.TriggerUpdatedChangeEntries();
Assert.AreEqual(1, provider.RequestedChangeListCount);
Assert.IsNotNull(provider.RequestedChangeListCallback);
Assert.IsTrue(model.Busy);
Assert.IsTrue(callValue);
provider.RequestedChangeListCallback.Invoke(new List<IChangeEntry>());
Assert.IsFalse(model.Busy);
Assert.IsFalse(callValue);
Assert.AreEqual(2, callCount);
}
[Test]
public void TestRequestDiff()
{
var provider = new TestSourceControlProvider();
var model = new ChangesModel(provider);
model.OnStart();
const string path = "path";
model.RequestDiffChanges(path);
Assert.AreEqual(1, provider.RequestedDiffChangesCount);
Assert.AreEqual(path, provider.RequestedDiffChangesPath);
}
[Test]
public void TestRequestDiscard()
{
var provider = new TestSourceControlProvider();
var model = new ChangesModel(provider);
model.OnStart();
const string path = "path";
var entry = new ChangeEntry(path);
model.RequestDiscard(entry);
Assert.AreEqual(1, provider.RequestedDiscardCount);
Assert.AreEqual(path, provider.RequestedDiscardEntry?.Path);
}
[Test]
public void TestRequestPublish()
{
var provider = new TestSourceControlProvider();
var model = new ChangesModel(provider);
model.OnStart();
const string message = "message";
model.RequestPublish(message, new List<IChangeEntry> { new ChangeEntry("path1"), new ChangeEntry("path2")});
Assert.AreEqual(1, provider.RequestedPublishCount);
Assert.AreEqual(message, provider.RequestedPublishMessage);
Assert.AreEqual(2, provider.RequestedPublishList?.Count);
}
static void AddEntry(ICollection<IChangeEntry> list, string pathTag, ChangeEntryStatus status, bool staged, bool unmerged = false)
{
list.Add(new ChangeEntry(pathTag, $"Original{pathTag}", status, staged, unmerged));
}
static List<IChangeEntry> BuildChangesList(int count)
{
var changes = new List<IChangeEntry>();
for (var i = 0; i < count; i++)
{
AddEntry(changes, $"Path{i}", ChangeEntryStatus.Modified, false);
}
return changes;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ac075bf7cbc97f4fbba27c78feb9c18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,130 @@
using System.Collections.Generic;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models;
namespace Unity.Cloud.Collaborate.Tests.Models
{
public class HistoryModelTests
{
TestSourceControlProvider m_Provider;
HistoryModel m_Model;
int m_BusyStatusUpdatedCount;
int m_EntryCountUpdatedCount;
int m_HistoryListReceivedCount;
int m_HistoryListUpdatedCount;
int m_SelectedRevisionReceivedCount;
[SetUp]
public void Setup()
{
m_Provider = new TestSourceControlProvider();
m_Model = new HistoryModel(m_Provider);
m_Model.OnStart();
m_BusyStatusUpdatedCount = 0;
m_EntryCountUpdatedCount = 0;
m_HistoryListReceivedCount = 0;
m_HistoryListUpdatedCount = 0;
m_SelectedRevisionReceivedCount = 0;
m_Model.BusyStatusUpdated += _ => m_BusyStatusUpdatedCount++;
m_Model.EntryCountUpdated += _ => m_EntryCountUpdatedCount++;
m_Model.HistoryListReceived += _ => m_HistoryListReceivedCount++;
m_Model.HistoryListUpdated += () => m_HistoryListUpdatedCount++;
m_Model.SelectedRevisionReceived += _ => m_SelectedRevisionReceivedCount++;
}
[TearDown]
public void TearDown()
{
m_Model = null;
m_Provider = null;
}
[Test]
public void TestHistoryListUpdated()
{
m_Provider.TriggerUpdatedHistoryEntries();
Assert.AreEqual(1, m_HistoryListUpdatedCount);
}
[Test]
public void TestIsBusyAndEntryCount()
{
m_Model.RequestEntryNumber();
Assert.AreEqual(1, m_Provider.RequestedHistoryCountCount);
Assert.AreEqual(false, m_Model.Busy);
Assert.AreEqual(2, m_BusyStatusUpdatedCount);
Assert.AreEqual(1, m_EntryCountUpdatedCount);
}
[Test]
public void TestRequestingPageOfRevisions()
{
m_Model.PageNumber = 2;
m_Model.RequestPageOfRevisions(10);
Assert.AreEqual(1, m_Provider.RequestedHistoryListCount);
Assert.AreEqual(20, m_Provider.RequestedHistoryListOffset);
Assert.AreEqual(10, m_Provider.RequestedHistoryListSize);
Assert.AreEqual(2, m_BusyStatusUpdatedCount);
Assert.AreEqual(1, m_HistoryListReceivedCount);
}
[Test]
public void TestRequestingSingleRevision()
{
const string revisionId = "123";
Assert.AreEqual(false, m_Model.IsRevisionSelected);
Assert.AreEqual(string.Empty, m_Model.SelectedRevisionId);
m_Model.RequestSingleRevision(revisionId);
Assert.AreEqual(true, m_Model.IsRevisionSelected);
Assert.AreEqual(1, m_Provider.RequestedHistoryRevisionCount);
Assert.AreEqual(revisionId, m_Provider.RequestedHistoryRevisionId);
Assert.AreEqual(2, m_BusyStatusUpdatedCount);
Assert.AreEqual(1, m_SelectedRevisionReceivedCount);
}
[Test]
public void TestRequestUpdateTo()
{
const string revisionId = "123";
m_Model.RequestUpdateTo(revisionId);
Assert.AreEqual(1, m_Provider.RequestedUpdateToCount);
Assert.AreEqual(revisionId, m_Provider.RequestedUpdateToRevisionId);
}
[Test]
public void TestRequestRestoreTo()
{
const string revisionId = "123";
m_Model.RequestRestoreTo(revisionId);
Assert.AreEqual(1, m_Provider.RequestedRestoreToCount);
Assert.AreEqual(revisionId, m_Provider.RequestedRestoreToRevisionId);
}
[Test]
public void TestRequestGoBackTo()
{
const string revisionId = "123";
m_Model.RequestGoBackTo(revisionId);
Assert.AreEqual(1, m_Provider.RequestedGoBackToCount);
Assert.AreEqual(revisionId, m_Provider.RequestedGoBackToRevisionId);
}
[Test]
public void TestRevert()
{
const string revisionId = "123";
m_Model.RequestRevert(revisionId, new List<string> { "a", "b", "c" });
Assert.AreEqual(1, m_Provider.RequestedRevertCount);
Assert.AreEqual(revisionId, m_Provider.RequestedRevertRevisionId);
Assert.AreEqual(3, m_Provider.RequestedRevertFileCount);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2079ae55f950aa4439a7ca7af8a9c136
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2fd9db3c67f54e59bb315a02250dbaf3
timeCreated: 1576179242

View file

@ -0,0 +1,254 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Api;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.Models.Structures;
using UnityEditor;
using UnityEngine;
namespace Unity.Cloud.Collaborate.Models.Providers
{
[UsedImplicitly]
internal class MockSourceControlProvider : ISourceControlProvider
{
public event Action UpdatedChangeList = delegate { };
public event Action<IReadOnlyList<string>> UpdatedSelectedChangeList = delegate { };
public event Action UpdatedHistoryEntries = delegate { };
public event Action<bool> UpdatedConflictState = delegate { };
public event Action<bool> UpdatedRemoteRevisionsAvailability = delegate { };
public event Action<ProjectStatus> UpdatedProjectStatus = delegate { };
public event Action<bool> UpdatedOperationStatus = delegate { };
public event Action<IProgressInfo> UpdatedOperationProgress = delegate { };
public event Action<IErrorInfo> ErrorOccurred = delegate { };
public event Action ErrorCleared = delegate { };
List<IChangeEntry> m_Changes;
readonly List<IHistoryEntry> m_History;
public MockSourceControlProvider()
{
m_Changes = new List<IChangeEntry>
{
new ChangeEntry("SomePath", "SomeOriginalPath", ChangeEntryStatus.Modified),
new ChangeEntry("SomeConflictedPath2", "SomeOriginalPath", ChangeEntryStatus.Modified, unmerged: true),
new ChangeEntry("SomePath3", "SomeOriginalPath", ChangeEntryStatus.Modified),
new ChangeEntry("SomeConflictedPath4", "SomeOriginalPath", ChangeEntryStatus.Modified, unmerged: true),
new ChangeEntry("SomeConflictedPath5", "SomeOriginalPath", ChangeEntryStatus.Modified, unmerged: true)
};
var historyChanges = new List<IChangeEntry>
{
new ChangeEntry("HistoryItemPath", "HistoryItemOriginalPath", ChangeEntryStatus.Modified, true)
};
m_History = new List<IHistoryEntry>
{
new HistoryEntry("HistoryItemRevisionId", HistoryEntryStatus.Current,"HistoryItemAuthorName", "HistoryItemMessage", DateTimeOffset.Now, historyChanges)
};
}
/// <summary>
/// Safely delays a call onto the main thread.
/// </summary>
/// <param name="call">Call to delay.</param>
static void SafeDelayCall(Action call)
{
Task.Delay(2000).ContinueWith(_ => EditorApplication.delayCall += () => call());
}
public void SetChanges(List<IChangeEntry> changes)
{
m_Changes = changes;
NotifyChanges();
}
IReadOnlyList<IChangeEntry> CloneChanges()
{
return m_Changes.Select(item => item).ToList();
}
IReadOnlyList<IHistoryEntry> CloneHistory()
{
return m_History.Select(item => item).ToList();
}
void NotifyChanges()
{
UpdatedChangeList?.Invoke();
}
void NotifyHistory()
{
UpdatedHistoryEntries?.Invoke();
}
public bool GetRemoteRevisionAvailability()
{
return false;
}
public bool GetConflictedState()
{
return m_Changes.Any(e => e.Unmerged);
}
public IProgressInfo GetProgressState()
{
return new ProgressInfo();
}
public IErrorInfo GetErrorState()
{
throw new NotImplementedException();
}
public ProjectStatus GetProjectStatus()
{
throw new NotImplementedException();
}
public void RequestChangeList(Action<IReadOnlyList<IChangeEntry>> callback)
{
callback(CloneChanges());
}
public void RequestPublish(string message, IReadOnlyList<IChangeEntry> changes = null)
{
throw new NotImplementedException();
}
public void RequestHistoryEntry(string revisionId, Action<IHistoryEntry> callback)
{
SafeDelayCall(() =>
{
try
{
callback(CloneHistory().FirstOrDefault(e => e.RevisionId == revisionId));
}
catch (Exception e)
{
Debug.LogException(e);
callback(CloneHistory().FirstOrDefault(i => i.RevisionId == revisionId));
}
});
}
public void RequestHistoryPage(int offset, int pageSize, Action<IReadOnlyList<IHistoryEntry>> callback)
{
var safeSize = Math.Min(m_History.Count - offset, pageSize);
SafeDelayCall(() =>
{
try
{
Assert.Greater(m_History.Count, offset, "The offset should never be greater than the total number of history entries.");
callback(CloneHistory().ToList().GetRange(offset, safeSize));
}
catch (Exception e)
{
Debug.LogException(e);
callback(null);
}
});
}
public void RequestHistoryCount(Action<int?> callback)
{
SafeDelayCall(() => callback(m_History.Count));
}
public void RequestDiscard(IChangeEntry entry)
{
throw new NotImplementedException();
}
public void RequestBulkDiscard(IReadOnlyList<IChangeEntry> entries)
{
throw new NotImplementedException();
}
public void RequestDiffChanges(string path)
{
throw new NotImplementedException();
}
public bool SupportsRevert { get; } = false;
public void RequestRevert(string revisionId, IReadOnlyList<string> files)
{
throw new NotImplementedException();
}
public void RequestUpdateTo(string revisionId)
{
throw new NotImplementedException();
}
public void RequestRestoreTo(string revisionId)
{
throw new NotImplementedException();
}
public void RequestGoBackTo(string revisionId)
{
throw new NotImplementedException();
}
public void ClearError()
{
}
public void RequestShowConflictedDifferences(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMerge(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMine(string[] paths)
{
throw new NotImplementedException();
}
public void RequestChooseRemote(string[] paths)
{
throw new NotImplementedException();
}
public void RequestSync()
{
throw new NotImplementedException();
}
public void RequestCancelJob()
{
throw new NotImplementedException();
}
public void RequestTurnOnService()
{
throw new NotImplementedException();
}
public void ShowServicePage()
{
throw new NotImplementedException();
}
public void ShowLoginPage()
{
throw new NotImplementedException();
}
public void ShowNoSeatPage()
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1a720a51e44604479a70a6a175aac0b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,191 @@
using System;
using System.Collections;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.Models.Providers;
using UnityEngine.TestTools;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class StartModelTests
{
TestCollab m_Provider;
AsyncToCoroutine m_Atc;
[OneTimeSetUp]
public void OneTimeSetup()
{
m_Atc = new AsyncToCoroutine();
}
[SetUp]
public void Setup()
{
m_Provider = new TestCollab();
}
[TearDown]
public void TearDown()
{
m_Provider = null;
}
[UnityTest]
public IEnumerator TestWhenProjectBoundSavesAssets()
{
return m_Atc.Run(async () =>
{
var saveAssetsCallCount = 0;
//ensure we return true for isProjectBound
m_Provider.isProjectBoundTestImpl = () => ProjectStatus.Bound;
m_Provider.saveAssetsTestImpl = () => saveAssetsCallCount++;
saveAssetsCallCount.ShouldBe(0);
await m_Provider.TestRequestTurnOnService();
saveAssetsCallCount.ShouldBe(1, $"Expected {nameof(saveAssetsCallCount)} to be 1");
});
}
[UnityTest]
public IEnumerator TestWhenGenesisReturnsForbiddenShowsCredentialsError()
{
return m_Atc.Run(async () =>
{
var showCredentialsErrorCallCount = 0;
var putAsyncCallCount = 0;
//ensure we return true for isProjectBound
m_Provider.isProjectBoundTestImpl = () => ProjectStatus.Bound;
m_Provider.showCredentialsErrorTestImpl = () => showCredentialsErrorCallCount++;
m_Provider.putAsyncTestImpl = () =>
{
putAsyncCallCount++;
return Task.Run(() => new HttpResponseMessage(HttpStatusCode.Forbidden));
};
putAsyncCallCount.ShouldBe(0);
showCredentialsErrorCallCount.ShouldBe(0);
await m_Provider.TestRequestTurnOnService();
putAsyncCallCount.ShouldBe(1, $"Expected {nameof(putAsyncCallCount)} to be 1");
showCredentialsErrorCallCount.ShouldBe(1, $"Expected {nameof(showCredentialsErrorCallCount)} to be 1");
});
}
[UnityTest]
public IEnumerator TestsWhenGenesisReturnsErrorShowsGenericError()
{
return m_Atc.Run(async () =>
{
var showGeneralErrorCallCount = 0;
var putAsyncCallCount = 0;
//ensure we return true for isProjectBound
m_Provider.isProjectBoundTestImpl = () => ProjectStatus.Bound;
m_Provider.showGeneralErrorTestImpl = () =>
{
showGeneralErrorCallCount++;
};
m_Provider.putAsyncTestImpl = () =>
{
putAsyncCallCount++;
return Task.Run(() => new HttpResponseMessage(HttpStatusCode.NotFound));
};
putAsyncCallCount.ShouldBe(0);
showGeneralErrorCallCount.ShouldBe(0);
await m_Provider.TestRequestTurnOnService();
putAsyncCallCount.ShouldBe(1, $"Expected {nameof(putAsyncCallCount)} to be 1");
showGeneralErrorCallCount.ShouldBe(1, $"Expected {nameof(showGeneralErrorCallCount)} to be 1");
});
}
[UnityTest]
public IEnumerator TestWhenGenesisReturnsOkCallsTurnOnCollabInternal()
{
return m_Atc.Run(async () =>
{
var putAsyncCallCount = 0;
var turnOnCollabInternalCallCount = 0;
// Ensure we return true for isProjectBound.
m_Provider.isProjectBoundTestImpl = () => ProjectStatus.Bound;
m_Provider.turnOnCollabInternalTestImpl = () => turnOnCollabInternalCallCount++;
m_Provider.putAsyncTestImpl = () =>
{
putAsyncCallCount++;
return Task.Run(() => new HttpResponseMessage(HttpStatusCode.OK));
};
putAsyncCallCount.ShouldBe(0);
turnOnCollabInternalCallCount.ShouldBe(0);
await m_Provider.TestRequestTurnOnService();
putAsyncCallCount.ShouldBe(1, $"Expected {nameof(putAsyncCallCount)} to be 1");
turnOnCollabInternalCallCount.ShouldBe(1, $"Expected {nameof(turnOnCollabInternalCallCount)} to be 1");
});
}
class TestCollab : Collab
{
public Func<ProjectStatus> isProjectBoundTestImpl;
public Action saveAssetsTestImpl;
public Action turnOnCollabInternalTestImpl;
public Func<Task<HttpResponseMessage>> putAsyncTestImpl;
public Action showCredentialsErrorTestImpl;
public Action showGeneralErrorTestImpl;
public TestCollab()
{
isProjectBoundTestImpl = () => ProjectStatus.Unbound;
saveAssetsTestImpl = () => { };
turnOnCollabInternalTestImpl = () => { };
showCredentialsErrorTestImpl = () => { };
showGeneralErrorTestImpl = () => { };
putAsyncTestImpl = () => Task.Run(() => new HttpResponseMessage());
}
public async Task TestRequestTurnOnService()
{
await RequestTurnOnServiceInternal();
}
protected override Task<HttpResponseMessage> PutAsync(HttpClient client, string fullUrl, StringContent content)
{
return putAsyncTestImpl?.Invoke();
}
protected override void TurnOnCollabInternal()
{
turnOnCollabInternalTestImpl?.Invoke();
}
protected override void SaveAssets()
{
saveAssetsTestImpl?.Invoke();
}
public override ProjectStatus GetProjectStatus()
{
return isProjectBoundTestImpl?.Invoke() ?? ProjectStatus.Unbound;
}
protected override void ShowCredentialsError()
{
showCredentialsErrorTestImpl?.Invoke();
}
protected override void ShowGeneralError()
{
showGeneralErrorTestImpl?.Invoke();
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 65dbc1a79b82e2b49884dcc702396733
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestChangesModel : IChangesModel
{
public int UpdateEntryToggleCount;
public string UpdateEntryTogglePath;
public bool? UpdateEntryToggleValue;
public int GetToggledEntriesCount;
public string GetToggledEntriesQuery;
public int GetUntoggledEntriesCount;
public string GetUntoggledEntriesQuery;
public int GetAllEntriesCount;
public string GetAllEntriesQuery;
public int GetConflictedEntriesCount;
public string GetConflictedEntriesQuery;
public int RequestInitialDataCount;
public int RequestDiscardCount;
public IChangeEntry RequestDiscardEntry;
public int RequestBulkDiscardCount;
public IReadOnlyList<IChangeEntry> RequestBulkDiscardPaths;
public int RequestDiffCount;
public string RequestDiffPath;
public int RequestPublishCount;
public IReadOnlyList<IChangeEntry> RequestPublishList;
public IReadOnlyList<IChangeEntryData> UntoggledEntries = new List<IChangeEntryData>();
public IReadOnlyList<IChangeEntryData> ToggledEntries = new List<IChangeEntryData>();
public IReadOnlyList<IChangeEntryData> AllEntries = new List<IChangeEntryData>();
public IReadOnlyList<IChangeEntryData> ConflictedEntries = new List<IChangeEntryData>();
public event Action UpdatedChangeList = delegate { };
public event Action<bool> BusyStatusUpdated = delegate { };
public event Action OnUpdatedSelectedChanges = delegate { };
public event Action StateChanged = delegate { };
public string SavedRevisionSummary { get; set; } = "";
public string SavedSearchQuery { get; set; } = "";
public int ToggledCount => ToggledEntries.Count;
public int TotalCount => AllEntries.Count;
public int ConflictedCount => ConflictedEntries.Count;
public bool Conflicted => ConflictedCount != 0;
public bool Busy { get; set; }
public void TriggerUpdatedChangeList()
{
UpdatedChangeList();
}
public void TriggerBusyStatusUpdated(bool value)
{
BusyStatusUpdated(value);
}
public bool UpdateEntryToggle(string path, bool toggled)
{
UpdateEntryToggleCount++;
UpdateEntryTogglePath = path;
UpdateEntryToggleValue = toggled;
return false;
}
public IReadOnlyList<IChangeEntryData> GetToggledEntries(string query = null)
{
GetToggledEntriesCount++;
GetToggledEntriesQuery = query;
return ToggledEntries;
}
public IReadOnlyList<IChangeEntryData> GetUntoggledEntries(string query = null)
{
GetUntoggledEntriesCount++;
GetUntoggledEntriesQuery = query;
return UntoggledEntries;
}
public IReadOnlyList<IChangeEntryData> GetAllEntries(string query = null)
{
GetAllEntriesCount++;
GetAllEntriesQuery = query;
return AllEntries;
}
public IReadOnlyList<IChangeEntryData> GetConflictedEntries(string query = null)
{
GetConflictedEntriesCount++;
GetConflictedEntriesQuery = query;
return ConflictedEntries;
}
public void RequestInitialData()
{
RequestInitialDataCount++;
}
public void RequestDiffChanges(string path)
{
RequestDiffCount++;
RequestDiffPath = path;
}
public void RequestDiscard(IChangeEntry entry)
{
RequestDiscardCount++;
RequestDiscardEntry = entry;
}
public void RequestBulkDiscard(IReadOnlyList<IChangeEntry> paths)
{
RequestBulkDiscardCount++;
RequestBulkDiscardPaths = paths;
}
public void RequestPublish(string message, IReadOnlyList<IChangeEntry> changes = null)
{
RequestPublishCount++;
RequestPublishList = changes;
}
public void RequestShowConflictedDifferences(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMerge(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMine(string[] paths)
{
throw new NotImplementedException();
}
public void RequestChooseRemote(string[] paths)
{
throw new NotImplementedException();
}
internal class ChangeEntryData : IChangeEntryData
{
public IChangeEntry Entry { get; set; }
public bool Toggled { get; set; }
public bool All { get; set; }
public bool ToggleReadOnly { get; set; }
public bool Conflicted { get; set; }
}
public void OnStart()
{
throw new NotImplementedException();
}
public void OnStop()
{
throw new NotImplementedException();
}
public void RestoreState(IWindowCache cache)
{
throw new NotImplementedException();
}
public void SaveState(IWindowCache cache)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b25b386ca61a6d4d97a654fd3e5b96d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestHistoryModel : IHistoryModel
{
public event Action HistoryListUpdated = delegate { };
public event Action<IReadOnlyList<IHistoryEntry>> HistoryListReceived = delegate { };
public event Action<IHistoryEntry> SelectedRevisionReceived = delegate { };
public event Action<bool> BusyStatusUpdated = delegate { };
public event Action<int?> EntryCountUpdated = delegate { };
public event Action StateChanged = delegate { };
public int RequestedPageOfRevisionsCount;
public int RequestedPageSize;
public int RequestedSingleRevisionCount;
[CanBeNull]
public string RequestedRevisionId;
public int RequestedEntryCountCount;
public int RequestedUpdateToCount;
[CanBeNull]
public string RequestedUpdateToRevisionId;
public int RequestedRestoreToCount;
[CanBeNull]
public string RequestedRestoreToRevisionId;
public int RequestedGoBackToCount;
[CanBeNull]
public string RequestedGoBackToRevisionId;
public int RequestedRevertCount;
[CanBeNull]
public string RequestedRevertRevisionId;
public int RequestedRevertFileCount;
public void SetNumberOfEntries(int count)
{
Assert.NotNull(EntryCountUpdated, "There should be an receiver for the entry number count event.");
EntryCountUpdated.Invoke(count);
}
public void TriggerUpdatedEntryListEvent()
{
Assert.NotNull(HistoryListUpdated, "There should be an receiver for the history list updated event.");
HistoryListUpdated();
}
public bool Busy { get; set; }
public int PageNumber { get; set; }
public string SelectedRevisionId { get; set; }
public string SavedRevisionId { get; set; }
public bool IsRevisionSelected => !string.IsNullOrEmpty(SelectedRevisionId);
public void RequestPageOfRevisions(int pageSize)
{
RequestedPageSize = pageSize;
RequestedPageOfRevisionsCount++;
}
public void RequestSingleRevision(string revisionId)
{
RequestedRevisionId = revisionId;
RequestedSingleRevisionCount++;
}
public void RequestEntryNumber()
{
RequestedEntryCountCount++;
}
public void RequestUpdateTo(string revisionId)
{
RequestedUpdateToCount++;
RequestedUpdateToRevisionId = revisionId;
}
public void RequestRestoreTo(string revisionId)
{
RequestedRestoreToCount++;
RequestedRestoreToRevisionId = revisionId;
}
public void RequestGoBackTo(string revisionId)
{
RequestedGoBackToCount++;
RequestedGoBackToRevisionId = revisionId;
}
public bool SupportsRevert { get; } = false;
public void RequestRevert(string revisionId, IReadOnlyList<string> files)
{
RequestedRevertCount++;
RequestedRevertRevisionId = revisionId;
RequestedRevertFileCount = files.Count;
}
public void OnStart()
{
throw new NotImplementedException();
}
public void OnStop()
{
throw new NotImplementedException();
}
public void RestoreState(IWindowCache cache)
{
throw new NotImplementedException();
}
public void SaveState(IWindowCache cache)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f56a99fa7c9121f46a7915e03de4d0a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,138 @@
using System;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestMainModel : IMainModel
{
public int clearErrorCount;
public int requestSyncCount;
public int requestCancelJobCount;
public IHistoryModel historyModel = new TestHistoryModel();
public IChangesModel changesModel = new TestChangesModel();
public (string id, string text, Action backAction)? backNavigation;
public event Action<bool> ConflictStatusChange = delegate { };
public void TriggerConflictStatusChange(bool conflict)
{
ConflictStatusChange(conflict);
}
public event Action<bool> OperationStatusChange = delegate { };
public void TriggerOperationStatusChange(bool inProgress)
{
OperationStatusChange(inProgress);
}
public event Action<IProgressInfo> OperationProgressChange = delegate { };
public void TriggerOperationProgressChange(IProgressInfo progressInfo)
{
OperationProgressChange(progressInfo);
}
public event Action<IErrorInfo> ErrorOccurred = delegate { };
public void TriggerErrorOccurred(IErrorInfo errorInfo)
{
ErrorOccurred(errorInfo);
}
public event Action ErrorCleared = delegate { };
public void TriggerErrorCleared()
{
ErrorCleared();
}
public event Action<bool> RemoteRevisionsAvailabilityChange = delegate { };
public void TriggerRemoteRevisionsAvailabilityChange(bool available)
{
RemoteRevisionsAvailabilityChange(available);
}
public event Action<string> BackButtonStateUpdated = delegate { };
public void TriggerBackButtonStateUpdated(string backText)
{
BackButtonStateUpdated(backText);
}
public event Action StateChanged = delegate { };
public void TriggerStateChanged()
{
StateChanged();
}
public bool RemoteRevisionsAvailable { get; set; }
public bool Conflicted { get; set; }
public IProgressInfo ProgressInfo { get; set; }
public IErrorInfo ErrorInfo { get; set; }
public int CurrentTabIndex { get; set; }
public IHistoryModel ConstructHistoryModel()
{
return historyModel;
}
public IChangesModel ConstructChangesModel()
{
return changesModel;
}
public void ClearError()
{
clearErrorCount++;
}
public void RequestSync()
{
requestSyncCount++;
}
public void RequestCancelJob()
{
requestCancelJobCount++;
}
public (string id, string text, Action backAction)? GetBackNavigation()
{
return backNavigation;
}
public void RegisterBackNavigation(string id, string text, Action backAction)
{
Assert.IsNull(backNavigation);
backNavigation = (id, text, backAction);
}
public bool UnregisterBackNavigation(string id)
{
if (backNavigation == null || backNavigation.Value.id != id)
return false;
backNavigation = null;
return true;
}
public void OnStart()
{
throw new NotImplementedException();
}
public void OnStop()
{
throw new NotImplementedException();
}
public void RestoreState(IWindowCache cache)
{
throw new NotImplementedException();
}
public void SaveState(IWindowCache cache)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e47743db60d9e3e48b0a6fa8c0b95640
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,248 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Api;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.Models.Structures;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestSourceControlProvider : ISourceControlProvider
{
public int RequestedHistoryRevisionCount;
[CanBeNull]
public string RequestedHistoryRevisionId;
public int RequestedHistoryListCount;
public int? RequestedHistoryListOffset;
public int? RequestedHistoryListSize;
public int RequestedHistoryCountCount;
public int RequestedUpdateToCount;
[CanBeNull]
public string RequestedUpdateToRevisionId;
public int RequestedRestoreToCount;
[CanBeNull]
public string RequestedRestoreToRevisionId;
public int RequestedGoBackToCount;
[CanBeNull]
public string RequestedGoBackToRevisionId;
public int RequestedRevertCount;
[CanBeNull]
public string RequestedRevertRevisionId;
public int? RequestedRevertFileCount;
public int RequestedChangeListCount;
[CanBeNull]
public Action<IReadOnlyList<IChangeEntry>> RequestedChangeListCallback;
public int RequestedDiscardCount;
[CanBeNull]
public IChangeEntry RequestedDiscardEntry;
public int RequestedBulkDiscardCount;
[CanBeNull]
public IReadOnlyList<IChangeEntry> RequestedBulkDiscardPaths;
public int RequestedDiffChangesCount;
[CanBeNull]
public string RequestedDiffChangesPath;
public int RequestedPublishCount;
[CanBeNull]
public string RequestedPublishMessage;
[CanBeNull]
public IReadOnlyList<IChangeEntry> RequestedPublishList;
public bool RemoteRevisionAvailability = false;
public bool ConflictedState = false;
public event Action UpdatedChangeList = delegate { };
public event Action UpdatedHistoryEntries = delegate { };
public event Action<bool> UpdatedConflictState = delegate { };
public event Action<bool> UpdatedRemoteRevisionsAvailability = delegate { };
public event Action<ProjectStatus> UpdatedProjectStatus = delegate { };
public event Action<bool> UpdatedOperationStatus = delegate { };
public event Action<IProgressInfo> UpdatedOperationProgress = delegate { };
public event Action<IErrorInfo> ErrorOccurred = delegate { };
public event Action ErrorCleared = delegate { };
public event Action<IReadOnlyList<string>> UpdatedSelectedChangeList = delegate { };
public bool GetRemoteRevisionAvailability()
{
return RemoteRevisionAvailability;
}
public bool GetConflictedState()
{
return ConflictedState;
}
public IProgressInfo GetProgressState()
{
throw new NotImplementedException();
}
public IErrorInfo GetErrorState()
{
throw new NotImplementedException();
}
public ProjectStatus GetProjectStatus()
{
throw new NotImplementedException();
}
public void RequestChangeList(Action<IReadOnlyList<IChangeEntry>> callback)
{
RequestedChangeListCount++;
RequestedChangeListCallback = callback;
}
public void RequestPublish(string message, IReadOnlyList<IChangeEntry> changes = null)
{
RequestedPublishCount++;
RequestedPublishMessage = message;
RequestedPublishList = changes;
}
public void TriggerUpdatedHistoryEntries()
{
Assert.NotNull(UpdatedHistoryEntries, "There should be a listener registered.");
UpdatedHistoryEntries();
}
public void TriggerUpdatedChangeEntries()
{
Assert.NotNull(UpdatedHistoryEntries, "There should be a listener registered.");
UpdatedChangeList();
}
public void RequestHistoryEntry(string revisionId, Action<IHistoryEntry> callback)
{
RequestedHistoryRevisionCount++;
RequestedHistoryRevisionId = revisionId;
callback(null);
}
public void RequestHistoryPage(int offset, int pageSize, Action<IReadOnlyList<IHistoryEntry>> callback)
{
RequestedHistoryListCount++;
RequestedHistoryListOffset = offset;
RequestedHistoryListSize = pageSize;
callback(null);
}
public void RequestHistoryCount(Action<int?> callback)
{
RequestedHistoryCountCount++;
callback(null);
}
public void RequestDiscard(IChangeEntry entry)
{
RequestedDiscardCount++;
RequestedDiscardEntry = entry;
}
public void RequestBulkDiscard(IReadOnlyList<IChangeEntry> entries)
{
RequestedBulkDiscardCount++;
RequestedBulkDiscardPaths = entries;
}
public void RequestDiffChanges(string path)
{
RequestedDiffChangesCount++;
RequestedDiffChangesPath = path;
}
public bool SupportsRevert { get; } = false;
public void RequestRevert(string revisionId, IReadOnlyList<string> files)
{
RequestedRevertCount++;
RequestedRevertRevisionId = revisionId;
RequestedRevertFileCount = files.Count;
}
public void RequestUpdateTo(string revisionId)
{
RequestedUpdateToCount++;
RequestedUpdateToRevisionId = revisionId;
}
public void RequestRestoreTo(string revisionId)
{
RequestedRestoreToCount++;
RequestedRestoreToRevisionId = revisionId;
}
public void RequestGoBackTo(string revisionId)
{
RequestedGoBackToCount++;
RequestedGoBackToRevisionId = revisionId;
}
public void ClearError()
{
}
public void RequestShowConflictedDifferences(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMerge(string path)
{
throw new NotImplementedException();
}
public void RequestChooseMine(string[] paths)
{
throw new NotImplementedException();
}
public void RequestChooseRemote(string[] paths)
{
throw new NotImplementedException();
}
public void RequestSync()
{
throw new NotImplementedException();
}
public void RequestCancelJob()
{
throw new NotImplementedException();
}
public void RequestTurnOnService()
{
throw new NotImplementedException();
}
public void ShowServicePage()
{
throw new NotImplementedException();
}
public void ShowLoginPage()
{
throw new NotImplementedException();
}
public void ShowNoSeatPage()
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fb18ae523e202db40a866e7813fa2c0c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,69 @@
using System;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestStartModel : IStartModel
{
public int requestTurnOnServiceCount;
public int showServicePageCount;
public int showLoginPageCount;
public int showNoSeatPageCount;
public event Action StateChanged = delegate { };
public void TriggerStateChanged()
{
StateChanged();
}
public event Action<ProjectStatus> ProjectStatusChanged = delegate { };
public void TriggerProjectStatusChanged(ProjectStatus status)
{
ProjectStatusChanged(status);
}
public ProjectStatus ProjectStatus { get; set; }
public void OnStart()
{
throw new NotImplementedException();
}
public void OnStop()
{
throw new NotImplementedException();
}
public void RestoreState(IWindowCache cache)
{
throw new NotImplementedException();
}
public void SaveState(IWindowCache cache)
{
throw new NotImplementedException();
}
public void RequestTurnOnService()
{
requestTurnOnServiceCount++;
}
public void ShowServicePage()
{
showServicePageCount++;
}
public void ShowLoginPage()
{
showLoginPageCount++;
}
public void ShowNoSeatPage()
{
showNoSeatPageCount++;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 49d15206774f47cab3c22a97f27bf8ec
timeCreated: 1576186334

View file

@ -0,0 +1,24 @@
using Unity.Cloud.Collaborate.UserInterface;
namespace Unity.Cloud.Collaborate.Tests.Models
{
internal class TestWindowCache : IWindowCache
{
public void Clear()
{
SimpleSelectedItems = default;
RevisionSummary = default;
ChangesSearchValue = default;
SelectedHistoryRevision = default;
HistoryPageNumber = default;
TabIndex = default;
}
public SelectedItemsDictionary SimpleSelectedItems { get; set; }
public string RevisionSummary { get; set; }
public string ChangesSearchValue { get; set; }
public string SelectedHistoryRevision { get; set; }
public int HistoryPageNumber { get; set; }
public int TabIndex { get; set; }
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: acd046f16a9a499699c470bf320ab6be
timeCreated: 1574115275

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 38fe47e80ef3d524d8c3508224f6cffe
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,341 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Tests.Models;
using Unity.Cloud.Collaborate.Views;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
public class ChangesPresenterTests
{
class TestableChangesPresenter : ChangesPresenter
{
public TestableChangesPresenter([NotNull] IChangesView view, [NotNull] IChangesModel model, [NotNull] IMainModel mainModel)
: base(view, model, mainModel)
{
}
public void NotifyOnRemoteRevisionsAvailabilityChange(bool available)
{
base.OnRemoteRevisionsAvailabilityChange(available);
}
public void NotifyOnUpdatedChangeList()
{
base.OnUpdatedChangeList();
}
public void NotifyOnUpdatedPartiallySelectedChanges()
{
base.OnUpdatedPartiallySelectedChanges();
}
public void NotifyOnConflictStatusChange(bool conflicted)
{
base.OnConflictStatusChange(conflicted);
}
}
TestChangesView m_View;
TestChangesModel m_Model;
TestMainModel m_MainModel;
TestableChangesPresenter m_Presenter;
[SetUp]
public void Setup()
{
m_View = new TestChangesView();
m_Model = new TestChangesModel();
m_MainModel = new TestMainModel();
m_Presenter = new TestableChangesPresenter(m_View, m_Model, m_MainModel);
}
[TearDown]
public void TearDown()
{
m_Presenter.Stop();
m_View = null;
m_Model = null;
m_MainModel = null;
m_Presenter = null;
}
[Test]
public void TestToggledCountValue()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path2") }
};
Assert.AreEqual(2, m_Presenter.ToggledCount);
}
[Test]
public void TestTotalCountValue()
{
m_Presenter.Start();
m_Model.AllEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = false, Entry = new ChangeEntry("path2") }
};
Assert.AreEqual(2, m_Presenter.TotalCount);
}
[Test]
public void TestConflictedCountValue()
{
m_Presenter.Start();
m_Model.ConflictedEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData
{
Conflicted = true,
Entry = new ChangeEntry("path", null, ChangeEntryStatus.Unmerged, false, true)
},
new TestChangesModel.ChangeEntryData
{
Conflicted = true,
Entry = new ChangeEntry("path2", null, ChangeEntryStatus.Unmerged, false, true)
}
};
Assert.AreEqual(2, m_Presenter.ConflictedCount);
}
[Test]
public void TestSearchingValue()
{
m_Presenter.Start();
m_Model.SavedSearchQuery = "test";
Assert.IsTrue(m_Presenter.Searching);
m_Model.SavedSearchQuery = "";
Assert.IsFalse(m_Presenter.Searching);
}
[Test]
public void TestSettingEntryToggle()
{
m_Presenter.Start();
const string path = "path";
const bool value = true;
m_Presenter.UpdateEntryToggle(path, value);
Assert.AreEqual(1, m_Model.UpdateEntryToggleCount);
Assert.AreEqual(path, m_Model.UpdateEntryTogglePath);
Assert.AreEqual(value, m_Model.UpdateEntryToggleValue);
}
[Test]
public void TestRequestPublish()
{
m_Presenter.Start();
m_Model.SavedSearchQuery = "";
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") }
};
m_Presenter.RequestPublish();
Assert.AreEqual(1, m_Model.GetToggledEntriesCount);
Assert.AreEqual(1, m_Model.RequestPublishCount);
Assert.AreEqual(1, m_Model.RequestPublishList.Count);
}
[Test]
public void TestRequestPublishFailWhenSearching()
{
m_Presenter.Start();
m_Model.SavedSearchQuery = "some query";
Assert.Catch(() => m_Presenter.RequestPublish());
}
[Test]
public void TestRequestDiscard()
{
m_Presenter.Start();
const string path = "path";
var entry = new ChangeEntry(path);
m_Presenter.RequestDiscard(entry);
Assert.AreEqual(1, m_Model.RequestDiscardCount);
Assert.AreEqual(path, m_Model.RequestDiscardEntry.Path);
// Ensure it created a dialogue
Assert.AreEqual(1, m_View.DisplayDialogueCount);
}
[Test]
public void TestRequestDiffChanges()
{
m_Presenter.Start();
const string path = "path";
m_Presenter.RequestDiffChanges(path);
Assert.AreEqual(1, m_Model.RequestDiffCount);
Assert.AreEqual(path, m_Model.RequestDiffPath);
}
[Test]
public void TestSetSearchQuery()
{
m_Presenter.Start();
Assert.AreEqual(1, m_View.SetSearchQueryCount);
const string query = "path Path ";
m_Presenter.SetSearchQuery(query);
Assert.AreEqual(query.Trim().ToLower(), m_Model.SavedSearchQuery);
Assert.AreEqual(2, m_View.SetSearchQueryCount);
Assert.AreEqual(query, m_View.SetSearchQueryValue);
}
[Test]
public void TestHavingSearchQueryDisablesPublish()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") }
};
// Base case
m_Presenter.SetSearchQuery("");
Assert.AreEqual(1, m_View.SetPublishEnabledCount);
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
// Base to disabled case
m_Presenter.SetSearchQuery("query");
Assert.AreEqual(2, m_View.SetPublishEnabledCount);
Assert.AreEqual(false, m_View.SetPublishEnabledValue);
Assert.IsNotNull(m_View.SetPublishEnabledReason);
// Disabled back to base case.
m_Presenter.SetSearchQuery("");
Assert.AreEqual(3, m_View.SetPublishEnabledCount);
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
}
[Test]
public void TestHavingConflictsDisablesPublish()
{
m_Model.ToggledEntries = new List<IChangeEntryData>()
{
new TestChangesModel.ChangeEntryData
{
Entry = new ChangeEntry("path", null, ChangeEntryStatus.Modified)
}
};
// Base case
m_Presenter.Start();
m_Model.ConflictedEntries = new List<IChangeEntryData>();
m_Model.TriggerUpdatedChangeList();
Assert.AreEqual(1, m_View.SetPublishEnabledCount);
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
// Disable
m_Model.ConflictedEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData
{
Conflicted = true,
Entry = new ChangeEntry("path", null, ChangeEntryStatus.Unmerged, false, true)
}
};
m_Model.TriggerUpdatedChangeList();
Assert.AreEqual(2, m_View.SetPublishEnabledCount);
Assert.AreEqual(false, m_View.SetPublishEnabledValue);
Assert.IsNotNull(m_View.SetPublishEnabledReason);
// Re enabled
m_Model.ConflictedEntries = new List<IChangeEntryData>();
m_Model.TriggerUpdatedChangeList();
Assert.AreEqual(3, m_View.SetPublishEnabledCount);
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
}
[Test]
public void TestSetRevisionService()
{
m_Presenter.Start();
Assert.AreEqual(1, m_View.SetRevisionSummaryCount);
const string summary = "summary";
m_Presenter.SetRevisionSummary(summary);
Assert.AreEqual(summary, m_Model.SavedRevisionSummary);
Assert.AreEqual(2, m_View.SetRevisionSummaryCount);
Assert.AreEqual(summary, m_View.SetRevisionSummaryValue);
}
[Test]
public void TestReceivingBusyMessage()
{
m_Presenter.Start();
// Sent initial status on start
Assert.AreEqual(1, m_View.SetBusyStatusCount);
Assert.AreEqual(false, m_View.SetBusyStatusValue);
// Test values once events called:
m_Model.TriggerBusyStatusUpdated(true);
Assert.AreEqual(2, m_View.SetBusyStatusCount);
Assert.AreEqual(true, m_View.SetBusyStatusValue);
m_Model.TriggerBusyStatusUpdated(false);
Assert.AreEqual(3, m_View.SetBusyStatusCount);
Assert.AreEqual(false, m_View.SetBusyStatusValue);
}
[Test]
public void TestOnUpdatedChangeListUpdatesPublishButton()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = false, Entry = new ChangeEntry("path2") }
};
m_Presenter.NotifyOnUpdatedChangeList();
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
}
[Test]
public void TestOnPartialChangesUpdatesPublishButton()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = false, Entry = new ChangeEntry("path2") }
};
m_Presenter.NotifyOnUpdatedPartiallySelectedChanges();
Assert.AreEqual(true, m_View.SetPublishEnabledValue);
}
[Test]
public void TestOnRemoteRevisionsAvailabilityChangeUpdatesPublishButton()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = false, Entry = new ChangeEntry("path2") }
};
m_MainModel.RemoteRevisionsAvailable = true;
m_Presenter.NotifyOnRemoteRevisionsAvailabilityChange(true);
Assert.AreEqual(false, m_View.SetPublishEnabledValue);
}
[Test]
public void TestOnConflictStatusChangeUpdatesPublishButton()
{
m_Presenter.Start();
m_Model.ToggledEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData { Toggled = true, Entry = new ChangeEntry("path") },
new TestChangesModel.ChangeEntryData { Toggled = false, Entry = new ChangeEntry("path2") }
};
m_Model.ConflictedEntries = new List<IChangeEntryData>
{
new TestChangesModel.ChangeEntryData
{
Conflicted = true,
Entry = new ChangeEntry("path", null, ChangeEntryStatus.Unmerged, false, true)
}
};
m_Presenter.NotifyOnConflictStatusChange(true);
Assert.AreEqual(false, m_View.SetPublishEnabledValue);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27c4708da6102f346a800846ab2a1e47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Tests.Models;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
public class HistoryPresenterTests
{
TestHistoryView m_View;
TestHistoryModel m_HistoryModel;
TestMainModel m_MainModel;
HistoryPresenter m_Presenter;
[SetUp]
public void Setup()
{
m_View = new TestHistoryView();
m_HistoryModel = new TestHistoryModel();
m_MainModel = new TestMainModel();
m_Presenter = new HistoryPresenter(m_View, m_HistoryModel, m_MainModel);
}
[TearDown]
public void TearDown()
{
m_Presenter.Stop();
m_View = null;
m_HistoryModel = null;
m_Presenter = null;
}
[Test]
public void TestStartCall()
{
m_Presenter.Start();
// Clear box testing here
Assert.AreEqual(m_HistoryModel.Busy, m_View.BusyStatus);
Assert.AreEqual(1, m_HistoryModel.RequestedEntryCountCount);
Assert.AreEqual(1, m_HistoryModel.RequestedPageOfRevisionsCount);
Assert.AreEqual(0, m_HistoryModel.RequestedSingleRevisionCount);
}
[Test]
public void TestStartWithSavedRevisionCall()
{
const string savedRevisionId = "123";
m_HistoryModel.SavedRevisionId = savedRevisionId;
m_Presenter.Start();
// Clear box testing here
Assert.AreEqual(m_HistoryModel.Busy, m_View.BusyStatus);
Assert.AreEqual(1, m_HistoryModel.RequestedEntryCountCount);
Assert.AreEqual(0, m_HistoryModel.RequestedPageOfRevisionsCount);
Assert.AreEqual(1, m_HistoryModel.RequestedSingleRevisionCount);
Assert.AreEqual(savedRevisionId, m_HistoryModel.RequestedRevisionId);
}
[Test]
public void TestReceivingUpdateEvent()
{
m_Presenter.Start();
// Clear box testing here
m_HistoryModel.TriggerUpdatedEntryListEvent();
Assert.AreEqual(2, m_HistoryModel.RequestedEntryCountCount);
Assert.AreEqual(2, m_HistoryModel.RequestedPageOfRevisionsCount);
Assert.AreEqual(0, m_HistoryModel.RequestedSingleRevisionCount);
}
[Test]
public void TestReceivingUpdateEventWithSelection()
{
const string selectedRevisionId = "123";
m_HistoryModel.SelectedRevisionId = selectedRevisionId;
m_Presenter.Start();
// Clear box testing here
m_HistoryModel.TriggerUpdatedEntryListEvent();
Assert.AreEqual(2, m_HistoryModel.RequestedEntryCountCount);
Assert.AreEqual(2, m_HistoryModel.RequestedSingleRevisionCount);
}
[Test]
public void TestReceivingEntryCount()
{
m_Presenter.Start();
m_HistoryModel.PageNumber = 1;
m_HistoryModel.SetNumberOfEntries(HistoryPresenter.pageSize * 2 + 1);
Assert.AreEqual(2, m_View.MaxPage);
Assert.AreEqual(1, m_View.Page);
}
[Test]
public void TestPreviousPageCall()
{
m_Presenter.Start();
m_HistoryModel.PageNumber = 1;
m_Presenter.PrevPage();
Assert.AreEqual(HistoryPresenter.pageSize, m_HistoryModel.RequestedPageSize, "Page size should match given value");
Assert.AreEqual(0, m_HistoryModel.PageNumber, "Requesting previous page should request previous page.");
}
[Test]
public void TestPreviousPageCallOnZero()
{
m_Presenter.Start();
m_HistoryModel.PageNumber = 0;
m_Presenter.PrevPage();
Assert.AreEqual(HistoryPresenter.pageSize, m_HistoryModel.RequestedPageSize, "Page size should match given value");
Assert.AreEqual(0, m_HistoryModel.PageNumber, "Requesting previous page on page zero shouldn't stay at zero.");
}
[Test]
public void TestNextPageCall()
{
m_Presenter.Start();
m_HistoryModel.PageNumber = 0;
m_HistoryModel.SetNumberOfEntries(HistoryPresenter.pageSize * 2);
m_Presenter.NextPage();
Assert.AreEqual(HistoryPresenter.pageSize, m_HistoryModel.RequestedPageSize, "Page size should match given value");
Assert.AreEqual(1, m_HistoryModel.PageNumber, "Requesting previous page should request next page.");
}
[Test]
public void TestNextPageCallOnZero()
{
m_Presenter.Start();
m_HistoryModel.PageNumber = 1;
m_HistoryModel.SetNumberOfEntries(HistoryPresenter.pageSize * 2);
m_Presenter.NextPage();
Assert.AreEqual(HistoryPresenter.pageSize, m_HistoryModel.RequestedPageSize, "Page size should match given value");
Assert.AreEqual(1, m_HistoryModel.PageNumber, "Requesting next page on max page should not change the page.");
}
[Test]
public void TestSetSelectedRevisionId()
{
const string selectedRevisionId = "123";
m_Presenter.Start();
m_Presenter.SelectedRevisionId = selectedRevisionId;
Assert.AreEqual(selectedRevisionId, m_HistoryModel.RequestedRevisionId);
}
[Test]
public void TestGotoCall()
{
const string revisionId = "123";
m_Presenter.Start();
var status = HistoryEntryStatus.Ahead;
m_Presenter.RequestGoto(revisionId, status);
Assert.AreEqual(1, m_HistoryModel.RequestedUpdateToCount);
Assert.AreEqual(revisionId, m_HistoryModel.RequestedUpdateToRevisionId);
status = HistoryEntryStatus.Current;
m_Presenter.RequestGoto(revisionId, status);
Assert.AreEqual(1, m_HistoryModel.RequestedRestoreToCount);
Assert.AreEqual(revisionId, m_HistoryModel.RequestedRestoreToRevisionId);
status = HistoryEntryStatus.Behind;
m_Presenter.RequestGoto(revisionId, status);
Assert.AreEqual(1, m_HistoryModel.RequestedGoBackToCount);
Assert.AreEqual(revisionId, m_HistoryModel.RequestedGoBackToRevisionId);
}
[Test]
public void TestRevertCall()
{
const string revisionId = "123";
m_Presenter.Start();
m_Presenter.RequestRevert(revisionId, new List<string> { "a", "b", "c" });
Assert.AreEqual(1, m_HistoryModel.RequestedRevertCount);
Assert.AreEqual(revisionId, m_HistoryModel.RequestedRevertRevisionId);
Assert.AreEqual(3, m_HistoryModel.RequestedRevertFileCount);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f5d8073410f83d479361cd2b45bcf60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,128 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Tests.Models;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
public class MainPresenterTests
{
TestMainView m_View;
TestMainModel m_MainModel;
MainPresenter m_Presenter;
[SetUp]
public void Setup()
{
m_View = new TestMainView();
m_MainModel = new TestMainModel();
m_Presenter = new MainPresenter(m_View, m_MainModel);
}
[TearDown]
public void TearDown()
{
m_Presenter.Stop();
m_View = null;
m_MainModel = null;
m_Presenter = null;
}
[Test]
public void TestBackNavigation()
{
m_Presenter.Start();
var called = false;
m_MainModel.backNavigation = ("test", "test-text", () => called = true);
m_Presenter.NavigateBack();
Assert.IsTrue(called);
Assert.IsNull(m_MainModel.backNavigation);
}
[Test]
public void TestBackNavigationWithNull()
{
m_Presenter.Start();
m_MainModel.backNavigation = null;
m_Presenter.NavigateBack();
Assert.IsNull(m_MainModel.backNavigation);
}
[Test]
public void TestAssigningPresenters()
{
m_Presenter.Start();
var changesView = new TestChangesView();
m_Presenter.AssignChangesPresenter(changesView);
Assert.IsNotNull(changesView.Presenter);
var historyView = new TestHistoryView();
m_Presenter.AssignHistoryPresenter(historyView);
Assert.IsNotNull(historyView.Presenter);
}
[Test]
public void TestCancellingJob()
{
m_Presenter.Start();
m_Presenter.RequestCancelJob();
Assert.AreEqual(1, m_MainModel.requestCancelJobCount);
}
[Test]
public void TestSettingTabIndex()
{
m_Presenter.Start();
const int newVal = 5;
m_Presenter.UpdateTabIndex(newVal);
Assert.AreEqual(newVal, m_MainModel.CurrentTabIndex);
}
[Test]
public void TestStartingWithJobInProgress()
{
m_MainModel.ProgressInfo = new ProgressInfo("test", "test", 50, 20);
m_Presenter.Start();
Assert.IsTrue(m_View.inProgress);
Assert.IsNotNull(m_View.progress);
}
[Test]
public void TestStartingWithError()
{
const string message = "test message";
m_MainModel.ErrorInfo = new ErrorInfo(20, 1, (int)ErrorInfoBehavior.Alert, message, "test", "20");
m_Presenter.Start();
Assert.AreEqual(1, m_View.alerts.Count);
Assert.AreEqual(message, m_View.alerts.First().Value.message);
}
[Test]
public void TestReceivingStateChange()
{
const string message = "test message";
const int tabIndex = 67;
m_Presenter.Start();
m_MainModel.backNavigation = ("id", message, () => { });
m_MainModel.CurrentTabIndex = tabIndex;
m_MainModel.TriggerStateChanged();
Assert.AreEqual(message, m_View.backNavigation);
Assert.AreEqual(tabIndex, m_View.tabIndex);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c27224849b8648b991691de4f0c90456
timeCreated: 1576178835

View file

@ -0,0 +1,94 @@
using NUnit.Framework;
using Unity.Cloud.Collaborate.Models.Enums;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Tests.Models;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
internal class StartPresenterTests
{
TestStartView m_View;
TestStartModel m_Model;
StartPresenter m_Presenter;
[SetUp]
public void Setup()
{
m_View = new TestStartView();
m_Model = new TestStartModel();;
m_Presenter = new StartPresenter(m_View, m_Model);
}
[TearDown]
public void TearDown()
{
m_Presenter.Stop();
m_View = null;
m_Model = null;
m_Presenter = null;
}
[Test]
public void TestRequestingStart()
{
m_Presenter.Start();
m_Model.ProjectStatus = ProjectStatus.Bound;
m_Presenter.RequestStart();
Assert.AreEqual(1, m_Model.requestTurnOnServiceCount);
m_Model.ProjectStatus = ProjectStatus.Unbound;
m_Presenter.RequestStart();
Assert.AreEqual(1, m_Model.showServicePageCount);
m_Model.ProjectStatus = ProjectStatus.LoggedOut;
m_Presenter.RequestStart();
Assert.AreEqual(1, m_Model.showLoginPageCount);
m_Model.ProjectStatus = ProjectStatus.NoSeat;
m_Presenter.RequestStart();
Assert.AreEqual(1, m_Model.showNoSeatPageCount);
}
[Test]
public void TestUpdatingProjectStatus()
{
m_Presenter.Start();
m_Model.TriggerProjectStatusChanged(ProjectStatus.Bound);
Assert.IsTrue(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.Unbound);
Assert.IsTrue(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.LoggedOut);
Assert.IsTrue(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.NoSeat);
Assert.IsTrue(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.Loading);
Assert.IsFalse(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.Offline);
Assert.IsFalse(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.Maintenance);
Assert.IsFalse(m_View.buttonVisible);
m_Model.TriggerProjectStatusChanged(ProjectStatus.Ready);
Assert.IsFalse(m_View.buttonVisible);
}
[Test]
public void TestStateChange()
{
m_Presenter.Start();
m_Model.ProjectStatus = ProjectStatus.Bound;
m_Model.TriggerStateChanged();
Assert.IsTrue(m_View.buttonVisible);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 485ab142ed644e479a8eb9a8137b8461
timeCreated: 1576186961

View file

@ -0,0 +1,94 @@
using System.Collections.Generic;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Views;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
internal class TestChangesView : IChangesView
{
public int SetBusyStatusCount;
public bool? SetBusyStatusValue;
public int SetSearchQueryCount;
public string SetSearchQueryValue;
public int SetRevisionSummaryCount;
public string SetRevisionSummaryValue;
public int SetConflictsCount;
public IReadOnlyList<IChangeEntryData> SetConflictsValue;
public int SetChangesCount;
public IReadOnlyList<IChangeEntryData> SetChangesValue;
public int SetToggledCountCount;
public int? SetToggledCountValue;
public int SetPublishEnabledCount;
public bool? SetPublishEnabledValue;
public string SetPublishEnabledReason;
public int DisplayDialogueCount;
public IChangesPresenter Presenter { get; set; }
public void SetBusyStatus(bool busy)
{
SetBusyStatusCount++;
SetBusyStatusValue = busy;
}
public void SetSearchQuery(string query)
{
SetSearchQueryCount++;
SetSearchQueryValue = query;
}
public void SetRevisionSummary(string message)
{
SetRevisionSummaryCount++;
SetRevisionSummaryValue = message;
}
public void SetConflicts(IReadOnlyList<IChangeEntryData> list)
{
SetConflictsCount++;
SetConflictsValue = list;
}
public void SetChanges(IReadOnlyList<IChangeEntryData> list)
{
SetChangesCount++;
SetChangesValue = list;
}
public void SetToggledCount(int count)
{
SetToggledCountCount++;
SetToggledCountValue = count;
}
public void SetPublishEnabled(bool enabled, string reason = null)
{
SetPublishEnabledCount++;
SetPublishEnabledValue = enabled;
SetPublishEnabledReason = reason;
}
public bool DisplayDialogue(string title, string message, string affirmative)
{
DisplayDialogueCount++;
return true;
}
public bool DisplayDialogue(string title, string message, string affirmative, string negative)
{
DisplayDialogueCount++;
return true;
}
public void SetSelectedChanges()
{
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85a8810f7371b644186b2bbc0fb8bc17
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,72 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Models.Structures;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Views;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
internal class TestHistoryView : IHistoryView
{
public IHistoryPresenter Presenter { get; set; }
public bool DialogueReturnValue = true;
public bool? BusyStatus;
public int? Page;
public int? MaxPage;
[CanBeNull]
public IHistoryEntry ReceivedEntry;
[CanBeNull]
public string DialogueTitle;
[CanBeNull]
public string DialogueMessage;
[CanBeNull]
public string DialogueAffirmative;
[CanBeNull]
public string DialogueNegative;
[CanBeNull]
public IReadOnlyList<IHistoryEntry> ReceivedList;
public void SetBusyStatus(bool busy)
{
BusyStatus = busy;
}
public void SetHistoryList(IReadOnlyList<IHistoryEntry> list)
{
ReceivedList = list;
ReceivedEntry = null;
}
public void SetPage(int page, int max)
{
Page = page;
MaxPage = max;
}
public void SetSelection(IHistoryEntry entry)
{
ReceivedEntry = entry;
ReceivedList = null;
}
public bool DisplayDialogue(string title, string message, string affirmative)
{
DialogueTitle = title;
DialogueMessage = message;
DialogueAffirmative = affirmative;
DialogueNegative = null;
return DialogueReturnValue;
}
public bool DisplayDialogue(string title, string message, string affirmative, string negative)
{
DialogueTitle = title;
DialogueMessage = message;
DialogueAffirmative = affirmative;
DialogueNegative = negative;
return DialogueReturnValue;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d82f3cb1859dfe4fb3e5d83610c264c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using NUnit.Framework;
using Unity.Cloud.Collaborate.Components;
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Views;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
internal class TestMainView : IMainView
{
public int? tabIndex;
public bool inProgress;
public (string title, string details, int percentage, int completed, int total, bool isPercentage, bool canCancel)? progress;
[CanBeNull]
public string backNavigation;
public IMainPresenter Presenter { get; set; }
public Dictionary<string, (string id, AlertBox.AlertLevel level, string message, (string text, Action action)? button)> alerts = new Dictionary<string, (string id, AlertBox.AlertLevel level, string message, (string text, Action action)? button)>();
public void AddAlert(string id, AlertBox.AlertLevel level, string message, (string text, Action action)? button = null)
{
alerts[id] = (id, level, message, button);
}
public void RemoveAlert(string id)
{
alerts.Remove(id);
}
public void SetTab(int index)
{
tabIndex = index;
}
public void AddOperationProgress()
{
Assert.IsFalse(inProgress);
inProgress = true;
}
public void RemoveOperationProgress()
{
Assert.IsTrue(inProgress);
inProgress = false;
}
public void SetOperationProgress(string title, string details, int percentage, int completed, int total, bool isPercentage, bool canCancel)
{
progress = (title, details, percentage, completed, total, isPercentage, canCancel);
}
public void ClearBackNavigation()
{
backNavigation = null;
}
public void DisplayBackNavigation(string text)
{
backNavigation = text;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 63ffed391ffc4e11949711d888affd00
timeCreated: 1576178951

View file

@ -0,0 +1,21 @@
using Unity.Cloud.Collaborate.Presenters;
using Unity.Cloud.Collaborate.Views;
namespace Unity.Cloud.Collaborate.Tests.Presenters
{
internal class TestStartView : IStartView
{
public bool buttonVisible;
public IStartPresenter Presenter { get; set; }
public string Text { get; set; }
public string ButtonText { get; set; }
public void SetButtonVisible(bool isVisible)
{
buttonVisible = isVisible;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c26636c25de34fd1b5d32fd8fdb9b47d
timeCreated: 1576186207

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62b5cc1364fceb24a9f76919757db06a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,147 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
namespace Unity.Cloud.Collaborate.Tests
{
public class CoroutineSynchronizationContext : SynchronizationContext
{
const int k_AwqInitialCapacity = 20;
readonly Queue<WorkRequest> m_AsyncWorkQueue = new Queue<WorkRequest>(k_AwqInitialCapacity);
readonly int m_MainThreadId = Thread.CurrentThread.ManagedThreadId;
// Send will process the call synchronously. If the call is processed on the main thread, we'll invoke it
// directly here. If the call is processed on another thread it will be queued up like POST to be executed
// on the main thread and it will wait. Once the main thread processes the work we can continue
public override void Send(SendOrPostCallback callback, object state)
{
if (m_MainThreadId == Thread.CurrentThread.ManagedThreadId)
{
callback(state);
}
else
{
using (var waitHandle = new ManualResetEvent(false))
{
lock (m_AsyncWorkQueue)
{
m_AsyncWorkQueue.Enqueue(new WorkRequest(callback, state, waitHandle));
}
waitHandle.WaitOne();
}
}
}
// Post will add the call to a task list to be executed later on the main thread then work will continue asynchronously
public override void Post(SendOrPostCallback callback, object state)
{
lock (m_AsyncWorkQueue)
{
m_AsyncWorkQueue.Enqueue(new WorkRequest(callback, state));
}
}
// Exec will execute tasks off the task list
public void Exec()
{
lock (m_AsyncWorkQueue)
{
var workCount = m_AsyncWorkQueue.Count;
for (var i = 0; i < workCount; i++)
{
var work = m_AsyncWorkQueue.Dequeue();
work.Invoke();
}
}
}
struct WorkRequest
{
readonly SendOrPostCallback m_DelegateCallback;
readonly object m_DelegateState;
readonly ManualResetEvent m_WaitHandle;
public WorkRequest(SendOrPostCallback callback, object state, ManualResetEvent waitHandle = null)
{
m_DelegateCallback = callback;
m_DelegateState = state;
m_WaitHandle = waitHandle;
}
public void Invoke()
{
m_DelegateCallback(m_DelegateState);
m_WaitHandle?.Set();
}
}
}
public class AsyncToCoroutine
{
readonly CoroutineSynchronizationContext m_Context;
readonly bool m_Cleanup;
public Func<Task> Before { get; set; }
public Func<Task> After { get; set; }
public AsyncToCoroutine(bool cleanup = true)
{
m_Context = new CoroutineSynchronizationContext();
m_Cleanup = cleanup;
}
public IEnumerator Run(Func<Task> func)
{
return Run(func, null);
}
// This method exists so we can avoid getting compiler warnings
// from non-async tests even if their Before/After are async
public IEnumerator Run(Action action)
{
return Run(null, action);
}
IEnumerator Run(Func<Task> func, Action action)
{
var oldContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(m_Context);
var task = RunAll();
while (!task.IsCompleted)
{
// Run any code that''s queued up.
m_Context.Exec();
// Skip frames until we're given more code or the task is done.
yield return null;
}
SynchronizationContext.SetSynchronizationContext(oldContext);
// Rethrow any exception that happened inside the task.
// Using a regular throw statement will lose the stack trace.
// https://stackoverflow.com/a/20170583
if (task.IsFaulted)
ExceptionDispatchInfo.Capture(task.Exception?.InnerException ?? task.Exception ?? new Exception("Unknown exception!")).Throw();
// Stupid hack to handle before/after methods that are async
// Ideally NUnit would do that for us but it doesn't support
// coroutines in it's Setup/Teardown methods.
async Task RunAll()
{
if (Before != null) await Before();
if (func != null)
await func();
else
action();
if (After != null) await After();
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c1d51319285aaa429e2c9f02a3b031c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,35 @@
namespace Unity.Cloud.Collaborate.Tests
{
public class BasicTests : ScenarioTestBase
{
// [UnityTest]
// public IEnumerator AddedAssetsShowAsUntrackedChanges()
// {
// return atc.Run(async () =>
// {
//
// // ensure initial clean state.
// await EnsureCleanChangesPageInitially();
//
// // ensure file doesn't already exist.
// const string filename = "file1.txt";
// File.Exists(filename).ShouldBe(false, $"{filename} already exists");
//
// // todo - wrap operations like these in a dedicated helper class.
// File.WriteAllText(filename, "added file empty content .. ");
//
// // todo - ahmad : port the state monitoring implementation from
// // collab ver to here to avoid arbitrary UI wait times.
// await Task.Delay(1000);
//
// var entries = (await BackendProvider.Instance.GetChanges());
// entries.Count.ShouldBe(1, "changes count did not add file1");
// entries[0].Path.ShouldBe("file1.txt", "change added is not named file1.txt");
// entries[0].Status.ShouldBe(ChangeEntryStatus.Untracked, "change added is untracked");
//
// // clean up the file. (todo - ahmad) : this should be added in an after() method.
// File.Delete(filename);
// });
// }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b4ac8521087fe8f4d9328b06d9fcf387
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,56 @@
using System;
namespace Unity.Cloud.Collaborate.Tests
{
public class ScenarioTestBase
{
// protected AsyncToCoroutine atc;
//
// [SetUp]
// public void Setup()
// {
// atc = new AsyncToCoroutine();
// }
//
// [OneTimeSetUp]
// public void OneTimeSetup()
// {
// SourceControlGitImplementation.IsRunningTests = true;
// }
//
// [OneTimeTearDown]
// public void OneTimeTearDown()
// {
// SourceControlGitImplementation.IsRunningTests = false;
// }
//
// protected async Task EnsureCleanChangesPageInitially()
// {
// Threading.mainThreadId = Thread.CurrentThread.ManagedThreadId;
//
// if (!BackendProvider.Instance.IsProviderInstalled())
// {
// BackendProvider.Instance.InstallProvider();
// }
//
// // set git identity - using RyanC test dedicated account.
// BackendProvider.Instance.SetGitNameAndEmail("ryancas+collabtest", "ryancas+collabtest@unity3d.com");
//
// // ensure clean state , todo - ahmad : add this to a setup/teardown pair of methods.
// await BackendProvider.Instance.CreateRepository();
// await BackendProvider.Instance.InitializeClient();
//
// BackendProvider.Instance.DoesRepositoryExist().ShouldBe(true, "Repository is not initialized");
// BackendProvider.Instance.IsClientInitialized().ShouldBe(true, "Git is not initialized");
//
// BackendProvider.Instance.Start();
//
// // ensure clean state by publishing everything.
// await BackendProvider.Instance.Publish("initial publish");
//
// // assert clean state.
// (await BackendProvider.Instance.GetChanges()).Count.ShouldBe(0, "file change count is not zero");
// }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38f16807aeb0a5349920644eef3e04f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using System;
namespace Unity.Cloud.Collaborate.Tests
{
public static class TestConstants
{
public const int RENDER_UI_THREAD_DELAY = 1000;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a374bf192ac57b94e9082ff6e1debb2a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,59 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace Unity.Cloud.Collaborate.Tests
{
public static class TestHelpers
{
public const string TestDirectory = "SomePathName/";
static readonly TaskFactory k_MyTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return k_MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
k_MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
public static void ThrowsAsync<T>(Func<Task> asyncDelegate) where T : Exception
{
Assert.Throws<T>(() => RunSync(asyncDelegate));
}
public static void ShouldBe<T>(this T expr1, T value, string msg = "")
{
if (!expr1.Equals(value))
throw new InvalidOperationException($"Test expected {value}, but found : {expr1}. [{msg}]");
}
public static void ShouldBe(this object expr1, object value, string msg = "")
{
if (expr1 != value)
throw new InvalidOperationException($"Test expected {value}, but found : {expr1}. [{msg}]");
}
public static void ShouldBeNull(object obj, string msg = "")
{
if (obj != null)
throw new InvalidOperationException($"Test expected null value, but found : {obj}. [{msg}]" );
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f922ccdce989b741a2eb502779aca3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,21 @@
using System;
using Unity.Cloud.Collaborate.Assets;
using Unity.Cloud.Collaborate.UserInterface;
using UnityEditor;
using UnityEngine.UIElements;
namespace Unity.Cloud.Collaborate.Tests
{
internal class TestWindow : EditorWindow
{
void OnEnable()
{
var root = rootVisualElement;
root.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(CollaborateWindow.MainStylePath));
root.AddToClassList(EditorGUIUtility.isProSkin
? UiConstants.ussDark
: UiConstants.ussLight);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3d6675532299974b9b16a1b9dcbab2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,141 @@
// This code snippet was provided originally by stanislav.osipov@unity3d.com from #ui-elements slack channel.
using System;
using System.Collections;
using Unity.Cloud.Collaborate.Assets;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace Unity.Cloud.Collaborate.Tests
{
internal static class UiTestHelpers
{
#region Events
// In order for tests to run without an EditorWindow but still be able to send
// events, we sometimes need to force the event type. IMGUI::GetEventType() (native) will
// return the event type as Ignore if the proper views haven't yet been
// initialized. This (falsely) breaks tests that rely on the event type. So for tests, we
// just ensure the event type is what we originally set it to when we sent it.
// This original type can be retrieved via Event.rawType.
static Event CreateEvent(Event evt)
{
return evt; //UIElementsUtility.CreateEvent(evt, evt.rawType);
}
public static Event MakeEvent(EventType type)
{
var evt = new Event { type = type };
return CreateEvent(evt);
}
public static Event MakeEvent(EventType type, Vector2 position)
{
var evt = new Event { type = type, mousePosition = position };
return CreateEvent(evt);
}
public static Event MakeKeyEvent(KeyCode code, EventType type = EventType.KeyDown, EventModifiers modifiers = EventModifiers.None, char character = '\0')
{
var evt = new Event { type = type, keyCode = code, character = character, modifiers = modifiers };
return CreateEvent(evt);
}
public static Event MakeMouseEvent(EventType type, Vector2 position, MouseButton button = MouseButton.LeftMouse, EventModifiers modifiers = EventModifiers.None, int clickCount = 1)
{
var evt = new Event { type = type, mousePosition = position, button = (int)button, modifiers = modifiers, clickCount = clickCount };
return CreateEvent(evt);
}
public static Event MakeScrollWheelEvent(Vector2 delta, Vector2 position)
{
var evt = new Event
{
type = EventType.ScrollWheel,
delta = delta,
mousePosition = position
};
return CreateEvent(evt);
}
public static Event MakeCommandEvent(EventType type, string command)
{
var evt = new Event { type = type, commandName = command };
return CreateEvent(evt);
}
#endregion
#region EditorWindow API
public static bool IsCompletelyVisible(EditorWindow window, VisualElement element)
{
if (element.ClassListContains(UiConstants.ussHidden))
{
return false;
}
var windowBounds = window.rootVisualElement.worldBound;
var elementBounds = element.worldBound;
return elementBounds.x >= windowBounds.x
&& elementBounds.y >= windowBounds.y
&& windowBounds.x + windowBounds.width >= elementBounds.x + elementBounds.width
&& windowBounds.y + windowBounds.height >= elementBounds.y + elementBounds.height;
}
public static bool IsPartiallyVisible(EditorWindow window, VisualElement element)
{
if (element.ClassListContains(UiConstants.ussHidden))
{
return false;
}
var windowBounds = window.rootVisualElement.worldBound;
var elementBounds = element.worldBound;
return !(elementBounds.x > windowBounds.x + windowBounds.width)
&& !(elementBounds.x + elementBounds.width < windowBounds.x)
&& !(elementBounds.y > windowBounds.y + windowBounds.height)
&& !(elementBounds.y + elementBounds.height < windowBounds.y);
}
public static void SendMouseDownEvent(EditorWindow window, VisualElement element)
{
var evt = MakeMouseEvent(EventType.MouseDown, element.worldBound.center);
window.SendEvent(evt);
}
public static void SendClickEvent(EditorWindow window, VisualElement element)
{
var evt = MakeMouseEvent(EventType.MouseDown, element.worldBound.center);
window.SendEvent(evt);
evt = MakeMouseEvent(EventType.MouseUp, element.worldBound.center);
window.SendEvent(evt);
}
public static void SimulateTyping(EditorWindow window, string text)
{
foreach (var character in text)
{
var evt = MakeKeyEvent(KeyCode.None, EventType.KeyDown, EventModifiers.None, character);
window.SendEvent(evt);
}
}
public static void SimulateTyping(EditorWindow window, char character, int repetitions)
{
for (var i = 0; i < repetitions; i++)
{
var evt = MakeKeyEvent(KeyCode.None, EventType.KeyDown, EventModifiers.None, character);
window.SendEvent(evt);
}
}
public static IEnumerator Pause(int frames)
{
for (var i = 0; i < frames; i++)
{
yield return null;
}
}
#endregion
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d87a2d0d02b26be4db83375afe481d39
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,23 @@
{
"name": "Unity.CollabProxy.EditorTests",
"references": [
"Unity.CollabProxy.Editor",
"UnityEngine.TestRunner",
"UnityEditor.TestRunner"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 88c7566234a7f32409f05c32e6ae7b3e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: