Browse Source
* web: make TextInput manage its view state * web: make TextInput manage its view state * web: make TextInput manage its view state * web: add tests for controlled TextArea and RadioButton * Add more tests for controlled and uncontrolled inputs * Add more tests for controlled and uncontrolled inputs * Update date input tests * Update time input tests * Update date input tests * Add docs for controlled and unctontrolled input modes * web: improve docs for controlled inputs * web: make benchmark add1kItems run only 2 times instead of 3 (to prevent it from throwing timeout) Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>pull/1048/head
Oleksandr Karpovich
3 years ago
committed by
GitHub
22 changed files with 1918 additions and 92 deletions
@ -0,0 +1,74 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. |
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.jetbrains.compose.web.attributes.builders |
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.NonRestartableComposable |
||||||
|
import org.jetbrains.compose.web.attributes.InputType |
||||||
|
import org.jetbrains.compose.web.dom.ElementScope |
||||||
|
import org.w3c.dom.HTMLElement |
||||||
|
import org.w3c.dom.HTMLInputElement |
||||||
|
import org.w3c.dom.HTMLTextAreaElement |
||||||
|
|
||||||
|
|
||||||
|
private val controlledInputsValuesWeakMap: JsWeakMap = js("new WeakMap();").unsafeCast<JsWeakMap>() |
||||||
|
|
||||||
|
internal fun restoreControlledInputState(type: InputType<*>, inputElement: HTMLInputElement) { |
||||||
|
if (controlledInputsValuesWeakMap.has(inputElement)) { |
||||||
|
if (type == InputType.Radio) { |
||||||
|
controlledRadioGroups[inputElement.name]?.forEach { radio -> |
||||||
|
radio.checked = controlledInputsValuesWeakMap.get(radio).toString().toBoolean() |
||||||
|
} |
||||||
|
inputElement.checked = controlledInputsValuesWeakMap.get(inputElement).toString().toBoolean() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if (type == InputType.Checkbox) { |
||||||
|
inputElement.checked = controlledInputsValuesWeakMap.get(inputElement).toString().toBoolean() |
||||||
|
} else { |
||||||
|
inputElement.value = controlledInputsValuesWeakMap.get(inputElement).toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal fun restoreControlledTextAreaState(element: HTMLTextAreaElement) { |
||||||
|
if (controlledInputsValuesWeakMap.has(element)) { |
||||||
|
element.value = controlledInputsValuesWeakMap.get(element).toString() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal fun <V : Any> saveControlledInputState(element: HTMLElement, value: V) { |
||||||
|
controlledInputsValuesWeakMap.set(element, value) |
||||||
|
|
||||||
|
if (element is HTMLInputElement) { |
||||||
|
updateRadioGroupIfNeeded(element) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// internal only for testing purposes. It actually should be private. |
||||||
|
internal val controlledRadioGroups = mutableMapOf<String, MutableSet<HTMLInputElement>>() |
||||||
|
|
||||||
|
private fun updateRadioGroupIfNeeded(element: HTMLInputElement) { |
||||||
|
if (element.type == "radio" && element.name.isNotEmpty()) { |
||||||
|
if (!controlledRadioGroups.containsKey(element.name)) { |
||||||
|
controlledRadioGroups[element.name] = mutableSetOf() |
||||||
|
} |
||||||
|
controlledRadioGroups[element.name]!!.add(element) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
@NonRestartableComposable |
||||||
|
internal fun ElementScope<HTMLInputElement>.DisposeRadioGroupEffect() { |
||||||
|
DisposableRefEffect { ref -> |
||||||
|
onDispose { |
||||||
|
controlledRadioGroups[ref.name]?.remove(ref) |
||||||
|
if (controlledRadioGroups[ref.name]?.isEmpty() == true) { |
||||||
|
controlledRadioGroups.remove(ref.name) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
package org.jetbrains.compose.web.core.tests |
||||||
|
|
||||||
|
import androidx.compose.runtime.* |
||||||
|
import org.jetbrains.compose.web.dom.Div |
||||||
|
import org.jetbrains.compose.web.attributes.builders.controlledRadioGroups |
||||||
|
import org.jetbrains.compose.web.attributes.name |
||||||
|
import org.jetbrains.compose.web.dom.RadioInput |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
import kotlin.test.assertTrue |
||||||
|
|
||||||
|
class ControlledRadioGroupsTests { |
||||||
|
|
||||||
|
@Test |
||||||
|
fun controlledRadioGroupGetsUpdated() = runTest { |
||||||
|
var countOfRadio by mutableStateOf(0) |
||||||
|
|
||||||
|
composition { |
||||||
|
repeat(countOfRadio) { |
||||||
|
key (it) { |
||||||
|
RadioInput(checked = false) { |
||||||
|
id("r$it") |
||||||
|
name("group1") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals(0, controlledRadioGroups.size) |
||||||
|
|
||||||
|
countOfRadio = 5 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(1, controlledRadioGroups.size) |
||||||
|
assertTrue(controlledRadioGroups.keys.first() == "group1") |
||||||
|
assertEquals(5, controlledRadioGroups["group1"]!!.size) |
||||||
|
|
||||||
|
countOfRadio = 2 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(1, controlledRadioGroups.size) |
||||||
|
assertTrue(controlledRadioGroups.keys.first() == "group1") |
||||||
|
assertEquals(2, controlledRadioGroups["group1"]!!.size) |
||||||
|
|
||||||
|
countOfRadio = 0 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(0, controlledRadioGroups.size) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun multipleControlledRadioGroupsGetUpdated() = runTest { |
||||||
|
var countOfRadioG1 by mutableStateOf(0) |
||||||
|
var countOfRadioG2 by mutableStateOf(0) |
||||||
|
|
||||||
|
composition { |
||||||
|
Div { |
||||||
|
repeat(countOfRadioG1) { |
||||||
|
key(it) { |
||||||
|
RadioInput(checked = false) { |
||||||
|
id("r1-$it") |
||||||
|
name("group1") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Div { |
||||||
|
repeat(countOfRadioG2) { |
||||||
|
key(it) { |
||||||
|
RadioInput(checked = false) { |
||||||
|
id("r2-$it") |
||||||
|
name("group2") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals(0, controlledRadioGroups.size) |
||||||
|
|
||||||
|
countOfRadioG1 = 5 |
||||||
|
countOfRadioG2 = 10 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(2, controlledRadioGroups.size) |
||||||
|
assertEquals(5, controlledRadioGroups["group1"]!!.size) |
||||||
|
assertEquals(10, controlledRadioGroups["group2"]!!.size) |
||||||
|
|
||||||
|
countOfRadioG2 = 2 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(2, controlledRadioGroups.size) |
||||||
|
assertEquals(5, controlledRadioGroups["group1"]!!.size) |
||||||
|
assertEquals(2, controlledRadioGroups["group2"]!!.size) |
||||||
|
|
||||||
|
countOfRadioG1 = 0 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(1, controlledRadioGroups.size) |
||||||
|
assertEquals(2, controlledRadioGroups["group2"]!!.size) |
||||||
|
|
||||||
|
countOfRadioG2 = 0 |
||||||
|
waitChanges() |
||||||
|
|
||||||
|
assertEquals(0, controlledRadioGroups.size) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,412 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. |
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
||||||
|
*/ |
||||||
|
|
||||||
|
package androidx.compose.web.sample.tests |
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import org.jetbrains.compose.web.attributes.InputType |
||||||
|
import org.jetbrains.compose.web.attributes.name |
||||||
|
import org.jetbrains.compose.web.dom.* |
||||||
|
import org.jetbrains.compose.web.sample.tests.TestText |
||||||
|
import org.jetbrains.compose.web.sample.tests.testCase |
||||||
|
|
||||||
|
class ControlledInputsTests { |
||||||
|
|
||||||
|
val textInputHardcodedValueShouldNotChange by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextInput(value = "hardcoded", attrs = { |
||||||
|
id("textInput") |
||||||
|
onInput { |
||||||
|
onInputText = it.value |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textInputMutableValueShouldGetOverridden by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("InitialValue") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextInput(value = onInputText, attrs = { |
||||||
|
id("textInput") |
||||||
|
onInput { |
||||||
|
onInputText = "OVERRIDDEN VALUE" |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textInputMutableValueShouldChange by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("InitialValue") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextInput(value = onInputText, attrs = { |
||||||
|
id("textInput") |
||||||
|
onInput { |
||||||
|
onInputText = it.value |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textAreaHardcodedValueShouldNotChange by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextArea(value = "hardcoded", attrs = { |
||||||
|
id("textArea") |
||||||
|
onInput { |
||||||
|
onInputText = it.value |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textAreaMutableValueShouldGetOverridden by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("InitialValue") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextArea(value = onInputText, attrs = { |
||||||
|
id("textArea") |
||||||
|
onInput { |
||||||
|
onInputText = "OVERRIDDEN VALUE" |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textAreaMutableValueShouldChange by testCase { |
||||||
|
var onInputText by remember { mutableStateOf("InitialValue") } |
||||||
|
|
||||||
|
P { TestText(onInputText) } |
||||||
|
|
||||||
|
Div { |
||||||
|
TextArea(value = onInputText, attrs = { |
||||||
|
id("textArea") |
||||||
|
onInput { |
||||||
|
onInputText = it.value |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val checkBoxHardcodedNeverChanges by testCase { |
||||||
|
var checkClicked by remember { mutableStateOf(false) } |
||||||
|
|
||||||
|
P { TestText(checkClicked.toString()) } |
||||||
|
|
||||||
|
Div { |
||||||
|
CheckboxInput(checked = false) { |
||||||
|
id("checkbox") |
||||||
|
onInput { |
||||||
|
checkClicked = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val checkBoxMutableValueChanges by testCase { |
||||||
|
var checked by remember { mutableStateOf(false) } |
||||||
|
|
||||||
|
P { TestText(checked.toString()) } |
||||||
|
|
||||||
|
Div { |
||||||
|
CheckboxInput(checked = checked) { |
||||||
|
id("checkbox") |
||||||
|
onInput { |
||||||
|
checked = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val checkBoxDefaultCheckedChangesDoesntAffectState by testCase { |
||||||
|
var checked by remember { mutableStateOf(true) } |
||||||
|
|
||||||
|
P { TestText(checked.toString()) } |
||||||
|
|
||||||
|
Div { |
||||||
|
Input(type = InputType.Checkbox) { |
||||||
|
id("checkboxMirror") |
||||||
|
if (checked) defaultChecked() |
||||||
|
} |
||||||
|
|
||||||
|
Input(type = InputType.Checkbox) { |
||||||
|
id("checkboxMain") |
||||||
|
checked(checked) |
||||||
|
onInput { checked = it.value } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val radioHardcodedNeverChanges by testCase { |
||||||
|
Div { |
||||||
|
RadioInput(checked = true) { |
||||||
|
id("radio1") |
||||||
|
name("group1") |
||||||
|
} |
||||||
|
RadioInput(checked = false) { |
||||||
|
id("radio2") |
||||||
|
name("group1") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val radioMutableCheckedChanges by testCase { |
||||||
|
var checked by remember { mutableStateOf(0) } |
||||||
|
|
||||||
|
TestText("Checked - $checked") |
||||||
|
|
||||||
|
Div { |
||||||
|
RadioInput(checked = checked == 1) { |
||||||
|
id("radio1") |
||||||
|
name("group1") |
||||||
|
onInput { checked = 1 } |
||||||
|
} |
||||||
|
RadioInput(checked = checked == 2) { |
||||||
|
id("radio2") |
||||||
|
name("group1") |
||||||
|
onInput { checked = 2 } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val numberHardcodedNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
NumberInput(value = 5, min = 0, max = 100) { |
||||||
|
id("numberInput") |
||||||
|
onInput { |
||||||
|
typedValue = it.value.toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val numberMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf(5) } |
||||||
|
TestText(value = value.toString()) |
||||||
|
|
||||||
|
NumberInput(value = value, min = 0, max = 100) { |
||||||
|
id("numberInput") |
||||||
|
onInput { |
||||||
|
value = it.value!!.toInt() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val rangeHardcodedNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
RangeInput(value = 21) { |
||||||
|
id("rangeInput") |
||||||
|
onInput { |
||||||
|
typedValue = it.value.toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val rangeMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf(10) } |
||||||
|
|
||||||
|
TestText(value = value.toString()) |
||||||
|
|
||||||
|
RangeInput(value = value) { |
||||||
|
id("rangeInput") |
||||||
|
onInput { |
||||||
|
value = it.value!!.toInt() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val emailHardcodedNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
EmailInput(value = "a@a.abc") { |
||||||
|
id("emailInput") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val emailMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf("") } |
||||||
|
TestText(value = value) |
||||||
|
|
||||||
|
EmailInput(value = value) { |
||||||
|
id("emailInput") |
||||||
|
onInput { |
||||||
|
value = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val passwordHardcodedNeverChanges by testCase { |
||||||
|
var typeValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typeValue) |
||||||
|
|
||||||
|
PasswordInput(value = "123456") { |
||||||
|
id("passwordInput") |
||||||
|
onInput { |
||||||
|
typeValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val passwordMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf("") } |
||||||
|
TestText(value = value) |
||||||
|
|
||||||
|
EmailInput(value = value) { |
||||||
|
id("passwordInput") |
||||||
|
onInput { |
||||||
|
value = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val searchHardcodedNeverChanges by testCase { |
||||||
|
var typeValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typeValue) |
||||||
|
|
||||||
|
SearchInput(value = "hardcoded") { |
||||||
|
id("searchInput") |
||||||
|
onInput { |
||||||
|
typeValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val searchMutableChanges by testCase { |
||||||
|
var typeValue by remember { mutableStateOf("") } |
||||||
|
TestText(value = typeValue) |
||||||
|
|
||||||
|
SearchInput(value = typeValue) { |
||||||
|
id("searchInput") |
||||||
|
onInput { |
||||||
|
typeValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val telHardcodedNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
TelInput(value = "123456") { |
||||||
|
id("telInput") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val telMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf("") } |
||||||
|
TestText(value = value) |
||||||
|
|
||||||
|
TelInput(value = value) { |
||||||
|
id("telInput") |
||||||
|
onInput { |
||||||
|
value = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val urlHardcodedNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
UrlInput(value = "www.site.com") { |
||||||
|
id("urlInput") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val urlMutableChanges by testCase { |
||||||
|
var value by remember { mutableStateOf("") } |
||||||
|
TestText(value = value) |
||||||
|
|
||||||
|
UrlInput(value = value) { |
||||||
|
id("urlInput") |
||||||
|
onInput { |
||||||
|
value = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val hardcodedDateInputNeverChanges by testCase { |
||||||
|
var inputValue by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
TestText(inputValue) |
||||||
|
|
||||||
|
DateInput(value = "") { |
||||||
|
id("dateInput") |
||||||
|
onInput { |
||||||
|
inputValue = "onInput Caught" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val mutableDateInputChanges by testCase { |
||||||
|
var inputValue by remember { mutableStateOf("") } |
||||||
|
|
||||||
|
TestText(inputValue) |
||||||
|
|
||||||
|
DateInput(value = inputValue) { |
||||||
|
id("dateInput") |
||||||
|
onInput { |
||||||
|
inputValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val hardcodedTimeNeverChanges by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
TestText(typedValue) |
||||||
|
|
||||||
|
TimeInput(value = "14:00") { |
||||||
|
id("time") |
||||||
|
onInput { |
||||||
|
typedValue = "onInput Caught" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val mutableTimeChanges by testCase { |
||||||
|
var value by remember { mutableStateOf("") } |
||||||
|
|
||||||
|
TestText(value) |
||||||
|
|
||||||
|
TimeInput(value = value) { |
||||||
|
id("time") |
||||||
|
onInput { |
||||||
|
value = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,190 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. |
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
||||||
|
*/ |
||||||
|
|
||||||
|
package androidx.compose.web.sample.tests |
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import org.jetbrains.compose.web.attributes.InputType |
||||||
|
import org.jetbrains.compose.web.attributes.name |
||||||
|
import org.jetbrains.compose.web.dom.* |
||||||
|
import org.jetbrains.compose.web.sample.tests.TestText |
||||||
|
import org.jetbrains.compose.web.sample.tests.testCase |
||||||
|
|
||||||
|
class UncontrolledInputsTests { |
||||||
|
|
||||||
|
val textInputDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var inputValue by remember { mutableStateOf("") } |
||||||
|
|
||||||
|
Input(type = InputType.Text) { |
||||||
|
|
||||||
|
id("textInput") |
||||||
|
defaultValue("defaultInputValue") |
||||||
|
|
||||||
|
attr("data-input-value", inputValue) |
||||||
|
|
||||||
|
onInput { |
||||||
|
inputValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val textAreaDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var inputValue by remember { mutableStateOf("") } |
||||||
|
|
||||||
|
TextArea { |
||||||
|
|
||||||
|
id("textArea") |
||||||
|
defaultValue("defaultTextAreaValue") |
||||||
|
|
||||||
|
attr("data-text-area-value", inputValue) |
||||||
|
|
||||||
|
onInput { |
||||||
|
inputValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val checkBoxDefaultCheckedRemainsTheSameButCheckedCanBeChanged by testCase { |
||||||
|
var checkedValue by remember { mutableStateOf(true) } |
||||||
|
|
||||||
|
Input(type = InputType.Checkbox) { |
||||||
|
id("checkbox") |
||||||
|
defaultChecked() |
||||||
|
value("checkbox-value") |
||||||
|
|
||||||
|
attr("data-checkbox", checkedValue.toString()) |
||||||
|
|
||||||
|
onInput { |
||||||
|
checkedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val radioDefaultCheckedRemainsTheSameButCheckedCanBeChanged by testCase { |
||||||
|
var checkedValue by remember { mutableStateOf("") } |
||||||
|
|
||||||
|
Input(type = InputType.Radio) { |
||||||
|
id("radio1") |
||||||
|
defaultChecked() |
||||||
|
value("radio-value1") |
||||||
|
name("radiogroup") |
||||||
|
|
||||||
|
attr("data-radio", checkedValue) |
||||||
|
|
||||||
|
onInput { |
||||||
|
checkedValue = "radio-value1" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Input(type = InputType.Radio) { |
||||||
|
id("radio2") |
||||||
|
value("radio-value2") |
||||||
|
name("radiogroup") |
||||||
|
|
||||||
|
attr("data-radio", checkedValue) |
||||||
|
|
||||||
|
onInput { |
||||||
|
checkedValue = "radio-value2" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val numberDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
TestText(value = "Value = $typedValue") |
||||||
|
|
||||||
|
Input(type = InputType.Number) { |
||||||
|
id("numberInput") |
||||||
|
defaultValue(11) |
||||||
|
onInput { |
||||||
|
typedValue = it.value.toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val rangeDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
|
||||||
|
TestText(value = "Value = $typedValue") |
||||||
|
|
||||||
|
Input(type = InputType.Range) { |
||||||
|
id("rangeInput") |
||||||
|
defaultValue(7) |
||||||
|
onInput { |
||||||
|
typedValue = it.value.toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val emailDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = "Value = $typedValue") |
||||||
|
|
||||||
|
Input(type = InputType.Email) { |
||||||
|
id("emailInput") |
||||||
|
defaultValue("a@a.abc") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val passwordDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = "Value = $typedValue") |
||||||
|
|
||||||
|
Input(type = InputType.Password) { |
||||||
|
id("passwordInput") |
||||||
|
defaultValue("1111") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val searchDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = "Value = $typedValue") |
||||||
|
|
||||||
|
Input(type = InputType.Search) { |
||||||
|
id("searchInput") |
||||||
|
defaultValue("kotlin") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val telDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
Input(type = InputType.Tel) { |
||||||
|
id("telInput") |
||||||
|
defaultValue("123123") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val urlDefaultValueRemainsTheSameButValueCanBeChanged by testCase { |
||||||
|
var typedValue by remember { mutableStateOf("None") } |
||||||
|
TestText(value = typedValue) |
||||||
|
|
||||||
|
Input(type = InputType.Url) { |
||||||
|
id("urlInput") |
||||||
|
defaultValue("www.site.com") |
||||||
|
onInput { |
||||||
|
typedValue = it.value |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,507 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. |
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.jetbrains.compose.web.tests.integration |
||||||
|
|
||||||
|
import org.jetbrains.compose.web.tests.integration.common.BaseIntegrationTests |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.ResolveDrivers |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.openTestPage |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.waitTextToBe |
||||||
|
import org.junit.jupiter.api.Assumptions |
||||||
|
import org.openqa.selenium.By |
||||||
|
import org.openqa.selenium.Keys |
||||||
|
import org.openqa.selenium.WebDriver |
||||||
|
import org.openqa.selenium.chrome.ChromeDriver |
||||||
|
|
||||||
|
class ControlledInputsTests : BaseIntegrationTests() { |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textInputHardcodedValueShouldNotChange(driver: WebDriver) { |
||||||
|
driver.openTestPage("textInputHardcodedValueShouldNotChange") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val controlledTextInput = driver.findElement(By.id("textInput")) |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("A") |
||||||
|
driver.waitTextToBe(value = "hardcodedA") |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("B") |
||||||
|
driver.waitTextToBe(value = "hardcodedB") |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("C") |
||||||
|
driver.waitTextToBe(value = "hardcodedC") |
||||||
|
|
||||||
|
check(controlledTextInput.getAttribute("value") == "hardcoded") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textInputMutableValueShouldGetOverridden(driver: WebDriver) { |
||||||
|
driver.openTestPage("textInputMutableValueShouldGetOverridden") |
||||||
|
driver.waitTextToBe(value = "InitialValue") |
||||||
|
|
||||||
|
val controlledTextInput = driver.findElement(By.id("textInput")) |
||||||
|
controlledTextInput.sendKeys("ABC") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "OVERRIDDEN VALUE") |
||||||
|
check(controlledTextInput.getAttribute("value") == "OVERRIDDEN VALUE") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textInputMutableValueShouldChange(driver: WebDriver) { |
||||||
|
driver.openTestPage("textInputMutableValueShouldChange") |
||||||
|
driver.waitTextToBe(value = "InitialValue") |
||||||
|
|
||||||
|
val controlledTextInput = driver.findElement(By.id("textInput")) |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("A") |
||||||
|
driver.waitTextToBe(value = "InitialValueA") |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("B") |
||||||
|
driver.waitTextToBe(value = "InitialValueAB") |
||||||
|
|
||||||
|
controlledTextInput.sendKeys("C") |
||||||
|
driver.waitTextToBe(value = "InitialValueABC") |
||||||
|
|
||||||
|
check(controlledTextInput.getAttribute("value") == "InitialValueABC") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textAreaHardcodedValueShouldNotChange(driver: WebDriver) { |
||||||
|
driver.openTestPage("textAreaHardcodedValueShouldNotChange") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val controlledTextArea = driver.findElement(By.id("textArea")) |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("A") |
||||||
|
driver.waitTextToBe(value = "hardcodedA") |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("B") |
||||||
|
driver.waitTextToBe(value = "hardcodedB") |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("C") |
||||||
|
driver.waitTextToBe(value = "hardcodedC") |
||||||
|
|
||||||
|
check(controlledTextArea.getAttribute("value") == "hardcoded") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textAreaMutableValueShouldGetOverridden(driver: WebDriver) { |
||||||
|
driver.openTestPage("textAreaMutableValueShouldGetOverridden") |
||||||
|
driver.waitTextToBe(value = "InitialValue") |
||||||
|
|
||||||
|
val controlledTextArea = driver.findElement(By.id("textArea")) |
||||||
|
controlledTextArea.sendKeys("ABC") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "OVERRIDDEN VALUE") |
||||||
|
check(controlledTextArea.getAttribute("value") == "OVERRIDDEN VALUE") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textAreaMutableValueShouldChange(driver: WebDriver) { |
||||||
|
driver.openTestPage("textAreaMutableValueShouldChange") |
||||||
|
driver.waitTextToBe(value = "InitialValue") |
||||||
|
|
||||||
|
val controlledTextArea = driver.findElement(By.id("textArea")) |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("A") |
||||||
|
driver.waitTextToBe(value = "InitialValueA") |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("B") |
||||||
|
driver.waitTextToBe(value = "InitialValueAB") |
||||||
|
|
||||||
|
controlledTextArea.sendKeys("C") |
||||||
|
driver.waitTextToBe(value = "InitialValueABC") |
||||||
|
|
||||||
|
check(controlledTextArea.getAttribute("value") == "InitialValueABC") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun checkBoxHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("checkBoxHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "false") |
||||||
|
|
||||||
|
val checkbox = driver.findElement(By.id("checkbox")) |
||||||
|
check(!checkbox.isSelected) |
||||||
|
|
||||||
|
checkbox.click() |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "true") // input received but ignored |
||||||
|
check(!checkbox.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun checkBoxMutableValueChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("checkBoxMutableValueChanges") |
||||||
|
driver.waitTextToBe(value = "false") |
||||||
|
|
||||||
|
val checkbox = driver.findElement(By.id("checkbox")) |
||||||
|
check(!checkbox.isSelected) |
||||||
|
|
||||||
|
checkbox.click() |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "true") |
||||||
|
check(checkbox.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun checkBoxDefaultCheckedChangesDoesntAffectState(driver: WebDriver) { |
||||||
|
driver.openTestPage("checkBoxDefaultCheckedChangesDoesntAffectState") |
||||||
|
driver.waitTextToBe(value = "true") |
||||||
|
|
||||||
|
val mainCheckbox = driver.findElement(By.id("checkboxMain")) |
||||||
|
val mirrorCheckbox = driver.findElement(By.id("checkboxMirror")) |
||||||
|
|
||||||
|
check(mainCheckbox.isSelected) |
||||||
|
check(mirrorCheckbox.isSelected) |
||||||
|
|
||||||
|
mirrorCheckbox.click() |
||||||
|
driver.waitTextToBe(value = "true") |
||||||
|
check(!mirrorCheckbox.isSelected) |
||||||
|
check(mainCheckbox.isSelected) |
||||||
|
|
||||||
|
mainCheckbox.click() |
||||||
|
driver.waitTextToBe(value = "false") |
||||||
|
check(!mainCheckbox.isSelected) |
||||||
|
check(!mirrorCheckbox.isSelected) |
||||||
|
|
||||||
|
mainCheckbox.click() |
||||||
|
driver.waitTextToBe(value = "true") |
||||||
|
check(mainCheckbox.isSelected) |
||||||
|
check(!mirrorCheckbox.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun radioHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("radioHardcodedNeverChanges") |
||||||
|
|
||||||
|
val radio1 = driver.findElement(By.id("radio1")) |
||||||
|
val radio2 = driver.findElement(By.id("radio2")) |
||||||
|
|
||||||
|
check(radio1.isSelected) |
||||||
|
check(!radio2.isSelected) |
||||||
|
|
||||||
|
check(radio1.getAttribute("name") == radio2.getAttribute("name")) |
||||||
|
check(radio1.getAttribute("name") == "group1") |
||||||
|
check(radio2.getAttribute("name") == "group1") |
||||||
|
|
||||||
|
radio2.click() |
||||||
|
|
||||||
|
check(radio1.isSelected) |
||||||
|
check(!radio2.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun radioMutableCheckedChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("radioMutableCheckedChanges") |
||||||
|
driver.waitTextToBe(value = "Checked - 0") |
||||||
|
|
||||||
|
val radio1 = driver.findElement(By.id("radio1")) |
||||||
|
val radio2 = driver.findElement(By.id("radio2")) |
||||||
|
|
||||||
|
check(!radio1.isSelected) |
||||||
|
check(!radio2.isSelected) |
||||||
|
|
||||||
|
radio2.click() |
||||||
|
driver.waitTextToBe(value = "Checked - 2") |
||||||
|
|
||||||
|
check(!radio1.isSelected) |
||||||
|
check(radio2.isSelected) |
||||||
|
|
||||||
|
radio1.click() |
||||||
|
driver.waitTextToBe(value = "Checked - 1") |
||||||
|
|
||||||
|
check(radio1.isSelected) |
||||||
|
check(!radio2.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun numberHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("numberHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("numberInput")) |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "5") |
||||||
|
|
||||||
|
numberInput.sendKeys("1") |
||||||
|
driver.waitTextToBe(value = "51") |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "5") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun numberMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("numberMutableChanges") |
||||||
|
driver.waitTextToBe(value = "5") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("numberInput")) |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "5") |
||||||
|
|
||||||
|
numberInput.sendKeys("1") |
||||||
|
driver.waitTextToBe(value = "51") |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "51") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun rangeHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("rangeHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("rangeInput")) |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "21") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "22") |
||||||
|
check(numberInput.getAttribute("value") == "21") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "22") |
||||||
|
check(numberInput.getAttribute("value") == "21") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun rangeMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("rangeMutableChanges") |
||||||
|
driver.waitTextToBe(value = "10") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("rangeInput")) |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "10") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "11") |
||||||
|
check(numberInput.getAttribute("value") == "11") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "12") |
||||||
|
check(numberInput.getAttribute("value") == "12") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun emailHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("emailHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val emailInput = driver.findElement(By.id("emailInput")) |
||||||
|
check(emailInput.getAttribute("value") == "a@a.abc") |
||||||
|
|
||||||
|
emailInput.sendKeys("@") |
||||||
|
driver.waitTextToBe(value = "a@a.abc@") |
||||||
|
|
||||||
|
check(emailInput.getAttribute("value") == "a@a.abc") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun emailMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("emailMutableChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val emailInput = driver.findElement(By.id("emailInput")) |
||||||
|
check(emailInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
emailInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "a") |
||||||
|
|
||||||
|
check(emailInput.getAttribute("value") == "a") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun passwordHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("passwordHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val passwordInput = driver.findElement(By.id("passwordInput")) |
||||||
|
check(passwordInput.getAttribute("value") == "123456") |
||||||
|
|
||||||
|
passwordInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "123456a") |
||||||
|
|
||||||
|
check(passwordInput.getAttribute("value") == "123456") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun passwordMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("passwordMutableChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val passwordInput = driver.findElement(By.id("passwordInput")) |
||||||
|
check(passwordInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
passwordInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "a") |
||||||
|
|
||||||
|
check(passwordInput.getAttribute("value") == "a") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun searchHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("searchHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val searchInput = driver.findElement(By.id("searchInput")) |
||||||
|
check(searchInput.getAttribute("value") == "hardcoded") |
||||||
|
|
||||||
|
searchInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "hardcodeda") |
||||||
|
|
||||||
|
check(searchInput.getAttribute("value") == "hardcoded") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun searchMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("searchMutableChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val searchInput = driver.findElement(By.id("searchInput")) |
||||||
|
check(searchInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
searchInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "a") |
||||||
|
|
||||||
|
check(searchInput.getAttribute("value") == "a") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun telHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("telHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val telInput = driver.findElement(By.id("telInput")) |
||||||
|
check(telInput.getAttribute("value") == "123456") |
||||||
|
|
||||||
|
telInput.sendKeys("7") |
||||||
|
driver.waitTextToBe(value = "1234567") |
||||||
|
|
||||||
|
check(telInput.getAttribute("value") == "123456") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun telMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("telMutableChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val telInput = driver.findElement(By.id("telInput")) |
||||||
|
check(telInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
telInput.sendKeys("1") |
||||||
|
driver.waitTextToBe(value = "1") |
||||||
|
|
||||||
|
check(telInput.getAttribute("value") == "1") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun urlHardcodedNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("urlHardcodedNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val urlInput = driver.findElement(By.id("urlInput")) |
||||||
|
check(urlInput.getAttribute("value") == "www.site.com") |
||||||
|
|
||||||
|
urlInput.sendKeys("a") |
||||||
|
driver.waitTextToBe(value = "www.site.coma") |
||||||
|
|
||||||
|
check(urlInput.getAttribute("value") == "www.site.com") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun urlMutableChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("urlMutableChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val urlInput = driver.findElement(By.id("urlInput")) |
||||||
|
check(urlInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
urlInput.sendKeys("w") |
||||||
|
driver.waitTextToBe(value = "w") |
||||||
|
|
||||||
|
check(urlInput.getAttribute("value") == "w") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun hardcodedDateInputNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("hardcodedDateInputNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val dateInput = driver.findElement(By.id("dateInput")) |
||||||
|
check(dateInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
driver.sendKeysForDateInput(dateInput, 2021, 10, 22) |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "onInput Caught") |
||||||
|
check(dateInput.getAttribute("value") == "") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun mutableDateInputChanges(driver: WebDriver) { |
||||||
|
// We skip chrome, since for some reason `sendKeys` doesn't work as expected when used for Controlled Input in Chrome |
||||||
|
Assumptions.assumeTrue( |
||||||
|
driver !is ChromeDriver, |
||||||
|
"chrome driver doesn't work properly when using sendKeys on Controlled Input" |
||||||
|
) |
||||||
|
|
||||||
|
driver.openTestPage("mutableDateInputChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val dateInput = driver.findElement(By.id("dateInput")) |
||||||
|
check(dateInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
driver.sendKeysForDateInput(dateInput, 2021, 10, 22) |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "2021-10-22") |
||||||
|
check(dateInput.getAttribute("value") == "2021-10-22") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun hardcodedTimeNeverChanges(driver: WebDriver) { |
||||||
|
driver.openTestPage("hardcodedTimeNeverChanges") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val timeInput = driver.findElement(By.id("time")) |
||||||
|
check(timeInput.getAttribute("value") == "14:00") |
||||||
|
|
||||||
|
timeInput.sendKeys("18:31") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "onInput Caught") |
||||||
|
check(timeInput.getAttribute("value") == "14:00") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun mutableTimeChanges(driver: WebDriver) { |
||||||
|
// We skip chrome, since for some reason `sendKeys` doesn't work as expected when used for Controlled Input in Chrome |
||||||
|
Assumptions.assumeTrue( |
||||||
|
driver !is ChromeDriver, |
||||||
|
"chrome driver doesn't work properly when using sendKeys on Controlled Input" |
||||||
|
) |
||||||
|
|
||||||
|
driver.openTestPage("mutableTimeChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val timeInput = driver.findElement(By.id("time")) |
||||||
|
check(timeInput.getAttribute("value") == "") |
||||||
|
|
||||||
|
timeInput.sendKeys("18:31") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "18:31") |
||||||
|
check(timeInput.getAttribute("value") == "18:31") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun timeInputSendKeysOnChromeFailingTest(driver: WebDriver) { |
||||||
|
Assumptions.assumeTrue( |
||||||
|
driver is ChromeDriver, |
||||||
|
"this a `failing test for Chrome only` to catch when issue with sendKeys is resolved" |
||||||
|
) |
||||||
|
driver.openTestPage("mutableTimeChanges") |
||||||
|
driver.waitTextToBe(value = "") |
||||||
|
|
||||||
|
val timeInput = driver.findElement(By.id("time")) |
||||||
|
|
||||||
|
timeInput.sendKeys("18:31") |
||||||
|
driver.waitTextToBe(value = "18:03") // it should be 18:31, but this is a failing test, so wrong value is expected |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,208 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. |
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.jetbrains.compose.web.tests.integration |
||||||
|
|
||||||
|
import org.jetbrains.compose.web.tests.integration.common.BaseIntegrationTests |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.ResolveDrivers |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.openTestPage |
||||||
|
import org.jetbrains.compose.web.tests.integration.common.waitTextToBe |
||||||
|
import org.openqa.selenium.By |
||||||
|
import org.openqa.selenium.Keys |
||||||
|
import org.openqa.selenium.WebDriver |
||||||
|
|
||||||
|
class UncontrolledInputsTests : BaseIntegrationTests() { |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textInputDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("textInputDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
|
||||||
|
val input = driver.findElement(By.id("textInput")) |
||||||
|
check(input.getAttribute("value") == "defaultInputValue") |
||||||
|
|
||||||
|
input.sendKeys("-TypedText") |
||||||
|
|
||||||
|
val inputHtml = driver.outerHtmlOfElementWithId("textInput") |
||||||
|
|
||||||
|
check(inputHtml.contains("value=\"defaultInputValue\"")) |
||||||
|
check(input.getAttribute("value") == "defaultInputValue-TypedText") // this checks the `value` property of the input |
||||||
|
check(input.getAttribute("data-input-value") == "defaultInputValue-TypedText") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun textAreaDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("textAreaDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
|
||||||
|
val textArea = driver.findElement(By.id("textArea")) |
||||||
|
check(textArea.getAttribute("value") == "defaultTextAreaValue") |
||||||
|
|
||||||
|
textArea.sendKeys("-TypedText") |
||||||
|
|
||||||
|
val innerTextOfTextArea = driver.outerHtmlOfElementWithId("textArea") |
||||||
|
|
||||||
|
check(innerTextOfTextArea.contains(">defaultTextAreaValue</")) // inner text keeps default value |
||||||
|
check(textArea.getAttribute("value") == "defaultTextAreaValue-TypedText") // this checks the `value` property of the textarea |
||||||
|
check(textArea.getAttribute("data-text-area-value") == "defaultTextAreaValue-TypedText") |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun checkBoxDefaultCheckedRemainsTheSameButCheckedCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("checkBoxDefaultCheckedRemainsTheSameButCheckedCanBeChanged") |
||||||
|
|
||||||
|
val checkbox = driver.findElement(By.id("checkbox")) |
||||||
|
|
||||||
|
val innerTextOfCheckbox1 = driver.outerHtmlOfElementWithId("checkbox") |
||||||
|
check(innerTextOfCheckbox1.contains("checked")) |
||||||
|
check(checkbox.getAttribute("value") == "checkbox-value") |
||||||
|
check(checkbox.getAttribute("data-checkbox") == "true") |
||||||
|
check(checkbox.isSelected) |
||||||
|
|
||||||
|
checkbox.click() |
||||||
|
|
||||||
|
val innerTextOfCheckbox2 = driver.outerHtmlOfElementWithId("checkbox") |
||||||
|
check(innerTextOfCheckbox2.contains("checked")) |
||||||
|
check(checkbox.getAttribute("value") == "checkbox-value") |
||||||
|
check(checkbox.getAttribute("data-checkbox") == "false") |
||||||
|
check(!checkbox.isSelected) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun radioDefaultCheckedRemainsTheSameButCheckedCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("radioDefaultCheckedRemainsTheSameButCheckedCanBeChanged") |
||||||
|
|
||||||
|
val radio1 = driver.findElement(By.id("radio1")) |
||||||
|
val radio2 = driver.findElement(By.id("radio2")) |
||||||
|
|
||||||
|
check(radio1.isSelected) |
||||||
|
check(!radio2.isSelected) |
||||||
|
|
||||||
|
check(driver.outerHtmlOfElementWithId("radio1").contains("checked")) |
||||||
|
check(!driver.outerHtmlOfElementWithId("radio2").contains("checked")) |
||||||
|
|
||||||
|
radio2.click() |
||||||
|
|
||||||
|
check(!radio1.isSelected) |
||||||
|
check(radio2.isSelected) |
||||||
|
|
||||||
|
check(driver.outerHtmlOfElementWithId("radio1").contains("checked")) |
||||||
|
check(!driver.outerHtmlOfElementWithId("radio2").contains("checked")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun numberDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("numberDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "Value = None") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("numberInput")) |
||||||
|
check(numberInput.getAttribute("value") == "11") |
||||||
|
|
||||||
|
numberInput.sendKeys("5") |
||||||
|
driver.waitTextToBe(value = "Value = 511") |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "511") |
||||||
|
check(driver.outerHtmlOfElementWithId("numberInput").contains("value=\"11\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun rangeDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("rangeDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "Value = None") |
||||||
|
|
||||||
|
val numberInput = driver.findElement(By.id("rangeInput")) |
||||||
|
check(numberInput.getAttribute("value") == "7") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "Value = 8") |
||||||
|
|
||||||
|
numberInput.sendKeys(Keys.ARROW_RIGHT) |
||||||
|
driver.waitTextToBe(value = "Value = 9") |
||||||
|
|
||||||
|
check(numberInput.getAttribute("value") == "9") |
||||||
|
check(driver.outerHtmlOfElementWithId("rangeInput").contains("value=\"7\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun emailDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("emailDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "Value = None") |
||||||
|
|
||||||
|
val emailInput = driver.findElement(By.id("emailInput")) |
||||||
|
check(emailInput.getAttribute("value") == "a@a.abc") |
||||||
|
|
||||||
|
emailInput.clear() |
||||||
|
emailInput.sendKeys("u@u.com") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "Value = u@u.com") |
||||||
|
check(emailInput.getAttribute("value") == "u@u.com") |
||||||
|
|
||||||
|
check(driver.outerHtmlOfElementWithId("emailInput").contains("value=\"a@a.abc\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun passwordDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("passwordDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "Value = None") |
||||||
|
|
||||||
|
val passwordInput = driver.findElement(By.id("passwordInput")) |
||||||
|
check(passwordInput.getAttribute("value") == "1111") |
||||||
|
|
||||||
|
passwordInput.clear() |
||||||
|
passwordInput.sendKeys("a") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "Value = a") |
||||||
|
check(passwordInput.getAttribute("value") == "a") |
||||||
|
|
||||||
|
check(driver.outerHtmlOfElementWithId("passwordInput").contains("value=\"1111\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun searchDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("searchDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "Value = None") |
||||||
|
|
||||||
|
val searchInput = driver.findElement(By.id("searchInput")) |
||||||
|
check(searchInput.getAttribute("value") == "kotlin") |
||||||
|
|
||||||
|
searchInput.clear() |
||||||
|
searchInput.sendKeys("j") |
||||||
|
driver.waitTextToBe(value = "Value = j") |
||||||
|
|
||||||
|
check(searchInput.getAttribute("value") == "j") |
||||||
|
|
||||||
|
check(driver.outerHtmlOfElementWithId("searchInput").contains("value=\"kotlin\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun telDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("telDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val telInput = driver.findElement(By.id("telInput")) |
||||||
|
check(telInput.getAttribute("value") == "123123") |
||||||
|
|
||||||
|
telInput.clear() |
||||||
|
telInput.sendKeys("987654321") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "987654321") |
||||||
|
check(telInput.getAttribute("value") == "987654321") |
||||||
|
check(driver.outerHtmlOfElementWithId("telInput").contains("value=\"123123\"")) |
||||||
|
} |
||||||
|
|
||||||
|
@ResolveDrivers |
||||||
|
fun urlDefaultValueRemainsTheSameButValueCanBeChanged(driver: WebDriver) { |
||||||
|
driver.openTestPage("urlDefaultValueRemainsTheSameButValueCanBeChanged") |
||||||
|
driver.waitTextToBe(value = "None") |
||||||
|
|
||||||
|
val urlInput = driver.findElement(By.id("urlInput")) |
||||||
|
check(urlInput.getAttribute("value") == "www.site.com") |
||||||
|
|
||||||
|
urlInput.clear() |
||||||
|
urlInput.sendKeys("google.com") |
||||||
|
|
||||||
|
driver.waitTextToBe(value = "google.com") |
||||||
|
check(urlInput.getAttribute("value") == "google.com") |
||||||
|
check(driver.outerHtmlOfElementWithId("urlInput").contains("value=\"www.site.com\"")) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue