示例#1
0
        public override DirectoryInfo GetTempFolder()
        {
            var d = new DirectoryInfo(Application.temporaryCachePath);

            AssertV2.AreEqual(base.GetTempFolder().FullPath(), d.FullPath()); // TODO test this
            return(d);
        }
示例#2
0
        public override IEnumerator RunTest()
        {
            MyUserUi userUiPresenter = new MyUserUi();

            userUiPresenter.targetView = gameObject.GetViewStack().GetLatestView();

            { // Load a first user into the UI by passing it through the presenter:
                var user1 = new MyUserModel()
                {
                    userName = "******", userAge = 4
                };
                yield return(userUiPresenter.LoadModelIntoView(user1).AsCoroutine());

                AssertV2.AreEqual("Carl", userUiPresenter.NameInputField().text);
                AssertV2.AreEqual("4", userUiPresenter.AgeInputField().text);
            }

            yield return(new WaitForSeconds(1f)); // Load another user into the UI:

            {                                     // Example of loading a second user in a separate asyn method "LoadUser2":
                yield return(LoadUser2(userUiPresenter).AsCoroutine());

                AssertV2.AreEqual("55", userUiPresenter.AgeInputField().text); // The age of user 2
            }
        }
示例#3
0
        private static string GetKeyFromBsonDoc(BsonDocument x)
        {
            var key = x.Keys.First();

            AssertV2.AreEqual("_id", key);
            return(x[key].AsString);
        }
示例#4
0
 public void TestReadableAssertAreEqualErrorOutputs()
 {
     AssertV2.AreEqual("abcd", "abce");
     AssertV2.AreEqual(new int[4] {
         1, 2, 2, 4
     }, new int[4] {
         1, 2, 3, 4
     });
     AssertV2.AreEqual(new int[2] {
         1, 2
     }, new int[2] {
         1, 3
     });
     AssertV2.AreEqual(new int[6] {
         1, 2, 3, 4, 5, 6
     }, new int[6] {
         1, 2, 3, 4, 5, 7
     });
     AssertV2.AreEqual(new int[2] {
         1, 2
     }, new int[1] {
         1
     });
     AssertV2.AreEqual(new int[1] {
         1
     }, new int[2] {
         1, 2
     });
 }
示例#5
0
        public static Canvas GetOrAddRootCanvas()
        {
            var roots = GetAllRootCanvases();

            if (roots.IsNullOrEmpty())
            {
                return(CreateNewRootCanvas());
            }
            // Check if there is a root canvas that has a ViewStack attached:
            var rootCanvasesWithViewStack = roots.Filter(x => x.GetComponent <ViewStack>() != null);

            if (!rootCanvasesWithViewStack.IsNullOrEmpty())
            {
                AssertV2.AreEqual(1, rootCanvasesWithViewStack.Count(), "rootCanvasesWithViewStack");
                return(rootCanvasesWithViewStack.First());
            }
            // Prefer canvas objects that are on the root level of the open scene:
            var canvasesOnRootOfScene = roots.Filter(x => x.gameObject.GetParent() == null);

            if (canvasesOnRootOfScene.IsNullOrEmpty())
            {
                AssertV2.AreEqual(1, canvasesOnRootOfScene.Count(), "canvasesOnRootOfScene");
                return(canvasesOnRootOfScene.First());
            }
            // As a fallback return the first root canvas:
            return(roots.First());
        }
示例#6
0
        public static Texture2D ToTexture2D(this ImageResult self)
        {
            AssertV2.AreEqual(8, self.BitsPerChannel);
            Texture2D tex = new Texture2D(self.Width, self.Height, TextureFormat.RGBA32, false);

            tex.LoadRawTextureData(self.Data);
            tex.Apply();
            return(tex);
        }
示例#7
0
        private async Task LoadUser2(MyUserUi userUiPresenter)
        {
            var user2 = new MyUserModel()
            {
                userName = "******", userAge = 55
            };
            await userUiPresenter.LoadModelIntoView(user2);

            AssertV2.AreEqual("Anna", userUiPresenter.NameInputField().text);
        }
