예제 #1
0
        public void CanCaptureReferencesToDynamicallyAddedComponents()
        {
            var           appElement = MountTestComponent <ComponentRefComponent>();
            var           incrementButtonSelector  = By.CssSelector("#child-component button");
            var           currentCountTextSelector = By.CssSelector("#child-component p:first-of-type");
            var           resetButton         = appElement.FindElement(By.Id("reset-child"));
            var           toggleChildCheckbox = appElement.FindElement(By.Id("toggle-child"));
            Func <string> currentCountText    = () => appElement.FindElement(currentCountTextSelector).Text;

            // Verify the reference was captured initially
            appElement.FindElement(incrementButtonSelector).Click();
            WaitAssert.Equal("Current count: 1", currentCountText);
            resetButton.Click();
            WaitAssert.Equal("Current count: 0", currentCountText);
            appElement.FindElement(incrementButtonSelector).Click();
            WaitAssert.Equal("Current count: 1", currentCountText);

            // Remove and re-add a new instance of the child, checking the text was reset
            toggleChildCheckbox.Click();
            WaitAssert.Empty(() => appElement.FindElements(incrementButtonSelector));
            toggleChildCheckbox.Click();
            WaitAssert.Equal("Current count: 0", currentCountText);

            // Verify we have a new working reference
            appElement.FindElement(incrementButtonSelector).Click();
            WaitAssert.Equal("Current count: 1", currentCountText);
            resetButton.Click();
            WaitAssert.Equal("Current count: 0", currentCountText);
        }
예제 #2
0
        public void InputNumberInteractsWithEditContext_NonNullableInt()
        {
            var appElement       = MountTestComponent <TypicalValidationComponent>();
            var ageInput         = appElement.FindElement(By.ClassName("age")).FindElement(By.TagName("input"));
            var messagesAccessor = CreateValidationMessagesAccessor(appElement);

            // Validates on edit
            WaitAssert.Equal("valid", () => ageInput.GetAttribute("class"));
            ageInput.SendKeys("123\t");
            WaitAssert.Equal("modified valid", () => ageInput.GetAttribute("class"));

            // Can become invalid
            ageInput.SendKeys("e100\t");
            WaitAssert.Equal("modified invalid", () => ageInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "The AgeInYears field must be a number." }, messagesAccessor);

            // Empty is invalid, because it's not a nullable int
            ageInput.Clear();
            ageInput.SendKeys("\t");
            WaitAssert.Equal("modified invalid", () => ageInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "The AgeInYears field must be a number." }, messagesAccessor);

            // Zero is within the allowed range
            ageInput.SendKeys("0\t");
            WaitAssert.Equal("modified valid", () => ageInput.GetAttribute("class"));
            WaitAssert.Empty(messagesAccessor);
        }
예제 #3
0
        public async Task EditFormWorksWithDataAnnotationsValidator()
        {
            var appElement        = MountTestComponent <SimpleValidationComponent>();
            var userNameInput     = appElement.FindElement(By.ClassName("user-name")).FindElement(By.TagName("input"));
            var acceptsTermsInput = appElement.FindElement(By.ClassName("accepts-terms")).FindElement(By.TagName("input"));
            var submitButton      = appElement.FindElement(By.TagName("button"));
            var messagesAccessor  = CreateValidationMessagesAccessor(appElement);

            // Editing a field doesn't trigger validation on its own
            userNameInput.SendKeys("Bert\t");
            acceptsTermsInput.Click(); // Accept terms
            acceptsTermsInput.Click(); // Un-accept terms
            await Task.Delay(500);     // There's no expected change to the UI, so just wait a moment before asserting

            WaitAssert.Empty(messagesAccessor);
            Assert.Empty(appElement.FindElements(By.Id("last-callback")));

            // Submitting the form does validate
            submitButton.Click();
            WaitAssert.Equal(new[] { "You must accept the terms" }, messagesAccessor);
            WaitAssert.Equal("OnInvalidSubmit", () => appElement.FindElement(By.Id("last-callback")).Text);

            // Can make another field invalid
            userNameInput.Clear();
            submitButton.Click();
            WaitAssert.Equal(new[] { "Please choose a username", "You must accept the terms" }, messagesAccessor);
            WaitAssert.Equal("OnInvalidSubmit", () => appElement.FindElement(By.Id("last-callback")).Text);

            // Can make valid
            userNameInput.SendKeys("Bert\t");
            acceptsTermsInput.Click();
            submitButton.Click();
            WaitAssert.Empty(messagesAccessor);
            WaitAssert.Equal("OnValidSubmit", () => appElement.FindElement(By.Id("last-callback")).Text);
        }
