@@ -908,3 +908,319 @@ async def test_select_option_should_work_when_re_defining_top_level_event_class(
908
908
await page .selectOption ("select" , "blue" )
909
909
assert await page .evaluate ("result.onInput" ) == ["blue" ]
910
910
assert await page .evaluate ("result.onChange" ) == ["blue" ]
911
+
912
+
913
+ async def give_it_a_chance_to_fill (page ):
914
+ for i in range (5 ):
915
+ await page .evaluate (
916
+ "() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"
917
+ )
918
+
919
+
920
+ async def test_fill_should_fill_textarea (page , server ):
921
+ await page .goto (server .PREFIX + "/input/textarea.html" )
922
+ await page .fill ("textarea" , "some value" )
923
+ assert await page .evaluate ("result" ) == "some value"
924
+
925
+
926
+ @pytest .mark .skip_browser ("webkit" )
927
+ async def test_fill_should_fill_input (page , server ):
928
+ # Disabled as in upstream, we should validate time in the Playwright lib
929
+ await page .goto (server .PREFIX + "/input/textarea.html" )
930
+ await page .fill ("input" , "some value" )
931
+ assert await page .evaluate ("result" ) == "some value"
932
+
933
+
934
+ async def test_fill_should_throw_on_unsupported_inputs (page , server ):
935
+ await page .goto (server .PREFIX + "/input/textarea.html" )
936
+ for type in ["color" , "file" ]:
937
+ await page .evalOnSelector (
938
+ "input" , "(input, type) => input.setAttribute('type', type)" , type
939
+ )
940
+ with pytest .raises (Error ) as exc_info :
941
+ await page .fill ("input" , "" )
942
+ assert f'input of type "{ type } " cannot be filled' in exc_info .value .message
943
+
944
+
945
+ async def test_fill_should_fill_different_input_types (page , server ):
946
+ await page .goto (server .PREFIX + "/input/textarea.html" )
947
+ for type in ["password" , "search" , "tel" , "text" , "url" ]:
948
+ await page .evalOnSelector (
949
+ "input" , "(input, type) => input.setAttribute('type', type)" , type
950
+ )
951
+ await page .fill ("input" , "text " + type )
952
+ assert await page .evaluate ("result" ) == "text " + type
953
+
954
+
955
+ async def test_fill_should_fill_date_input_after_clicking (page , server ):
956
+ await page .setContent ("<input type=date>" )
957
+ await page .click ("input" )
958
+ await page .fill ("input" , "2020-03-02" )
959
+ assert await page .evalOnSelector ("input" , "input => input.value" ) == "2020-03-02"
960
+
961
+
962
+ @pytest .mark .skip_browser ("webkit" )
963
+ async def test_fill_should_throw_on_incorrect_date (page , server ):
964
+ # Disabled as in upstream, we should validate time in the Playwright lib
965
+ await page .setContent ("<input type=date>" )
966
+ with pytest .raises (Error ) as exc_info :
967
+ await page .fill ("input" , "2020-13-05" )
968
+ assert "Malformed value" in exc_info .value .message
969
+
970
+
971
+ async def test_fill_should_fill_time_input (page , server ):
972
+ await page .setContent ("<input type=time>" )
973
+ await page .fill ("input" , "13:15" )
974
+ assert await page .evalOnSelector ("input" , "input => input.value" ) == "13:15"
975
+
976
+
977
+ @pytest .mark .skip_browser ("webkit" )
978
+ async def test_fill_should_throw_on_incorrect_time (page , server ):
979
+ # Disabled as in upstream, we should validate time in the Playwright lib
980
+ await page .setContent ("<input type=time>" )
981
+ with pytest .raises (Error ) as exc_info :
982
+ await page .fill ("input" , "25:05" )
983
+ assert "Malformed value" in exc_info .value .message
984
+
985
+
986
+ async def test_fill_should_fill_datetime_local_input (page , server ):
987
+ await page .setContent ("<input type=datetime-local>" )
988
+ await page .fill ("input" , "2020-03-02T05:15" )
989
+ assert (
990
+ await page .evalOnSelector ("input" , "input => input.value" ) == "2020-03-02T05:15"
991
+ )
992
+
993
+
994
+ @pytest .mark .only_browser ("chromium" )
995
+ async def test_fill_should_throw_on_incorrect_datetime_local (page ):
996
+ await page .setContent ("<input type=datetime-local>" )
997
+ with pytest .raises (Error ) as exc_info :
998
+ await page .fill ("input" , "abc" )
999
+ assert "Malformed value" in exc_info .value .message
1000
+
1001
+
1002
+ async def test_fill_should_fill_contenteditable (page , server ):
1003
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1004
+ await page .fill ("div[contenteditable]" , "some value" )
1005
+ assert (
1006
+ await page .evalOnSelector ("div[contenteditable]" , "div => div.textContent" )
1007
+ == "some value"
1008
+ )
1009
+
1010
+
1011
+ async def test_fill_should_fill_elements_with_existing_value_and_selection (
1012
+ page , server
1013
+ ):
1014
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1015
+
1016
+ await page .evalOnSelector ("input" , "input => input.value = 'value one'" )
1017
+ await page .fill ("input" , "another value" )
1018
+ assert await page .evaluate ("result" ) == "another value"
1019
+
1020
+ await page .evalOnSelector (
1021
+ "input" ,
1022
+ """input => {
1023
+ input.selectionStart = 1
1024
+ input.selectionEnd = 2
1025
+ }""" ,
1026
+ )
1027
+
1028
+ await page .fill ("input" , "maybe this one" )
1029
+ assert await page .evaluate ("result" ) == "maybe this one"
1030
+
1031
+ await page .evalOnSelector (
1032
+ "div[contenteditable]" ,
1033
+ """div => {
1034
+ div.innerHTML = 'some text <span>some more text<span> and even more text'
1035
+ range = document.createRange()
1036
+ range.selectNodeContents(div.querySelector('span'))
1037
+ selection = window.getSelection()
1038
+ selection.removeAllRanges()
1039
+ selection.addRange(range)
1040
+ }""" ,
1041
+ )
1042
+
1043
+ await page .fill ("div[contenteditable]" , "replace with this" )
1044
+ assert (
1045
+ await page .evalOnSelector ("div[contenteditable]" , "div => div.textContent" )
1046
+ == "replace with this"
1047
+ )
1048
+
1049
+
1050
+ async def test_fill_should_throw_when_element_is_not_an_input_textarea_or_contenteditable (
1051
+ page , server
1052
+ ):
1053
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1054
+ with pytest .raises (Error ) as exc_info :
1055
+ await page .fill ("body" , "" )
1056
+ assert "Element is not an <input>" in exc_info .value .message
1057
+
1058
+
1059
+ async def test_fill_should_throw_if_passed_a_non_string_value (page , server ):
1060
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1061
+ with pytest .raises (Error ) as exc_info :
1062
+ await page .fill ("textarea" , 123 )
1063
+ assert "Value must be string." in exc_info .value .message
1064
+
1065
+
1066
+ async def test_fill_should_retry_on_disabled_element (page , server ):
1067
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1068
+ await page .evalOnSelector ("input" , "i => i.disabled = true" )
1069
+ done = []
1070
+
1071
+ async def fill ():
1072
+ await page .fill ("input" , "some value" )
1073
+ done .append (True )
1074
+
1075
+ promise = asyncio .ensure_future (fill ())
1076
+ await give_it_a_chance_to_fill (page )
1077
+ assert done == []
1078
+ assert await page .evaluate ("result" ) == ""
1079
+
1080
+ await page .evalOnSelector ("input" , "i => i.disabled = false" )
1081
+ await promise
1082
+ assert await page .evaluate ("result" ) == "some value"
1083
+
1084
+
1085
+ async def test_fill_should_retry_on_readonly_element (page , server ):
1086
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1087
+ await page .evalOnSelector ("textarea" , "i => i.readOnly = true" )
1088
+ done = []
1089
+
1090
+ async def fill ():
1091
+ await page .fill ("textarea" , "some value" )
1092
+ done .append (True )
1093
+
1094
+ promise = asyncio .ensure_future (fill ())
1095
+ await give_it_a_chance_to_fill (page )
1096
+ assert done == []
1097
+ assert await page .evaluate ("result" ) == ""
1098
+
1099
+ await page .evalOnSelector ("textarea" , "i => i.readOnly = false" )
1100
+ await promise
1101
+ assert await page .evaluate ("result" ) == "some value"
1102
+
1103
+
1104
+ async def test_fill_should_retry_on_invisible_element (page , server ):
1105
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1106
+ await page .evalOnSelector ("input" , "i => i.style.display = 'none'" )
1107
+ done = []
1108
+
1109
+ async def fill ():
1110
+ await page .fill ("input" , "some value" )
1111
+ done .append (True )
1112
+
1113
+ promise = asyncio .ensure_future (fill ())
1114
+ await give_it_a_chance_to_fill (page )
1115
+ assert done == []
1116
+ assert await page .evaluate ("result" ) == ""
1117
+
1118
+ await page .evalOnSelector ("input" , "i => i.style.display = 'inline'" )
1119
+ await promise
1120
+ assert await page .evaluate ("result" ) == "some value"
1121
+
1122
+
1123
+ async def test_fill_should_be_able_to_fill_the_body (page ):
1124
+ await page .setContent ('<body contentEditable="true"></body>' )
1125
+ await page .fill ("body" , "some value" )
1126
+ assert await page .evaluate ("document.body.textContent" ) == "some value"
1127
+
1128
+
1129
+ async def test_fill_should_fill_fixed_position_input (page ):
1130
+ await page .setContent ('<input style="position: fixed;" />' )
1131
+ await page .fill ("input" , "some value" )
1132
+ assert await page .evaluate ("document.querySelector('input').value" ) == "some value"
1133
+
1134
+
1135
+ async def test_fill_should_be_able_to_fill_when_focus_is_in_the_wrong_frame (page ):
1136
+ await page .setContent (
1137
+ """
1138
+ <div contentEditable="true"></div>
1139
+ <iframe></iframe>
1140
+ """
1141
+ )
1142
+ await page .focus ("iframe" )
1143
+ await page .fill ("div" , "some value" )
1144
+ assert await page .evalOnSelector ("div" , "d => d.textContent" ) == "some value"
1145
+
1146
+
1147
+ async def test_fill_should_be_able_to_fill_the_input_type_number_ (page ):
1148
+ await page .setContent ('<input id="input" type="number"></input>' )
1149
+ await page .fill ("input" , "42" )
1150
+ assert await page .evaluate ("input.value" ) == "42"
1151
+
1152
+
1153
+ async def test_fill_should_be_able_to_fill_exponent_into_the_input_type_number_ (page ):
1154
+ await page .setContent ('<input id="input" type="number"></input>' )
1155
+ await page .fill ("input" , "-10e5" )
1156
+ assert await page .evaluate ("input.value" ) == "-10e5"
1157
+
1158
+
1159
+ async def test_fill_should_be_able_to_fill_input_type_number__with_empty_string (page ):
1160
+ await page .setContent ('<input id="input" type="number" value="123"></input>' )
1161
+ await page .fill ("input" , "" )
1162
+ assert await page .evaluate ("input.value" ) == ""
1163
+
1164
+
1165
+ async def test_fill_should_not_be_able_to_fill_text_into_the_input_type_number_ (page ):
1166
+ await page .setContent ('<input id="input" type="number"></input>' )
1167
+ with pytest .raises (Error ) as exc_info :
1168
+ await page .fill ("input" , "abc" )
1169
+ assert "Cannot type text into input[type=number]" in exc_info .value .message
1170
+
1171
+
1172
+ async def test_fill_should_be_able_to_clear (page , server ):
1173
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1174
+ await page .fill ("input" , "some value" )
1175
+ assert await page .evaluate ("result" ) == "some value"
1176
+ await page .fill ("input" , "" )
1177
+ assert await page .evaluate ("result" ) == ""
1178
+
1179
+
1180
+ async def test_close_event_should_work_with_window_close (page , server ):
1181
+ promise = asyncio .ensure_future (page .waitForEvent ("popup" ))
1182
+ await page .evaluate ("window['newPage'] = window.open('about:blank')" )
1183
+ popup = await promise
1184
+ close_promise = asyncio .ensure_future (popup .waitForEvent ("close" ))
1185
+ await page .evaluate ("window['newPage'].close()" )
1186
+ await close_promise
1187
+
1188
+
1189
+ async def test_close_event_should_work_with_page_close (context , server ):
1190
+ page = await context .newPage ()
1191
+ close_promise = asyncio .ensure_future (page .waitForEvent ("close" ))
1192
+ await page .close ()
1193
+ await close_promise
1194
+
1195
+
1196
+ async def test_page_context_should_return_the_correct_browser_instance (page , context ):
1197
+ assert page .context == context
1198
+
1199
+
1200
+ async def test_frame_should_respect_name (page , server ):
1201
+ await page .setContent ("<iframe name=target></iframe>" )
1202
+ assert page .frame (name = "bogus" ) is None
1203
+ frame = page .frame (name = "target" )
1204
+ assert frame
1205
+ assert frame == page .mainFrame .childFrames [0 ]
1206
+
1207
+
1208
+ async def test_frame_should_respect_url (page , server ):
1209
+ await page .setContent (f'<iframe src="{ server .EMPTY_PAGE } "></iframe>' )
1210
+ assert page .frame (url = re .compile (r"bogus" )) is None
1211
+ assert page .frame (url = re .compile (r"empty" )).url == server .EMPTY_PAGE
1212
+
1213
+
1214
+ async def test_press_should_work (page , server ):
1215
+ await page .goto (server .PREFIX + "/input/textarea.html" )
1216
+ await page .press ("textarea" , "a" )
1217
+ assert await page .evaluate ("document.querySelector('textarea').value" ) == "a"
1218
+
1219
+
1220
+ async def test_frame_press_should_work (page , server ):
1221
+ await page .setContent (
1222
+ f'<iframe name=inner src="{ server .PREFIX } /input/textarea.html"></iframe>'
1223
+ )
1224
+ frame = page .frame ("inner" )
1225
+ await frame .press ("textarea" , "a" )
1226
+ assert await frame .evaluate ("document.querySelector('textarea').value" ) == "a"
0 commit comments