示例#8
0
        private Task <Texture2D> StartLoading(string imageUrl)
        {
            var runningTask = this.StartCoroutineAsTask(LoadFromUrlCoroutine(imageUrl, response), () => {
                AssertV2.AreEqual(imageUrlCurrentlyLoadingFrom, imageUrl); // Check that there was not a new url set in the meantime
                var result = response.getResult();
                response   = null;                                         // Set back to null to indicate the task is done
                return(result);
            });

            return(UnityRestRequest.WrapWithResponseErrorHandling(response, runningTask));
        }
示例#9
0
        public string GetHeaderValue(string headerName, string fallbackValue)
        {
            var headerValues = GetHeaderValues(headerName);

            if (headerValues == null)
            {
                return(fallbackValue);
            }
            AssertV2.AreEqual(1, headerValues.Count());
            return(headerValues.First());
        }
示例#10
0
        private async void ShowUserUi(GameObject buttonGo)
        {
            Ui1_PresenterTests.MyUserUi presenter = new Ui1_PresenterTests.MyUserUi();
            GameObject ui = gameObject.GetViewStack().ShowView("MyUserUi1", gameObject);

            presenter.targetView = ui;
            await presenter.LoadModelIntoView(currentUser);

            var links = ui.GetLinkMap();

            AssertV2.AreEqual(currentUser.userName, links.Get <InputField>("Name").text, "userName");
        }
示例#11
0
 private IEnumerator ShowAllFoundTests(List <XunitTestRunner.Test> allTests)
 {
     this.CellData = allTests;
     if (autoRunAllTests)
     {
         foreach (var test in allTests)
         {
             yield return(RunTestCoroutine(test));
         }
         AssertV2.AreEqual(0, allTests.Filter(t => t.testTask.IsFaulted).Count());
     }
 }
示例#12
0
    private void TestJsonSerialization()
    {
        var prefsKey = "testObj1";
        var myObj    = new MyClass1()
        {
            theCurrentTime = "It is " + DateTime.Now, myInt = 123
        };

        PlayerPrefsV2.SetObject(prefsKey, myObj);
        AssertV2.AreEqual(myObj.theCurrentTime, PlayerPrefsV2.GetObject <MyClass1>(prefsKey, null).theCurrentTime);
        AssertV2.AreEqual(myObj.myInt, PlayerPrefsV2.GetObject <MyClass1>(prefsKey, null).myInt);
        links.Get <Text>("JsonOutput").text = JsonWriter.GetWriter().Write(PlayerPrefsV2.GetObject <MyClass1>(prefsKey, null));
    }
示例#13
0
 private static MyUser ReduceSelection(MyModel parent, MyUser oldFieldValue, object action)
 {
     if (action is ChangeSelectionAction a)
     {
         return(a.newSelection);
     }
     if (action is DeleteAction d)
     {
         AssertV2.AreEqual(oldFieldValue, d.userToDelete, "currentlySelectedUser");
         return(null); // Clear selection when deleted
     }
     return(ReduceUser(oldFieldValue, action));
 }
 private static bool JsonCouldBeFullyParsed(IJsonReader reader, string path, IDictionary input, IDictionary parsed, int depth)
 {
     if (depth > MAX_DEPTH)
     {
         Log.e("Deth > " + MAX_DEPTH + ", will abort recursive search on this level, path=" + path); return(false);
     }
     foreach (var f in input)
     {
         var field = (DictionaryEntry)f;
         var key   = field.Key;
         var value = field.Value;
         //Assert.IsTrue(field != null);
         value = JsonReader.convertToGenericDictionaryOrArray(value);
         if (value != null && !parsed.Contains(key))
         {
             var infoStringAboutField = "field " + path + "." + key + " = " + value;
             if (value != null)
             {
                 infoStringAboutField += ", value type=(" + value.GetType() + ")";
             }
             var args = new StackFrame(5 + depth, true).AddTo(null);
             Log.e(" > Missing " + infoStringAboutField, args);
             return(false);
         }
         else if (value is IDictionary)
         {
             var a = value as IDictionary;
             var valueInParsedDict = JsonReader.convertToGenericDictionaryOrArray(parsed[key]);
             var b    = valueInParsedDict as IDictionary;
             var args = new StackFrame(5 + depth, true).AddTo(null);
             AssertV2.IsNotNull(b, "Field was found but it was not a JsonObject, it was a " + valueInParsedDict.GetType(), args);
             return(JsonCouldBeFullyParsed(reader, path + "." + key, a, b, depth + 1));
         }
         else if (value is IDictionary[])
         {
             var a = value as IDictionary[];
             var valueInParsedArray = JsonReader.convertToGenericDictionaryOrArray(parsed[key]);
             var b    = valueInParsedArray as IDictionary[];
             var args = new StackFrame(5 + depth, true).AddTo(null);
             AssertV2.IsNotNull(b, "Field was found but it was not a JsonArray, it was a " + valueInParsedArray.GetType(), args);
             AssertV2.AreEqual(a.Length, b.Length, "", args);
             var r = true;
             for (int i = 0; i < a.Length; i++)
             {
                 r = JsonCouldBeFullyParsed(reader, path + "." + key + "[" + i + "]", a[i], b[i], depth + 1) & r;
             }
             return(r);
         }
     }
     return(true);
 }