예제 #4
0
        public void ValidationMessageDisplaysMessagesForField()
        {
            var appElement            = MountTestComponent <TypicalValidationComponent>();
            var emailContainer        = appElement.FindElement(By.ClassName("email"));
            var emailInput            = emailContainer.FindElement(By.TagName("input"));
            var emailMessagesAccessor = CreateValidationMessagesAccessor(emailContainer);
            var submitButton          = appElement.FindElement(By.TagName("button"));

            // Doesn't show messages for other fields
            submitButton.Click();
            WaitAssert.Empty(emailMessagesAccessor);

            // Updates on edit
            emailInput.SendKeys("abc\t");
            WaitAssert.Equal(new[] { "That doesn't look like a real email address" }, emailMessagesAccessor);

            // Can show more than one message
            emailInput.SendKeys("too long too long too long\t");
            WaitAssert.Equal(new[] { "That doesn't look like a real email address", "We only accept very short email addresses (max 10 chars)" }, emailMessagesAccessor);

            // Can become valid
            emailInput.Clear();
            emailInput.SendKeys("[email protected]\t");
            WaitAssert.Empty(emailMessagesAccessor);
        }
예제 #5
0
        public void InputDateInteractsWithEditContext_NonNullableDateTime()
        {
            var appElement       = MountTestComponent <TypicalValidationComponent>();
            var renewalDateInput = appElement.FindElement(By.ClassName("renewal-date")).FindElement(By.TagName("input"));
            var messagesAccessor = CreateValidationMessagesAccessor(appElement);

            // Validates on edit
            WaitAssert.Equal("valid", () => renewalDateInput.GetAttribute("class"));
            renewalDateInput.SendKeys("01/01/2000\t");
            WaitAssert.Equal("modified valid", () => renewalDateInput.GetAttribute("class"));

            // Can become invalid
            renewalDateInput.SendKeys("0/0/0");
            WaitAssert.Equal("modified invalid", () => renewalDateInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "The RenewalDate field must be a date." }, messagesAccessor);

            // Empty is invalid, because it's not nullable
            renewalDateInput.SendKeys($"{Keys.Backspace}\t{Keys.Backspace}\t{Keys.Backspace}\t");
            WaitAssert.Equal("modified invalid", () => renewalDateInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "The RenewalDate field must be a date." }, messagesAccessor);

            // Can become valid
            renewalDateInput.SendKeys("01/01/01\t");
            WaitAssert.Equal("modified valid", () => renewalDateInput.GetAttribute("class"));
            WaitAssert.Empty(messagesAccessor);
        }
예제 #6
0
        public void NonBubblingEvent_FiredOnElementWithoutHandler()
        {
            Browser.FindElement(By.Id("input-without-onfocus")).Click();

            // Triggers no event
            WaitAssert.Empty(GetLogLines);
        }
예제 #7
0
        public void CanRenderFragmentsWhilePreservingSurroundingElements()
        {
            // Initially, the region isn't shown
            var appElement     = MountTestComponent <RenderFragmentToggler>();
            var originalButton = appElement.FindElement(By.TagName("button"));
            Func <IEnumerable <IWebElement> > fragmentElements = () => appElement.FindElements(By.CssSelector("p[name=fragment-element]"));

            Assert.Empty(fragmentElements());

            // The JS-side DOM builder handles regions correctly, placing elements
            // after the region after the corresponding elements
            Assert.Equal("The end", appElement.FindElements(By.CssSelector("div > *:last-child")).Single().Text);

            // When we click the button, the region is shown
            originalButton.Click();
            WaitAssert.Single(fragmentElements);

            // The button itself was preserved, so we can click it again and see the effect
            originalButton.Click();
            WaitAssert.Empty(fragmentElements);
        }
예제 #8
0
        public void InputTextInteractsWithEditContext()
        {
            var appElement       = MountTestComponent <TypicalValidationComponent>();
            var nameInput        = appElement.FindElement(By.ClassName("name")).FindElement(By.TagName("input"));
            var messagesAccessor = CreateValidationMessagesAccessor(appElement);

            // Validates on edit
            WaitAssert.Equal("valid", () => nameInput.GetAttribute("class"));
            nameInput.SendKeys("Bert\t");
            WaitAssert.Equal("modified valid", () => nameInput.GetAttribute("class"));

            // Can become invalid
            nameInput.SendKeys("01234567890123456789\t");
            WaitAssert.Equal("modified invalid", () => nameInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "That name is too long" }, messagesAccessor);

            // Can become valid
            nameInput.Clear();
            nameInput.SendKeys("Bert\t");
            WaitAssert.Equal("modified valid", () => nameInput.GetAttribute("class"));
            WaitAssert.Empty(messagesAccessor);
        }