示例#15
0
        public void TestAssertV2Methods()
        {
            AssertV2.ThrowExeptionIfAssertionFails(() => {
                AssertV2.IsTrue(1 + 1 == 2, "This assertion must not fail");
                var s1 = "a";
                AssertV2.AreEqual(s1, s1);
                AssertV2.IsNull(null, "myVarX");
                AssertV2.AreEqual(1, 1);
                AssertV2.AreNotEqual(1, 2);
            });

            var stopWatch = AssertV2.TrackTiming();
            var res       = 1f;

            for (float i = 1; i < 500000; i++)
            {
                res = i / res + i;
            }
            Assert.NotEqual(0, res);

            stopWatch.Stop();
            AssertV2.ThrowExeptionIfAssertionFails(() => { stopWatch.AssertUnderXms(200); });
            Assert.True(stopWatch.IsUnderXms(200), "More time was needed than expected!");

            AssertV2.AreEqual("abcd", "abce");
            AssertV2.AreEqual(new int[4] {
                1, 2, 2, 4
            }, new int[4] {
                1, 2, 3, 4
            });
            AssertV2.AreEqual(new int[2] {
                1, 2
            }, new int[2] {
                1, 3
            });
            AssertV2.AreEqual(new int[6] {
                1, 2, 3, 4, 5, 6
            }, new int[6] {
                1, 2, 3, 4, 5, 7
            });
            AssertV2.AreEqual(new int[2] {
                1, 2
            }, new int[1] {
                1
            });
            AssertV2.AreEqual(new int[1] {
                1
            }, new int[2] {
                1, 2
            });
        }
示例#16
0
 public void TestAssertV2Throws()
 {
     AssertV2.ThrowExeptionIfAssertionFails(() => {
         try {
             AssertV2.Throws <Exception>(() => {
                 AssertV2.AreEqual(1, 1); // this will not fail..
             });                          // ..so the AssertV2.Throws should fail
             Log.e("This line should never be reached since AssertV2.Throws should fail!");
             throw new Exception("AssertV2.Throws did not fail correctly!");
         } catch (AssertV2.ThrowsException) { // Only catch it if its a ThrowsException
             // AssertV2.Throws failed correctly and threw an ThrowsException error
             Log.d("ThrowsException was expected and arrived correctly");
         }
     });
 }
 public static void CheckIntersectingFieldViewsForChanges(this Dictionary <string, FieldView> self, Dictionary <string, FieldView> newFieldViews,
                                                          Action <FieldView, FieldView, string> onUpdateNeeded)
 {
     foreach (var item in self.IntersectKeys(newFieldViews))
     {
         var oldFieldView  = item.Value;
         var newFieldView  = newFieldViews[item.Key];
         var newFieldValue = JsonWriter.GetWriter(newFieldView.field).Write(newFieldView.field);
         if (oldFieldView.fieldAsJson != newFieldValue)
         {
             onUpdateNeeded(oldFieldView, newFieldView, newFieldValue);
         }
         AssertV2.AreEqual(item.Value.fieldName, newFieldView.fieldName);
     }
 }
示例#18
0
 private IEnumerator ShowAllFoundTests(List <XunitTestRunner.Test> allTests)
 {
     this.CellData = allTests;
     if (autoRunAllTests)
     {
         using (var progress = pm.GetOrAddProgress("RunAllTests", allTests.Count, true)) {
             foreach (var test in allTests)
             {
                 progress.IncrementCount();
                 yield return(RunTestCoroutine(test));
             }
         }
         AssertV2.AreEqual(0, allTests.Filter(t => t.testTask.IsFaulted).Count());
     }
 }
示例#19
0
        /// <summary> Takes a string like AA34 and returns the CellPos for it </summary>
        private static CellPos ToCellPos(string cellPosString)
        {
            var regex = "([A-Za-z]+)([0-9]+)"; // See https://regex101.com/r/uS6cH4/19
            var match = Regex.Match(cellPosString, regex);

            AssertV2.AreEqual(3, match.Groups.Count);
            if (match.Groups.Count != 3)
            {
                throw Log.e("Invalid CellPos: " + cellPosString);
            }
            Group g0 = match.Groups[1];
            Group g1 = match.Groups[2];

            return(new CellPos(g0.Value, int.Parse(g1.Value)));
        }
示例#20
0
        private async Task TestJsonSerialization()
        {
            var t        = Log.MethodEntered();
            var prefsKey = "testObj1";
            var myObj    = new MyClass1()
            {
                theCurrentTime = "It is " + DateTimeV2.Now, myInt = 123
            };
            await Preferences.instance.Set(prefsKey, myObj);

            AssertV2.AreEqual(myObj.theCurrentTime, (await Preferences.instance.Get <MyClass1>(prefsKey, null)).theCurrentTime);
            AssertV2.AreEqual(myObj.myInt, (await Preferences.instance.Get <MyClass1>(prefsKey, null)).myInt);
            links.Get <Text>("JsonOutput").text = JsonWriter.GetWriter().Write(await Preferences.instance.Get <MyClass1>(prefsKey, null));
            Log.MethodDone(t);
        }
示例#21
0
 private MyUser3 ReduceUser(MyUser3 previousState, object action)
 {
     if (action is ActionSetNewUser a)
     {
         return(a.newUser);
     }
     if (action is ActionUpdateUser a2)
     {
         AssertV2.AreEqual(a2.target.name, previousState.name);
         if (object.Equals(a2.target.name, previousState.name))
         {
             return(a2.newValues);
         }
     }
     return(previousState);
 }
示例#22
0
        public static Canvas GetOrAddRootCanvas()
        {
            var roots = GetAllRootCanvases();

            if (roots.IsNullOrEmpty())
            {
                return(CreateNewRootCanvas());
            }
            // Check if there is a root canvas that has a ViewStack attached:
            var rootCanvasesWithViewStack = roots.Filter(x => x.GetComponent <ViewStack>() != null);

            if (!rootCanvasesWithViewStack.IsNullOrEmpty())
            {
                AssertV2.AreEqual(1, rootCanvasesWithViewStack.Count(), "rootCanvasesWithViewStack");
                return(rootCanvasesWithViewStack.First());
            }
            return(FilterForBestRootCanvas(roots));
        }
示例#23
0
        public bool SwitchBackToLastView(GameObject gameObject, bool destroyFinalView = false)
        {
            var currentView  = GetRootFor(gameObject);
            var currentIndex = currentView.transform.GetSiblingIndex();

            AssertV2.AreEqual(currentIndex, transform.childCount - 1, "Current was not last view in the stack");
            if (currentIndex > 0)
            {
                var lastView = transform.GetChild(currentIndex - 1).gameObject;
                lastView.SetActive(true);
                EventBus.instance.Publish(UiEvents.SWITCH_BACK_TO_LAST_VIEW, lastView);
            }
            if (currentIndex == 0 && !destroyFinalView)
            {
                return(false);
            }
            return(currentView.Destroy());
        }