예제 #9
0
        public void InputTextAreaInteractsWithEditContext()
        {
            var appElement       = MountTestComponent <TypicalValidationComponent>();
            var descriptionInput = appElement.FindElement(By.ClassName("description")).FindElement(By.TagName("textarea"));
            var messagesAccessor = CreateValidationMessagesAccessor(appElement);

            // Validates on edit
            WaitAssert.Equal("valid", () => descriptionInput.GetAttribute("class"));
            descriptionInput.SendKeys("Hello\t");
            WaitAssert.Equal("modified valid", () => descriptionInput.GetAttribute("class"));

            // Can become invalid
            descriptionInput.SendKeys("too long too long too long too long too long\t");
            WaitAssert.Equal("modified invalid", () => descriptionInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "Description is max 20 chars" }, messagesAccessor);

            // Can become valid
            descriptionInput.Clear();
            descriptionInput.SendKeys("Hello\t");
            WaitAssert.Equal("modified valid", () => descriptionInput.GetAttribute("class"));
            WaitAssert.Empty(messagesAccessor);
        }
예제 #10
0
        public void InputNumberInteractsWithEditContext_NullableFloat()
        {
            var appElement       = MountTestComponent <TypicalValidationComponent>();
            var heightInput      = appElement.FindElement(By.ClassName("height")).FindElement(By.TagName("input"));
            var messagesAccessor = CreateValidationMessagesAccessor(appElement);

            // Validates on edit
            WaitAssert.Equal("valid", () => heightInput.GetAttribute("class"));
            heightInput.SendKeys("123.456\t");
            WaitAssert.Equal("modified valid", () => heightInput.GetAttribute("class"));

            // Can become invalid
            heightInput.SendKeys("e100\t");
            WaitAssert.Equal("modified invalid", () => heightInput.GetAttribute("class"));
            WaitAssert.Equal(new[] { "The OptionalHeight field must be a number." }, messagesAccessor);

            // Empty is valid, because it's a nullable float
            heightInput.Clear();
            heightInput.SendKeys("\t");
            WaitAssert.Equal("modified valid", () => heightInput.GetAttribute("class"));
            WaitAssert.Empty(messagesAccessor);
        }
예제 #11
0
        public void CanCaptureReferencesToDynamicallyAddedElements()
        {
            var appElement    = MountTestComponent <ElementRefComponent>();
            var buttonElement = appElement.FindElement(By.TagName("button"));
            var checkbox      = appElement.FindElement(By.CssSelector("input[type=checkbox]"));

            // We're going to remove the input. But first, put in some contents
            // so we can observe it's not the same instance later
            appElement.FindElement(By.Id("capturedElement")).SendKeys("some text");

            // Remove the captured element
            checkbox.Click();
            WaitAssert.Empty(() => appElement.FindElements(By.Id("capturedElement")));

            // Re-add it; observe it starts empty again
            checkbox.Click();
            var inputElement = appElement.FindElement(By.Id("capturedElement"));

            Assert.Equal(string.Empty, inputElement.GetAttribute("value"));

            // See that the capture variable was automatically updated to reference the new instance
            buttonElement.Click();
            WaitAssert.Equal("Clicks: 1", () => inputElement.GetAttribute("value"));
        }
예제 #12
0
        public void CanAddAndRemoveEventHandlersDynamically()
        {
            var appElement                 = MountTestComponent <CounterComponent>();
            var countDisplayElement        = appElement.FindElement(By.TagName("p"));
            var incrementButton            = appElement.FindElement(By.TagName("button"));
            var toggleClickHandlerCheckbox = appElement.FindElement(By.CssSelector("[type=checkbox]"));

            // Initial count is zero; clicking button increments count
            Assert.Equal("Current count: 0", countDisplayElement.Text);
            incrementButton.Click();
            WaitAssert.Equal("Current count: 1", () => countDisplayElement.Text);

            // We can remove an event handler
            toggleClickHandlerCheckbox.Click();
            WaitAssert.Empty(() => appElement.FindElements(By.Id("listening-message")));
            incrementButton.Click();
            WaitAssert.Equal("Current count: 1", () => countDisplayElement.Text);

            // We can add an event handler
            toggleClickHandlerCheckbox.Click();
            appElement.FindElement(By.Id("listening-message"));
            incrementButton.Click();
            WaitAssert.Equal("Current count: 2", () => countDisplayElement.Text);
        }