示例#24
0
        private string GetFileExtensionFromMimeType(string fallbackValue)
        {
            var mime = GetContentMimeType(fallbackValue);

            if (mime == null)
            {
                return(fallbackValue);
            }
            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
            if (mime.Contains(";"))
            {
                mime = mime.Split(";").First(p => p.Contains("/"));
            }
            var x = mime.Split("/");

            AssertV2.AreEqual(2, x.Length);
            return(x.Last());
        }
示例#25
0
        public static async Task <Dictionary <Item, Item> > GetBestAnswersFor(string question, List <string> tags, int maxResults = 3)
        {
            ApiResponse bestQuestions = await Search(question, tags);

            var questionsWithAnswers            = bestQuestions.items.Filter(x => x.answer_count > 0 && x.score > 0);
            Dictionary <Item, Item> bestAnswers = new Dictionary <Item, Item>();

            foreach (Item q in questionsWithAnswers)
            {
                var answers = await GetAnswersForQuestion(q.question_id, pageSize : 1);

                AssertV2.AreEqual(1, answers.items.Count());
                bestAnswers.Add(q, answers.items.First());
                if (bestAnswers.Count >= maxResults)
                {
                    break;
                }
            }
            return(bestAnswers);
        }
示例#26
0
        public override IEnumerator RunTest()
        {
            // Create an immutable datastore that will contain the data model in this example:
            var log = Middlewares.NewLoggingMiddleware <MyDataModel3>();
            IDataStore <MyDataModel3> store = new DataStore <MyDataModel3>(MainReducer, new MyDataModel3(), log);

            IoC.inject.SetSingleton(store);

            // Create a presenter that connectes the model with the view (the Unity UI):
            var currentUserPresenter = new MyUserUi3();

            // Set the target view by loading it from a prefab and setting the root GO:
            currentUserPresenter.targetView = ViewStackHelper.MainViewStack().ShowView("MyUserUi1");
            // Connect the model changes with the presenter:
            currentUserPresenter.ListenToStoreUpdates(store, state => state.currentUser);

            // Dispatch a first setUser action to update the UI:
            store.Dispatch(new ActionSetNewUser()
            {
                newUser = new MyUser3("Carl", 99)
            });
            // Delay needed since the UI update simulates a delay too:
            yield return(new WaitForSeconds(0.5f));

            // Check that the UI was automatically updated:
            AssertV2.AreEqual("Carl", currentUserPresenter.NameUi().text);
            AssertV2.AreEqual("99", currentUserPresenter.AgeUi().text);

            // Simulate that the user changed the model via the UI:
            store.Dispatch(new ActionUpdateUser()
            {
                target    = store.GetState().currentUser,
                newValues = new MyUser3("Paul", 0)
            });
            // Delay needed since the UI update simulates a delay too:
            yield return(new WaitForSeconds(2f));

            // Check that the UI was automatically updated:
            AssertV2.AreEqual("Paul", currentUserPresenter.NameUi().text);
            AssertV2.AreEqual("0", currentUserPresenter.AgeUi().text);
        }
示例#27
0
        public string GetHeaderValue(string headerName, string fallbackValue, bool allowFuzzyHeaderName = true)
        {
            var headerValues = GetHeaderValues(headerName);

            if (headerValues == null && allowFuzzyHeaderName)
            {
                // Google names it "x-goog-stored-content-length" instead of "content-length"
                var similar = headers.Filter(x => x.Key.Contains(headerName.ToLowerInvariant()));
                // If there is exactly 1 header that matches the fuzzy search, use that one:
                if (similar.Count() == 1)
                {
                    headerValues = similar.First().Value;
                }
            }
            if (headerValues == null)
            {
                return(fallbackValue);
            }
            AssertV2.AreEqual(1, headerValues.Count());
            return(headerValues.First());
        }
示例#28
0
        public override IEnumerator RunTest()
        {
            var testTracker = new TestAppFlowTracker();

            testTracker.WithAllTrackingActive();
            AppFlow.AddAppFlowTracker(testTracker);

            setupImmutableDatastore();
            // In setupImmutableDatastore() Log.MethodEntered is used, so there must be a recorded method:
            AssertV2.AreEqual(1, testTracker.recordedEvents.Count(x => x.category == EventConsts.catMethod));
            // In setupImmutableDatastore() the datastore will be set as a singleton:
            AssertV2.AreEqual(1, testTracker.recordedEvents.Count(x => x.action.Contains("DataStore")));

            var store = MyDataModel.GetStore();

            AssertV2.IsNotNull(store, "store");
            store.Dispatch(new ActionSetBool1()
            {
                newB = true
            });
            store.Dispatch(new ActionSetString1 {
                newS = "abc"
            });
            AssertV2.AreEqual(true, store.GetState().subSection1.bool1);
            AssertV2.AreEqual("abc", store.GetState().subSection1.string1);
            // After the 2 mutations, there should be 2 mutation AppFlow events recorded:
            AssertV2.AreEqual(2, testTracker.recordedEvents.Count(x => x.category == EventConsts.catMutation));

            var presenter = new MyDataModelPresenter();

            presenter.targetView = gameObject;
            yield return(presenter.LoadModelIntoView(store).AsCoroutine());

            // After the presenter loaded the UI there should be a load start and load end event recorded:
            AssertV2.AreEqual(2, testTracker.recordedEvents.Count(x => x.category == EventConsts.catPresenter));
            // The MyDataModelPresenter uses a GetLinkMap() when connecting to the view:
            AssertV2.AreEqual(1, testTracker.recordedEvents.Count(x => x.category == EventConsts.catLinked));

            yield return(new WaitForSeconds(1));
        }
示例#29
0
        public void TestAssertV2Methods()
        {
            AssertV2.ThrowExeptionIfAssertionFails(() => {
                AssertV2.IsTrue(AssertV2.throwExeptionIfAssertionFails, "AssertV2.throwExeptionIfAssertionFails");

                AssertV2.IsTrue(1 + 1 == 2, "This assertion must not fail");
                AssertV2.Throws <Exception>(() => {
                    AssertV2.IsTrue(1 + 1 == 4, "This assertion has to fail");
                    Log.e("This line should never be printed since throwExeptionIfAssertionFails is true");
                });

                var s1 = "a";
                AssertV2.AreEqual(s1, s1);

                AssertV2.IsTrue(AssertV2.throwExeptionIfAssertionFails, "AssertV2.throwExeptionIfAssertionFails");
                AssertV2.Throws <Exception>(() => { AssertV2.AreNotEqual(s1, s1, "s1"); });

                string myVarX = null;
                AssertV2.IsNull(null, "myVarX");
                myVarX = "Now myVarX is not null anymore";
                AssertV2.Throws <Exception>(() => { AssertV2.IsNull(myVarX, "myVarX"); });

                AssertV2.AreEqual(1, 1);
                AssertV2.Throws <Exception>(() => { AssertV2.AreEqual(1, 2); });

                AssertV2.AreNotEqual(1, 2);
                AssertV2.Throws <Exception>(() => { AssertV2.AreNotEqual(1, 1); });

                var stopWatch = AssertV2.TrackTiming();
                Thread.Sleep(10);
                stopWatch.Stop();
                AssertV2.Throws <Exception>(() => { stopWatch.AssertUnderXms(1); }); // This should always fail

                stopWatch.AssertUnderXms(50);
                AssertV2.IsTrue(stopWatch.IsUnderXms(50), "More time was needed than expected!");
            });
        }
示例#30
0
        public virtual JsonSchema NewField(string name, Type parentType, object pInstance = null, JToken jpInstance = null)
        {
            MemberInfo model      = parentType?.GetMember(name).First();
            Type       modelType  = GetModelType(model);
            JTokenType jTokenType = ToJTokenType(modelType, jpInstance);

            AssertV2.IsNotNull(jTokenType, "jTokenType");
            JsonSchema newField = new JsonSchema()
            {
                type = jTokenType.ToJsonSchemaType(), title = JsonSchema.ToTitle(name)
            };

            ExtractFieldDocu(newField, model, modelType, jTokenType, pInstance, jpInstance);
            if (model != null)
            {
                if (!model.CanWriteTo())
                {
                    newField.readOnly = true;
                }
                if (model.TryGetCustomAttribute(out RegexAttribute attr))
                {
                    newField.pattern = attr.regex;
                }
                if (model.TryGetCustomAttribute(out ContentAttribute c))
                {
                    newField.format = "" + c.type;
                }
                if (model.TryGetCustomAttribute(out MinMaxRangeAttribute ra))
                {
                    newField.minimum = ra.minimum;
                    newField.maximum = ra.maximum;
                }
                if (model.TryGetCustomAttribute(out InputLengthAttribute ila))
                {
                    if (ila.minLength > 0)
                    {
                        newField.minLength = ila.minLength;
                    }
                    if (ila.maxLength > 0)
                    {
                        newField.maxLength = ila.maxLength;
                    }
                }
                if (model.TryGetCustomAttribute(out EnumAttribute e))
                {
                    newField.contentEnum     = e.names;
                    newField.additionalItems = e.allowOtherInput;
                }
                if (model.TryGetCustomAttribute(out RequiredAttribute r))
                {
                    newField.mandatory = true;
                }
                if (model.TryGetCustomAttribute(out JsonPropertyAttribute p))
                {
                    if (p.Required == Required.Always || p.Required == Required.DisallowNull)
                    {
                        newField.mandatory = true;
                    }
                }

                if (modelType.IsEnum)
                {
                    newField.contentEnum = Enum.GetNames(modelType);
                }
            }
            if (jTokenType == JTokenType.Object)
            {
                if (modelType == null)
                {
                    newField.properties = new Dictionary <string, JsonSchema>();
                    AddFieldsViaJson(newField, null, jpInstance as JObject);
                }
                else
                {
                    var modelInstance = pInstance != null?model.GetValue(pInstance) : null;

                    SetupInnerJsonSchema(newField, modelType, modelInstance);
                }
            }
            if (jTokenType == JTokenType.Array)
            {
                var listElemType   = GetListElementType(modelType);
                var arrayElemJType = ToJTokenType(listElemType);
                if (arrayElemJType == JTokenType.Null)
                {
                    if (jpInstance is JArray a && a.Count > 0)
                    {
                        arrayElemJType = a.First.Type;
                    }
                }
                if (arrayElemJType != JTokenType.Null)
                {
                    if (!IsSimpleType(arrayElemJType))
                    {
                        var childrenInstances = GetChildrenArray(pInstance, jpInstance, model);
                        if (childrenInstances == null || AllChildrenHaveSameType(childrenInstances))
                        {
                            var firstChildInstance = childrenInstances?.FirstOrDefault();
                            var childVm            = new JsonSchema()
                            {
                                type = arrayElemJType.ToJsonSchemaType()
                            };
                            SetupInnerJsonSchema(childVm, listElemType, firstChildInstance);
                            newField.items = new List <JsonSchema>()
                            {
                                childVm
                            };
                        }
                        else
                        {
                            newField.items = new List <JsonSchema>();
                            foreach (var child in childrenInstances)
                            {
                                var childVm = new JsonSchema()
                                {
                                    type = arrayElemJType.ToJsonSchemaType()
                                };
                                SetupInnerJsonSchema(childVm, child.GetType(), child);
                                newField.items.Add(childVm);
                            }
                            AssertV2.AreEqual(childrenInstances.Length, newField.items.Count);
                        }
                    }
                    else
                    {
                        newField.items = new List <JsonSchema>()
                        {
                            new JsonSchema()
                            {
                                type = arrayElemJType.ToJsonSchemaType()
                            }
                        };
                    }
                }
            }
            return(newField);
        }