How to use validateProperties method in Playwright Internal

Best JavaScript code snippet using playwright-internal

FormValidator.1.0.min.js

Source:FormValidator.1.0.min.js Github

copy

Full Screen

1function hasClass(ele, cls) { return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")) }2function addClass(ele, cls) { if (!this.hasClass(ele, cls)) { ele.className += " " + cls } }3function removeClass(ele, cls) { if (hasClass(ele, cls)) { var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); ele.className = ele.className.replace(reg, " ") } }4var reInt = /^\s*[+-]?\d+\s*$/;//整数类型5var reUInt = /^\s*[+]?\d+\s*$/;//正整数类型6var DataType = {7 Int16: { Name: "Int16", MaxValue: 32767, MinValue: -32768, CheckRange: function (val) { return ((isFinite(val)) && (reInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },8 Int32: { Name: "Int32", MaxValue: 2147483647, MinValue: -2147483648, CheckRange: function (val) { return ((isFinite(val)) && (reInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },9 Int64: { Name: "Int64", MaxValue: 9223372036854776000, MinValue: -9223372036854776000, CheckRange: function (val) { return ((isFinite(val)) && (reInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },10 Float: { Name: "Float", MaxValue: 3.402823e+38, MinValue: -3.402823e+38, CheckRange: function (val) { return ((isFinite(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },11 Double: { Name: "Double", MaxValue: 1.79e+308, MinValue: -1.79e+308, CheckRange: function (val) { return ((isFinite(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },12 UInt16: { Name: "UInt16", MaxValue: 65535, MinValue: 1, CheckRange: function (val) { return ((isFinite(val)) && (reUInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },13 UInt32: { Name: "UInt32", MaxValue: 4294967295, MinValue: 1, CheckRange: function (val) { return ((isFinite(val)) && (reUInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },14 UInt64: { Name: "UInt64", MaxValue: 18446744073709552000, MinValue: 1, CheckRange: function (val) { return ((isFinite(val)) && (reUInt.test(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },15 UFloat: { Name: "UFloat", MaxValue: 3.402823E+38, MinValue: 0, CheckRange: function (val) { return ((isFinite(val)) && (this.MaxValue >= val) && (this.MinValue <= val)); } },16 UDouble: { Name: "Double", MaxValue: 1.79e+308, MinValue: 0, CheckRange: function (val) { return ((isFinite(val)) && (this.MaxValue >= val) && (this.MinValue <= val)) } },17 DateTime: { Name: "DateTime", MaxValue: new Date(9999, 12, 31, 23, 59, 59), MinValue: new Date(1, 1, 1, 0, 0, 0), CheckRange: function (val) { var temp = Date.parse(val); return ((!isNaN(temp)) && (this.MaxValue >= temp) && (this.MinValue <= temp)) } },18 String: { Name: "String", IsNullOrEmpty: function (val) { return ((val == null) || (val == "")) }, IsNullOrWhiteSpace: function (val) { return (val == null) || /^\s*$/.test(val) }, Trim: function (val) { if (val != null) { return val.replace(/(^\s*)|(\s*$)/g, "") } return val } }19};20//获取最近父类节点21function GetClosestElement(obj, tagName) {22 if (DataType.String.IsNullOrWhiteSpace(tagName)) {23 throw "tagName 不能为空!"24 }25 tagName = tagName.toUpperCase();26 var node = obj.parentNode;27 while (node != null) {28 if ((node == null) || (node.tagName == tagName)) {29 break;30 }31 node = node.parentNode;32 }33 return node;34}35//获取子节点(根据name属性和tagName标签类型)36function GetElementsByNameAndTagName(container, name, tagName) {37 var lst = new Array();38 var eles = container.getElementsByTagName(tagName);39 for (var i = 0; i < eles.length; i++) {40 if (eles[i].name == name) {41 lst.push(eles[i]);42 }43 }44 return lst;45}46// 获取长度47function GetLength(obj) {48 var length = 0;49 switch (obj.type) {50 case "checkbox":51 case "radio":52 var form = GetClosestElement(obj, "FORM");53 var nodes = null;54 if (form != null) {55 nodes = GetElementsByNameAndTagName(form, obj.name, obj.tagName);56 }57 else {58 nodes = document.getElementsByName(obj.name);59 }60 if ((nodes != null) && (nodes.length > 0)) {61 for (var i = 0; i < nodes.length; i++) {62 if (nodes[i].checked) {63 length++;64 }65 }66 }67 break;68 case "select-one":69 case "select-multiple":70 for (var i = 0; i < obj.options.length; i++) {71 if (obj.options[i].selected) {72 length++;73 }74 }75 break;76 default:77 length = obj.value.length;78 break;79 }80 return length;81};82//表单验证css类83var ValidateCssClass = {84 Succeed: "validate-succeed",85 Error: "validate-error",86 Info: "validate-info"87};88//表单验证属性89var ValidateProperties = {90 CanEmpty: "fv-empty", //fv-empty="false",表示不能为空91 DataType: "fv-datatype",// 数据类型92 Custom: "fv-custom",//自定义验证函数93 Format: "fv-format",//格式化94 MaxValue: "fv-maxvalue",//最大值95 MinValue: "fv-minvalue",//最小值96 MaxLength: "fv-maxlength",//最长长度97 MinLength: "fv-minlength",//值最小长度98 Ajax: "fv-ajax",//ajax验证99 CompareTo: "fv-compareto",//比较验证属性格式:fv-compareto=">,id1,id2,id3" >为表达式,可选的表达式有:> < >= <= != =(大于,小于,大于等于,小于等于,不等于,等于)100 MsgPanel: "fv-msgpanel",//消息显示控件的id101 MsgInfo: "fv-msg-info",//用于显示默认消息(为msgpanel静态文本)102 MsgSuccess: "fv-msg-success",//验证成功消息,如果不填写,将采用默认静态消息显示(原msgpanel内容)103 MsgError: "fv-msg-error",//验证失败默认错误消息104 Validate: "fv-validate"//用于form元素上,fv-validate="true"表示此表单参与验证105}106//属性格式为:属性名="属性值|错误提示信息" 属性和信息,用|隔开107function ValidateConfig(val, msg) {108 this.Message = msg;109 this.Value = val;110}111//验证表单112function FormValidator(form) {113 this.Body = form;114}115//初始化表单验证116FormValidator.prototype.Init = function () {117 var salf = this;118 //拦截form提交事件,可能出现重复两次验证。119 //因为form.submit()方法,不会触发onsubmit事件。120 //而input type="submit"会触发内部submit方法,并直接提交。除非在onsubmit中,返回false。121 //故此会提交两次验证。可以通过代码标记实现,保证验证一次。但是麻烦。我喜欢代码简单点。两次验证不什么影响。 122 var onsubmit = salf.Body.onsubmit;123 if (onsubmit == null) {124 salf.Body.onsubmit = function () { return salf.Validate(); };125 }126 else {127 salf.Body.onsubmit = function () { return salf.Validate() && onsubmit(); };128 }129 //*130 if ((typeof (salf.Body.submit) == 'function' || (!salf.Body.submit.tagName && !salf.Body.submit.length))) {131 salf.Body.originalSubmit = salf.Body.submit;132 salf.Body.submit = function () {133 if (salf.Validate()) {134 salf.Body.originalSubmit();135 }136 }137 }138 //*/139 var inputItems = salf.Body.getElementsByTagName("input");140 var selectItems = salf.Body.getElementsByTagName("select");141 var textareaItems = salf.Body.getElementsByTagName("textarea");142 if ((inputItems != null) && (inputItems.length > 0)) {143 for (var i = 0; i < inputItems.length; i++) {144 if ((inputItems[i].type != "submit") && (inputItems[i].type != "button") && (inputItems[i].type != "reset")) {145 (new ElementValidator(inputItems[i])).Init();146 }147 }148 }149 if ((selectItems != null) && (selectItems.length > 0)) {150 for (var i = 0; i < selectItems.length; i++) {151 (new ElementValidator(selectItems[i])).Init();152 }153 }154 if ((textareaItems != null) && (textareaItems.length > 0)) {155 for (var i = 0; i < textareaItems.length; i++) {156 (new ElementValidator(textareaItems[i])).Init();157 }158 }159}160//显示属性信息,如果msg不为空,显示msg,如果msg为空,显示总的msg,如果总的msg为空,显示预定义msg161FormValidator.prototype.ShowMessage = function (msg, className) {162 var msgPenelId = this.Body.getAttribute(ValidateProperties.MsgPanel);163 var msgpanel = null;164 if (!DataType.String.IsNullOrWhiteSpace(msgPenelId)) {165 msgpanel = document.getElementById(msgPenelId);166 }167 if (msgpanel != null) {168 if (msgpanel.getAttribute(ValidateProperties.MsgInfo) == null) {169 //保存默认消息,用于验证后,没有设置验证失败消息,也没有设置fv-message的情况。170 msgpanel.setAttribute(ValidateProperties.MsgInfo, msgpanel.innerHTML);171 }172 if (DataType.String.IsNullOrWhiteSpace(msg)) {173 msg = msgpanel.getAttribute(ValidateProperties.MsgInfo);174 }175 msgpanel.innerHTML = msg;176 msgpanel.className = className;177 if (DataType.String.IsNullOrWhiteSpace(msg)) {178 msgpanel.style.visibility = "hidden";179 }180 else {181 msgpanel.style.visibility = "visible";182 }183 }184 else {185 if (!DataType.String.IsNullOrWhiteSpace(msg)) {186 alert(msg);187 }188 }189};190//设置验证状态191FormValidator.prototype.SetValidateStatus = function (validateResult) {192 var className = null;193 if (validateResult == true) {194 removeClass(this.Body, ValidateCssClass.Error);195 removeClass(this.Body, ValidateCssClass.Info);196 className = ValidateCssClass.Succeed;197 msg = this.Body.getAttribute(ValidateProperties.MsgSuccess);198 }199 else if (validateResult == false) {200 removeClass(this.Body, ValidateCssClass.Succeed);201 removeClass(this.Body, ValidateCssClass.Info);202 className = ValidateCssClass.Error;203 msg = this.Body.getAttribute(ValidateProperties.MsgError);204 }205 else {206 removeClass(this.Body, ValidateCssClass.Succeed);207 removeClass(this.Body, ValidateCssClass.Error);208 className = ValidateCssClass.Info;209 msg = null;210 }211 addClass(this.Body, className);212 this.ShowMessage(msg, className);213};214//验证函数215//html属性 fv-validate="true"216FormValidator.prototype.Validate = function () {217 var inputItems = this.Body.getElementsByTagName("input");218 var selectItems = this.Body.getElementsByTagName("select");219 var textareaItems = this.Body.getElementsByTagName("textarea");220 var chk = true;221 if ((inputItems != null) && (inputItems.length > 0)) {222 for (var i = 0; i < inputItems.length; i++) {223 if ((inputItems[i].type != "submit") && (inputItems[i].type != "button") && (inputItems[i].type != "reset")) {224 chk = (new ElementValidator(inputItems[i])).Validate() && chk;225 }226 }227 }228 if ((selectItems != null) && (selectItems.length > 0)) {229 for (var i = 0; i < selectItems.length; i++) {230 chk = (new ElementValidator(selectItems[i])).Validate() && chk;231 }232 }233 if ((textareaItems != null) && (textareaItems.length > 0)) {234 for (var i = 0; i < textareaItems.length; i++) {235 chk = (new ElementValidator(textareaItems[i])).Validate() && chk;236 }237 }238 this.SetValidateStatus(chk);239 return chk;240};241//验证控件,一般为:input(text, radio, checkbox),select, textarea242function ElementValidator(element) {243 this.Body = element;244}245ElementValidator.prototype.Init = function () {246 var salf = this;247 salf.Body.onblur = function () {248 salf.Validate();249 }250}251//验证函数252//html属性 FV-Validate="true"253ElementValidator.prototype.Validate = function () {254 return this.CheckEmpty() && this.CheckAjax() && this.CheckDataType() && this.CheckFormat() && this.CheckMaxLength() && this.CheckMinLength() && this.CheckMaxValue() && this.CheckMinValue() && this.CheckCompareTo() && this.CheckCustom();255};256//验证值是否为空257//html属性 FV-Empty="false"258ElementValidator.prototype.CheckEmpty = function () {259 var chk = true;260 var config = this.GetValidateConfig(ValidateProperties.CanEmpty);261 if ((config != null) && (config.Value == "false")) {262 chk = !DataType.String.IsNullOrWhiteSpace(this.Body.value)263 this.SetValidateStatus(chk, config.Message);264 }265 return chk;266};267//验证格式化268//html属性 FV-Format="正则表达式"269ElementValidator.prototype.CheckFormat = function () {270 var chk = true;271 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {272 var config = this.GetValidateConfig(ValidateProperties.Format);273 if (config != null) {274 chk = (new RegExp(config.Value)).test(this.Body.value);275 this.SetValidateStatus(chk, config.Message);276 }277 }278 else {279 this.SetValidateStatus(null, null);280 }281 return chk;282}283//验证最小长度284//html属性 FV-MinLength="false"285ElementValidator.prototype.CheckMinLength = function () {286 var chk = true;287 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {288 var config = this.GetValidateConfig(ValidateProperties.MinLength);289 if (config != null) {290 chk = GetLength(this.Body) >= parseInt(config.Value);291 this.SetValidateStatus(chk, config.Message);292 }293 }294 else {295 this.SetValidateStatus(null, null);296 }297 return chk;298};299//验证最大长度300ElementValidator.prototype.CheckMaxLength = function () {301 var chk = true;302 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {303 var config = this.GetValidateConfig(ValidateProperties.MaxLength);304 if (config != null) {305 chk = GetLength(this.Body) <= parseInt(config.Value);306 this.SetValidateStatus(chk, config.Message);307 }308 }309 else {310 this.SetValidateStatus(null, null);311 }312 return chk;313};314//验证数据类型315ElementValidator.prototype.CheckDataType = function () {316 var chk = true;317 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {318 var config = this.GetValidateConfig(ValidateProperties.DataType);319 if (config != null) {320 var type = config.Value;321 if (type == DataType.String.Name) {322 chk = true;323 }324 else if (DataType.hasOwnProperty(type)) {325 chk = DataType[type].CheckRange(this.Body.value);326 }327 else {328 alert("data type not define:" + type);329 throw "dta type not define!";330 }331 this.SetValidateStatus(chk, config.Message);332 }333 }334 else {335 this.SetValidateStatus(null, null);336 }337 return chk;338}339//验证最小值340ElementValidator.prototype.CheckMinValue = function () {341 var chk = true;342 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {343 var config = this.GetValidateConfig(ValidateProperties.MinValue);344 if (config != null) {345 if (isFinite(config.Value)) {346 var num1 = parseFloat(config.Value);347 var num2 = parseFloat(this.Body.value);348 chk = (num2 >= num1);349 }350 else {351 chk = (this.Body.value <= config.Value);352 }353 this.SetValidateStatus(chk, config.Message);354 }355 }356 else {357 this.SetValidateStatus(null, null);358 }359 return chk;360};361//验证最大值362ElementValidator.prototype.CheckMaxValue = function () {363 var chk = true;364 if (!DataType.String.IsNullOrEmpty(this.Body.value)) {365 var config = this.GetValidateConfig(ValidateProperties.MaxValue);366 if (config != null) {367 if (isFinite(config.Value)) {368 var num1 = parseFloat(config.Value);369 var num2 = parseFloat(this.Body.value);370 chk = (num2 <= num1);371 }372 else {373 chk = (this.Body.value <= config.Value);374 }375 this.SetValidateStatus(chk, config.Message);376 }377 }378 else {379 this.SetValidateStatus(null, null);380 }381 return chk;382};383// 返回值:-1 0 1, 表示小于,等于,大于384// -1, val1 < val2385// 0, val1 == val2386// 1, val1 > val2387function Compare(val1, val2) {388 var retval = 0;389 if ((val1 == null) && (val2 == null)) {390 retval = 0391 }392 else {393 if (val1 == null) {394 retval = -1;395 }396 else if (val2 == null) {397 retval = 1;398 }399 else {400 if (DataType.String.IsNullOrWhiteSpace(val1) || DataType.String.IsNullOrWhiteSpace(val2)) {401 val1 = val1.toString();402 val2 = val2.toString();403 }404 else {405 if ((!isNaN(val1)) && (!isNaN(val2))) {406 val1 = parseFloat(val1);407 val2 = parseFloat(val2);408 }409 }410 if (val1 == val2) {411 retval = 0;412 }413 else if (val1 < val2) {414 retval = -1;415 }416 else {417 retval = 1;418 }419 }420 }421 return retval;422}423//验证比较,比较验证属性格式:fv-compareto=">,id1,id2,id3"424ElementValidator.prototype.CheckCompareTo = function () {425 var chk = true;426 var config = this.GetValidateConfig(ValidateProperties.CompareTo);427 if (config != null) {428 var arr = config.Value.split("|");429 for (var j = 0; j < arr.length; j++) {430 var ids = arr[j].split(",");431 if ((ids != null) && (ids.length > 1)) {432 var op = DataType.String.Trim(ids[0]);433 switch (op) {434 case "==":435 for (var i = 1; i < ids.length; i++) {436 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) == 0);437 if (!chk) {438 break;439 }440 }441 break;442 case ">":443 for (var i = 1; i < ids.length; i++) {444 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) == 1);445 if (!chk) {446 break;447 }448 }449 break;450 case "<":451 for (var i = 1; i < ids.length; i++) {452 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) == -1);453 if (!chk) {454 break;455 }456 }457 break;458 case ">=":459 for (var i = 1; i < ids.length; i++) {460 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) >= 0);461 if (!chk) {462 break;463 }464 }465 break;466 case "<=":467 for (var i = 1; i < ids.length; i++) {468 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) <= 0);469 if (!chk) {470 break;471 }472 }473 break;474 case "!=":475 for (var i = 1; i < ids.length; i++) {476 chk = chk && (Compare(this.Body.value, document.getElementById(ids[i]).value) != 0);477 if (!chk) {478 break;479 }480 }481 break;482 default:483 throw "比较表达式有误!"484 break;485 }486 }487 else {488 throw "比较控件值验证设置,至少需要添加一个待比较控件的id,多个id用逗号(,)隔开。";489 }490 if (!chk) {491 this.SetValidateStatus(chk, config.Message);492 return false;493 }494 }495 this.SetValidateStatus(chk, config.Message);496 }497 return chk;498};499//验证Ajax500ElementValidator.prototype.CheckAjax = function () {501 //设置等待ajax验证502 //当提交要结束表单验证的时候,查看此状态。如果此状态还是pendding状态,则等待503 return true;504}505//验证自定义函数506ElementValidator.prototype.CheckCustom = function () {507 var chk = true;508 var config = this.GetValidateConfig(ValidateProperties.Custom);509 if (config != null) {510 chk = eval(config.Value + "()");511 this.SetValidateStatus(chk, config.Message);512 }513 return chk;514};515//获取验证属性配置516ElementValidator.prototype.GetValidateConfig = function (propertyName) {517 var val = this.Body.getAttribute(propertyName);518 if (DataType.String.IsNullOrWhiteSpace(val)) {519 return null;520 }521 else {522 return new ValidateConfig(val, this.Body.getAttribute(propertyName + "-msg"));523 }524}525//显示属性信息,如果msg不为空,显示msg,如果msg为空,显示总的msg,如果总的msg为空,显示预定义msg526ElementValidator.prototype.ShowMessage = function (msg, className) {527 var msgPanelId = this.Body.getAttribute(ValidateProperties.MsgPanel);528 if (msgPanelId != null) {529 var msgpanel = document.getElementById(msgPanelId);530 if (msgpanel != null) {531 if (msgpanel.getAttribute(ValidateProperties.MsgInfo) == null) {532 //保存默认消息,用于验证后,没有设置验证失败消息,也没有设置fv-message的情况。533 msgpanel.setAttribute(ValidateProperties.MsgInfo, msgpanel.innerHTML);534 }535 if (DataType.String.IsNullOrWhiteSpace(msg)) {536 msg = msgpanel.getAttribute(ValidateProperties.MsgInfo);537 }538 msgpanel.innerHTML = msg;539 msgpanel.className = className;540 if (DataType.String.IsNullOrWhiteSpace(msg)) {541 msgpanel.style.visibility = "hidden";542 }543 else {544 msgpanel.style.visibility = "visible";545 }546 }547 }548};549//设置验证状态550ElementValidator.prototype.SetValidateStatus = function (validateResult, msg) {551 var className = null;552 if (validateResult == true) {553 removeClass(this.Body, ValidateCssClass.Error);554 removeClass(this.Body, ValidateCssClass.Info);555 className = ValidateCssClass.Succeed;556 msg = this.Body.getAttribute(ValidateProperties.MsgSuccess);557 }558 else if (validateResult == false) {559 removeClass(this.Body, ValidateCssClass.Succeed);560 removeClass(this.Body, ValidateCssClass.Info);561 className = ValidateCssClass.Error;562 if (DataType.String.IsNullOrEmpty(msg)) {563 msg = this.Body.getAttribute(ValidateProperties.MsgError);564 }565 }566 else {567 removeClass(this.Body, ValidateCssClass.Succeed);568 removeClass(this.Body, ValidateCssClass.Error);569 className = ValidateCssClass.Info;570 msg = null;571 }572 addClass(this.Body, className);573 this.ShowMessage(msg, className);574};575function FormValidateInit() {576 var forms = document.getElementsByTagName("FORM");577 for (var i = 0; i < forms.length; i++) {578 if (forms[i].getAttribute(ValidateProperties.Validate) == "true") {579 new FormValidator(forms[i]).Init();580 }581 }582}583//以下代码,来自网络copy来用的。584// 如果支持 W3C DOM2, 则使用 W3C 方法 585if (document.addEventListener) {586 document.addEventListener("DOMContentLoaded", FormValidateInit, false);587}588else if (/MSIE/i.test(navigator.userAgent)) {// 如果是 IE 浏览器589 // 创建一个 script 标签, 该标签有 defer 属性, 当 document 加载完毕时才会被载入 590 document.write('<script id="__ie_onloadfix" defer src="javascript:void(0)"></script>');591 var script = document.getElementById("__ie_onloadfix");592 // 如果文档确实装载完毕, 调用初始化方法 593 script.onreadystatechange = function () {594 if (this.readyState == 'complete') {595 FormValidateInit();596 }597 }598 // 如果是 Safari 浏览器 599}600else if (/WebKit/i.test(navigator.userAgent)) {601 // 创建定时器, 每 0.1 秒检验一次, 如果文档装载完毕则调用初始化方法 602 var _timer = setInterval(function () {603 if (/loaded|complete/.test(document.readyState)) {604 clearInterval(_timer);605 FormValidateInit();606 }607 }, 100);608}609else {610 // 如果以上皆不是, 使用最坏的方法 (本例中, Opera 7 将会跑到这里来) 611 window.onload = function (e) {612 FormValidateInit();613 }...

Full Screen

Full Screen

actions.js

Source:actions.js Github

copy

Full Screen

1import TYPE from './type';2import SelectorBuilder from '../../client-functions/selectors/selector-builder';3import ClientFunctionBuilder from '../../client-functions/client-function-builder';4import functionBuilderSymbol from '../../client-functions/builder-symbol';5import { ActionCommandBase, CommandBase } from './base';6import {7 ActionOptions,8 ClickOptions,9 MouseOptions,10 TypeOptions,11 PressOptions,12 DragToElementOptions,13 OffsetOptions,14 CookieOptions,15} from './options';16import { initSelector, initUploadSelector } from './validations/initializers';17import { executeJsExpression } from '../execute-js-expression';18import { isJSExpression } from './utils';19import {20 actionOptions,21 integerArgument,22 positiveIntegerArgument,23 stringArgument,24 nonEmptyStringArgument,25 nullableStringArgument,26 urlArgument,27 stringOrStringArrayArgument,28 setSpeedArgument,29 actionRoleArgument,30 booleanArgument,31 functionArgument,32 cookiesArgument,33 setCookiesArgument,34 urlsArgument,35} from './validations/argument';36import { SetNativeDialogHandlerCodeWrongTypeError } from '../../errors/test-run';37import { ExecuteClientFunctionCommand } from './observation';38import { camelCase } from 'lodash';39// Initializers40function initActionOptions (name, val, initOptions, validate = true) {41 return new ActionOptions(val, validate);42}43function initClickOptions (name, val, initOptions, validate = true) {44 return new ClickOptions(val, validate);45}46function initMouseOptions (name, val, initOptions, validate = true) {47 return new MouseOptions(val, validate);48}49function initOffsetOptions (name, val, initOptions, validate = true) {50 return new OffsetOptions(val, validate);51}52function initTypeOptions (name, val, initOptions, validate = true) {53 return new TypeOptions(val, validate);54}55function initDragToElementOptions (name, val, initOptions, validate = true) {56 return new DragToElementOptions(val, validate);57}58function initPressOptions (name, val, initOptions, validate = true) {59 return new PressOptions(val, validate);60}61function initDialogHandler (name, val, { skipVisibilityCheck, testRun }) {62 let fn;63 if (isJSExpression(val))64 fn = executeJsExpression(val.value, testRun, { skipVisibilityCheck });65 else66 fn = val.fn;67 if (fn === null || fn instanceof ExecuteClientFunctionCommand)68 return fn;69 const options = val.options;70 const methodName = 'setNativeDialogHandler';71 const functionType = typeof fn;72 let builder = fn && fn[functionBuilderSymbol];73 const isSelector = builder instanceof SelectorBuilder;74 const isClientFunction = builder instanceof ClientFunctionBuilder;75 if (functionType !== 'function' || isSelector)76 throw new SetNativeDialogHandlerCodeWrongTypeError(isSelector ? 'Selector' : functionType);77 if (isClientFunction)78 builder = fn.with(options)[functionBuilderSymbol];79 else80 builder = new ClientFunctionBuilder(fn, options, { instantiation: methodName, execution: methodName });81 return builder.getCommand([]);82}83function initCookiesOption (name, val, initOptions, validate = true) {84 return val.map(cookie => new CookieOptions(cookie, validate));85}86// Commands87export class DispatchEventCommand extends ActionCommandBase {88 static methodName = camelCase(TYPE.dispatchEvent);89 constructor (obj, testRun, validateProperties) {90 super(obj, testRun, TYPE.dispatchEvent, validateProperties);91 }92 _getAssignableProperties () {93 return [94 { name: 'selector', init: initSelector, required: true },95 { name: 'eventName', type: nonEmptyStringArgument, required: true },96 { name: 'options', type: actionOptions },97 { name: 'relatedTarget', init: initSelector, required: false },98 ];99 }100}101export class ClickCommand extends ActionCommandBase {102 static methodName = camelCase(TYPE.click);103 constructor (obj, testRun, validateProperties) {104 super(obj, testRun, TYPE.click, validateProperties);105 }106 _getAssignableProperties () {107 return [108 { name: 'selector', init: initSelector, required: true },109 { name: 'options', type: actionOptions, init: initClickOptions, required: true },110 ];111 }112}113export class RightClickCommand extends ActionCommandBase {114 static methodName = camelCase(TYPE.rightClick);115 constructor (obj, testRun, validateProperties) {116 super(obj, testRun, TYPE.rightClick, validateProperties);117 }118 _getAssignableProperties () {119 return [120 { name: 'selector', init: initSelector, required: true },121 { name: 'options', type: actionOptions, init: initClickOptions, required: true },122 ];123 }124}125export class ExecuteExpressionCommand extends CommandBase {126 constructor (obj, testRun, validateProperties) {127 super(obj, testRun, TYPE.executeExpression, validateProperties);128 }129 _getAssignableProperties () {130 return [131 { name: 'expression', type: nonEmptyStringArgument, required: true },132 { name: 'resultVariableName', type: nonEmptyStringArgument, defaultValue: null },133 ];134 }135}136export class ExecuteAsyncExpressionCommand extends CommandBase {137 constructor (obj, testRun, validateProperties) {138 super(obj, testRun, TYPE.executeAsyncExpression, validateProperties);139 }140 _getAssignableProperties () {141 return [142 { name: 'expression', type: stringArgument, required: true },143 ];144 }145}146export class DoubleClickCommand extends ActionCommandBase {147 static methodName = camelCase(TYPE.doubleClick);148 constructor (obj, testRun, validateProperties) {149 super(obj, testRun, TYPE.doubleClick, validateProperties);150 }151 _getAssignableProperties () {152 return [153 { name: 'selector', init: initSelector, required: true },154 { name: 'options', type: actionOptions, init: initClickOptions, required: true },155 ];156 }157}158export class HoverCommand extends ActionCommandBase {159 static methodName = camelCase(TYPE.hover);160 constructor (obj, testRun, validateProperties) {161 super(obj, testRun, TYPE.hover, validateProperties);162 }163 _getAssignableProperties () {164 return [165 { name: 'selector', init: initSelector, required: true },166 { name: 'options', type: actionOptions, init: initMouseOptions, required: true },167 ];168 }169}170export class TypeTextCommand extends ActionCommandBase {171 static methodName = camelCase(TYPE.typeText);172 constructor (obj, testRun, validateProperties) {173 super(obj, testRun, TYPE.typeText, validateProperties);174 }175 _getAssignableProperties () {176 return [177 { name: 'selector', init: initSelector, required: true },178 { name: 'text', type: nonEmptyStringArgument, required: true },179 { name: 'options', type: actionOptions, init: initTypeOptions, required: true },180 ];181 }182}183export class DragCommand extends ActionCommandBase {184 static methodName = camelCase(TYPE.drag);185 constructor (obj, testRun, validateProperties) {186 super(obj, testRun, TYPE.drag, validateProperties);187 }188 _getAssignableProperties () {189 return [190 { name: 'selector', init: initSelector, required: true },191 { name: 'dragOffsetX', type: integerArgument, required: true },192 { name: 'dragOffsetY', type: integerArgument, required: true },193 { name: 'options', type: actionOptions, init: initMouseOptions, required: true },194 ];195 }196}197export class DragToElementCommand extends ActionCommandBase {198 static methodName = camelCase(TYPE.dragToElement);199 constructor (obj, testRun, validateProperties) {200 super(obj, testRun, TYPE.dragToElement, validateProperties);201 }202 _getAssignableProperties () {203 return [204 { name: 'selector', init: initSelector, required: true },205 { name: 'destinationSelector', init: initSelector, required: true },206 { name: 'options', type: actionOptions, init: initDragToElementOptions, required: true },207 ];208 }209}210export class ScrollCommand extends ActionCommandBase {211 static methodName = camelCase(TYPE.scroll);212 constructor (obj, testRun, validateProperties) {213 super(obj, testRun, TYPE.scroll, validateProperties);214 }215 _getAssignableProperties () {216 return [217 { name: 'selector', init: initSelector, required: false },218 { name: 'position', type: nullableStringArgument, required: false },219 { name: 'x', type: positiveIntegerArgument, defaultValue: null },220 { name: 'y', type: positiveIntegerArgument, defaultValue: null },221 { name: 'options', type: actionOptions, init: initOffsetOptions, required: true },222 ];223 }224}225export class ScrollByCommand extends ActionCommandBase {226 static methodName = camelCase(TYPE.scrollBy);227 constructor (obj, testRun, validateProperties) {228 super(obj, testRun, TYPE.scrollBy, validateProperties);229 }230 _getAssignableProperties () {231 return [232 { name: 'selector', init: initSelector, required: false },233 { name: 'byX', type: integerArgument, defaultValue: 0 },234 { name: 'byY', type: integerArgument, defaultValue: 0 },235 { name: 'options', type: actionOptions, init: initOffsetOptions, required: true },236 ];237 }238}239export class ScrollIntoViewCommand extends ActionCommandBase {240 static methodName = camelCase(TYPE.scrollIntoView);241 constructor (obj, testRun, validateProperties) {242 super(obj, testRun, TYPE.scrollIntoView, validateProperties);243 }244 _getAssignableProperties () {245 return [246 { name: 'selector', init: initSelector, required: true },247 { name: 'options', type: actionOptions, init: initOffsetOptions, required: true },248 ];249 }250}251export class SelectTextCommand extends ActionCommandBase {252 static methodName = camelCase(TYPE.selectText);253 constructor (obj, testRun, validateProperties) {254 super(obj, testRun, TYPE.selectText, validateProperties);255 }256 _getAssignableProperties () {257 return [258 { name: 'selector', init: initSelector, required: true },259 { name: 'startPos', type: positiveIntegerArgument, defaultValue: null },260 { name: 'endPos', type: positiveIntegerArgument, defaultValue: null },261 { name: 'options', type: actionOptions, init: initActionOptions, required: true },262 ];263 }264}265export class SelectEditableContentCommand extends ActionCommandBase {266 static methodName = camelCase(TYPE.selectEditableContent);267 constructor (obj, testRun, validateProperties) {268 super(obj, testRun, TYPE.selectEditableContent, validateProperties);269 }270 _getAssignableProperties () {271 return [272 { name: 'startSelector', init: initSelector, required: true },273 { name: 'endSelector', init: initSelector, defaultValue: null },274 { name: 'options', type: actionOptions, init: initActionOptions, required: true },275 ];276 }277}278export class SelectTextAreaContentCommand extends ActionCommandBase {279 static methodName = camelCase(TYPE.selectTextAreaContent);280 constructor (obj, testRun, validateProperties) {281 super(obj, testRun, TYPE.selectTextAreaContent, validateProperties);282 }283 _getAssignableProperties () {284 return [285 { name: 'selector', init: initSelector, required: true },286 { name: 'startLine', type: positiveIntegerArgument, defaultValue: null },287 { name: 'startPos', type: positiveIntegerArgument, defaultValue: null },288 { name: 'endLine', type: positiveIntegerArgument, defaultValue: null },289 { name: 'endPos', type: positiveIntegerArgument, defaultValue: null },290 { name: 'options', type: actionOptions, init: initActionOptions, required: true },291 ];292 }293}294export class PressKeyCommand extends ActionCommandBase {295 static methodName = camelCase(TYPE.pressKey);296 constructor (obj, testRun, validateProperties) {297 super(obj, testRun, TYPE.pressKey, validateProperties);298 }299 _getAssignableProperties () {300 return [301 { name: 'keys', type: nonEmptyStringArgument, required: true },302 { name: 'options', type: actionOptions, init: initPressOptions, required: true },303 ];304 }305}306export class NavigateToCommand extends ActionCommandBase {307 static methodName = camelCase(TYPE.navigateTo);308 constructor (obj, testRun, validateProperties) {309 super(obj, testRun, TYPE.navigateTo, validateProperties);310 }311 _getAssignableProperties () {312 return [313 { name: 'url', type: urlArgument, required: true },314 { name: 'stateSnapshot', type: nullableStringArgument, defaultValue: null },315 { name: 'forceReload', type: booleanArgument, defaultValue: false },316 ];317 }318}319export class SetFilesToUploadCommand extends ActionCommandBase {320 static methodName = camelCase(TYPE.setFilesToUpload);321 constructor (obj, testRun, validateProperties) {322 super(obj, testRun, TYPE.setFilesToUpload, validateProperties);323 }324 _getAssignableProperties () {325 return [326 { name: 'selector', init: initUploadSelector, required: true },327 { name: 'filePath', type: stringOrStringArrayArgument, required: true },328 ];329 }330}331export class ClearUploadCommand extends ActionCommandBase {332 static methodName = camelCase(TYPE.clearUpload);333 constructor (obj, testRun, validateProperties) {334 super(obj, testRun, TYPE.clearUpload, validateProperties);335 }336 _getAssignableProperties () {337 return [338 { name: 'selector', init: initUploadSelector, required: true },339 ];340 }341}342export class SwitchToIframeCommand extends ActionCommandBase {343 static methodName = camelCase(TYPE.switchToIframe);344 constructor (obj, testRun, validateProperties) {345 super(obj, testRun, TYPE.switchToIframe, validateProperties);346 }347 _getAssignableProperties () {348 return [349 { name: 'selector', init: initSelector, required: true },350 ];351 }352}353export class SwitchToMainWindowCommand extends ActionCommandBase {354 static methodName = camelCase(TYPE.switchToMainWindow);355 constructor () {356 super();357 this.type = TYPE.switchToMainWindow;358 }359}360export class OpenWindowCommand extends ActionCommandBase {361 static methodName = camelCase(TYPE.openWindow);362 constructor (obj, testRun, validateProperties) {363 super(obj, testRun, TYPE.openWindow, validateProperties);364 }365 _getAssignableProperties () {366 return [367 { name: 'url', type: urlArgument },368 ];369 }370}371export class CloseWindowCommand extends ActionCommandBase {372 static methodName = camelCase(TYPE.closeWindow);373 constructor (obj, testRun, validateProperties) {374 super(obj, testRun, TYPE.closeWindow, validateProperties);375 }376 _getAssignableProperties () {377 return [378 { name: 'windowId', type: nullableStringArgument, required: true },379 ];380 }381}382export class GetCurrentWindowCommand extends ActionCommandBase {383 static methodName = camelCase(TYPE.getCurrentWindow);384 constructor (obj, testRun, validateProperties) {385 super(obj, testRun, TYPE.getCurrentWindow, validateProperties);386 }387 _getAssignableProperties () {388 return [389 ];390 }391}392export class GetCurrentWindowsCommand extends ActionCommandBase {393 static methodName = camelCase(TYPE.getCurrentWindows);394 constructor (obj, testRun, validateProperties) {395 super(obj, testRun, TYPE.getCurrentWindows, validateProperties);396 }397 _getAssignableProperties () {398 return [399 ];400 }401}402export class SwitchToWindowCommand extends ActionCommandBase {403 static methodName = camelCase(TYPE.switchToWindow);404 constructor (obj, testRun, validateProperties) {405 super(obj, testRun, TYPE.switchToWindow, validateProperties);406 }407 _getAssignableProperties () {408 return [409 { name: 'windowId', type: nonEmptyStringArgument, required: true },410 ];411 }412}413export class SwitchToWindowByPredicateCommand extends ActionCommandBase {414 static methodName = camelCase(TYPE.switchToWindow);415 constructor (obj, testRun, validateProperties) {416 super(obj, testRun, TYPE.switchToWindowByPredicate, validateProperties);417 }418 _getAssignableProperties () {419 return [420 { name: 'id', type: nonEmptyStringArgument, required: false },421 { name: 'checkWindow', type: functionArgument, required: true },422 ];423 }424}425export class SwitchToParentWindowCommand extends ActionCommandBase {426 static methodName = camelCase(TYPE.switchToParentWindow);427 constructor (obj, testRun, validateProperties) {428 super(obj, testRun, TYPE.switchToParentWindow, validateProperties);429 }430 _getAssignableProperties () {431 return [432 ];433 }434}435export class SwitchToPreviousWindowCommand extends ActionCommandBase {436 static methodName = camelCase(TYPE.switchToPreviousWindow);437 constructor (obj, testRun, validateProperties) {438 super(obj, testRun, TYPE.switchToPreviousWindow, validateProperties);439 }440 _getAssignableProperties () {441 return [];442 }443}444export class SetNativeDialogHandlerCommand extends ActionCommandBase {445 static methodName = camelCase(TYPE.setNativeDialogHandler);446 constructor (obj, testRun, validateProperties) {447 super(obj, testRun, TYPE.setNativeDialogHandler, validateProperties);448 }449 _getAssignableProperties () {450 return [451 { name: 'dialogHandler', init: initDialogHandler, required: true },452 ];453 }454 static from (val) {455 const dialogHandlerStub = {456 dialogHandler: { fn: null },457 };458 const command = new SetNativeDialogHandlerCommand(dialogHandlerStub);459 command.dialogHandler = val.dialogHandler;460 return command;461 }462}463export class GetNativeDialogHistoryCommand extends ActionCommandBase {464 static methodName = camelCase(TYPE.getNativeDialogHistory);465 constructor () {466 super();467 this.type = TYPE.getNativeDialogHistory;468 }469}470export class GetBrowserConsoleMessagesCommand extends ActionCommandBase {471 static methodName = camelCase(TYPE.getBrowserConsoleMessages);472 constructor () {473 super();474 this.type = TYPE.getBrowserConsoleMessages;475 }476}477export class SetTestSpeedCommand extends ActionCommandBase {478 static methodName = camelCase(TYPE.setTestSpeed);479 constructor (obj, testRun, validateProperties) {480 super(obj, testRun, TYPE.setTestSpeed, validateProperties);481 }482 _getAssignableProperties () {483 return [484 { name: 'speed', type: setSpeedArgument, required: true },485 ];486 }487}488export class SetPageLoadTimeoutCommand extends ActionCommandBase {489 static methodName = camelCase(TYPE.setPageLoadTimeout);490 constructor (obj, testRun, validateProperties) {491 super(obj, testRun, TYPE.setPageLoadTimeout, validateProperties);492 }493 _getAssignableProperties () {494 return [495 { name: 'duration', type: positiveIntegerArgument, required: true },496 ];497 }498}499export class UseRoleCommand extends ActionCommandBase {500 static methodName = camelCase(TYPE.useRole);501 constructor (obj, testRun, validateProperties) {502 super(obj, testRun, TYPE.useRole, validateProperties);503 }504 _getAssignableProperties () {505 return [506 { name: 'role', type: actionRoleArgument, required: true },507 ];508 }509}510export class CloseChildWindowOnFileDownloading extends ActionCommandBase {511 static methodName = camelCase(TYPE.closeChildWindowOnFileDownloading);512 constructor (obj, testRun, validateProperties) {513 super(obj, testRun, TYPE.closeChildWindowOnFileDownloading, validateProperties);514 }515}516export class RecorderCommand extends ActionCommandBase {517 static methodName = camelCase(TYPE.recorder);518 constructor (obj, testRun) {519 super(obj, testRun, TYPE.recorder);520 }521 _getAssignableProperties () {522 return [523 { name: 'subtype', type: nonEmptyStringArgument, required: true },524 { name: 'forceExecutionInTopWindowOnly', type: booleanArgument, defaultValue: false },525 ];526 }527}528export class GetCookiesCommand extends ActionCommandBase {529 static methodName = camelCase(TYPE.getCookies);530 constructor (obj, testRun, validateProperties) {531 super(obj, testRun, TYPE.getCookies, validateProperties);532 }533 _getAssignableProperties () {534 return [535 { name: 'urls', type: urlsArgument, required: false },536 { name: 'cookies', type: cookiesArgument, init: initCookiesOption, required: false },537 ];538 }539}540export class SetCookiesCommand extends ActionCommandBase {541 static methodName = camelCase(TYPE.setCookies);542 constructor (obj, testRun, validateProperties) {543 super(obj, testRun, TYPE.setCookies, validateProperties);544 }545 _getAssignableProperties () {546 return [547 { name: 'url', type: urlsArgument, required: false },548 { name: 'cookies', type: setCookiesArgument, init: initCookiesOption, required: true },549 ];550 }551}552export class DeleteCookiesCommand extends ActionCommandBase {553 static methodName = camelCase(TYPE.deleteCookies);554 constructor (obj, testRun, validateProperties) {555 super(obj, testRun, TYPE.deleteCookies, validateProperties);556 }557 _getAssignableProperties () {558 return [559 { name: 'urls', type: urlsArgument, required: false },560 { name: 'cookies', type: cookiesArgument, init: initCookiesOption, required: false },561 ];562 }...

Full Screen

Full Screen

test-custom-resource-provider.js

Source:test-custom-resource-provider.js Github

copy

Full Screen

...39const customResourceProvider = new CustomResourceProvider('Custom::Resource', TEST_RESOURCE_SCHEMA);40const typesSchemaCustomResourceProvider = new CustomResourceProvider('Custom::Resource', TEST_RESOURCE_SCHEMA_TYPES);41const noSchemaCustomResourceProvider = new CustomResourceProvider('Custom::NoSchema', null);42describe('CustomResourceProvider', () => {43 describe('validateProperties()', () => {44 it('should validate when called with a valid property that must start with a slash', () => {45 // Arrange46 let properties = {47 Region: 'us-east-1',48 SecretPath: '/iam-a-validpath/level1/'49 };50 // Act and Assert51 expect(() => { customResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);52 });53 it('should validate when called with valid properties', () => {54 // Arrange55 let properties = {56 Architecture: null,57 InstanceType: 't3.small',58 LinuxVersion: 'Linux',59 Region: 'us-east-1'60 };61 // Act and Assert62 expect(() => { customResourceProvider.validateProperties(properties, 'Create'); }).to.not.throw(Error);63 });64 it('should validate when called with a required property with a value of 0', () => {65 // Arrange66 let properties = {67 NumberProp: 0,68 BooleanProp: true,69 ObjectProp: { s: 'str' }70 };71 // Act and Assert72 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Update'); }).to.not.throw(Error);73 });74 it('should validate when called with a required property with a value of false', () => {75 // Arrange76 let properties = {77 NumberProp: 1,78 BooleanProp: false,79 ObjectProp: { s: 'str' }80 };81 // Act and Assert82 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Update'); }).to.not.throw(Error);83 });84 it('should validate when called with a required property with a value of {}', () => {85 // Arrange86 let properties = {87 NumberProp: 1,88 BooleanProp: true,89 ObjectProp: {}90 };91 // Act and Assert92 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Update'); }).to.not.throw(Error);93 });94 it('should validate when called with a required property with a value of {}', () => {95 // Arrange96 let properties = {97 NumberProp: 1,98 BooleanProp: true,99 ObjectProp: {}100 };101 // Act and Assert102 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Update'); }).to.not.throw(Error);103 });104 it('should validate when custom resource has no property schema', () => {105 // Arrange106 let properties = {107 Architecture: null,108 InstanceType: 't3.small',109 LinuxVersion: 'Linux',110 Region: 'us-east-1'111 };112 // Act and Assert113 expect(() => { noSchemaCustomResourceProvider.validateProperties(properties, 'Create'); }).to.not.throw(Error);114 });115 it('should validate when called with a valid property that must start with a slash', () => {116 // Arrange117 let properties = {118 Region: 'us-east-1',119 SecretPath: '/iam-a-validpath/level1/'120 };121 // Act and Assert122 expect(() => { customResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);123 });124 it('should validate when called with missing properties that are not required for method', () => {125 // Arrange126 let properties = {127 Architecture: null,128 InstanceType: null,129 LinuxVersion: null,130 Region: 'us-east-1'131 };132 // Act and Assert133 expect(() => { customResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);134 });135 it('should validate when called with a valid property that must start with a slash', () => {136 // Arrange137 let properties = {138 Region: 'us-east-1',139 SecretPath: '/iam-a-validpath/level1/'140 };141 // Act and Assert142 expect(() => { customResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);143 });144 it('should validate and return default values when properties with defaults are not set', () => {145 // Arrange146 let properties = {147 NumberProp: 1,148 BooleanProp: true,149 ObjectProp: {},150 WithDefaultString: null,151 WithDefaultBoolean: undefined,152 WithDefaultNumber: undefined153 };154 // Act and Assert155 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);156 expect(properties.WithDefaultString).to.equal(DEFAULT_VALUE);157 expect(properties.WithDefaultBoolean).to.equal(DEFAULT_BOOLEAN_VALUE);158 expect(properties.WithDefaultNumber).to.equal(DEFAULT_NUMBER_VALUE);159 });160 it('should validate and not overwrite a properties with a default value that is set', () => {161 // Arrange162 let properties = {163 NumberProp: 1,164 BooleanProp: true,165 ObjectProp: {},166 WithDefaultString: 'I-have-a-value',167 WithDefaultBoolean: 'false',168 WithDefaultNumber: 9876543210169 };170 // Act and Assert171 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Delete'); }).to.not.throw(Error);172 expect(properties.WithDefaultString).to.equal('I-have-a-value');173 expect(properties.WithDefaultBoolean).to.equal(false);174 expect(properties.WithDefaultNumber).to.equal(9876543210);175 });176 it('should throw Error when called with a property that must start with a slash but does not', () => {177 // Arrange178 let properties = {179 Region: 'us-east-1',180 SecretPath: 'iam-not-a-validpath/level1/'181 };182 // Act and Assert183 expect(() => { customResourceProvider.validateProperties(properties, 'Delete'); }).to.throw(Error)184 .that.has.property('message').that.containIgnoreCase('invalid')185 .and.not.containIgnoreCase('missing');186 });187 it('should throw Error when called with invalid property value', () => {188 // Arrange189 let properties = {190 Architecture: null,191 InstanceType: 't3.small',192 LinuxVersion: 'Linux3', // Invalid value193 Region: 'us-east-1'194 };195 // Act and Assert196 expect(() => { customResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)197 .that.has.property('message').that.containIgnoreCase('invalid')198 .and.not.containIgnoreCase('missing');199 });200 it('should throw Error when called with missing property value', () => {201 // Arrange202 let properties = {203 Architecture: null,204 InstanceType: 't3.small',205 Region: null // Missing property206 };207 // Act and Assert208 expect(() => { customResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)209 .that.has.property('message').that.containIgnoreCase('missing')210 .and.not.containIgnoreCase('invalid');211 });212 it('should throw Error when called with missing and invalid property value', () => {213 // Arrange214 let properties = {215 Architecture: null,216 InstanceType: 't3.small',217 LinuxVersion: 'AmazonLinux', // Invalid property218 Region: null // Missing property219 };220 // Act and Assert221 expect(() => { customResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)222 .that.has.property('message').that.containIgnoreCase('missing')223 .and.that.containIgnoreCase('invalid');224 });225 it('should throw Error when called with a required property being an empty string', () => {226 // Arrange227 let properties = {228 Architecture: null,229 InstanceType: 't3.small',230 LinuxVersion: 'Linux2',231 Region: '' // Empty property232 };233 // Act and Assert234 expect(() => { customResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)235 .that.has.property('message').that.containIgnoreCase('missing')236 .and.not.containIgnoreCase('invalid');237 });238 it('should throw Error when called with a property value of the wrong type', () => {239 // Arrange240 let properties = {241 NumberProp: '123',242 BooleanProp: 'truey',243 ObjectProp: {}244 };245 // Act and Assert246 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)247 .that.has.property('message').that.containIgnoreCase('invalid')248 .and.that.containIgnoreCase('NumberProp')249 .and.that.containIgnoreCase('BooleanProp')250 .and.not.containIgnoreCase('ObjectProp')251 .and.not.containIgnoreCase('missing');252 });253 it('should throw Error when called with missing property value', () => {254 // Arrange255 let properties = {256 BooleanProp: true257 };258 // Act and Assert259 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)260 .that.has.property('message').that.containIgnoreCase('missing')261 .and.that.containIgnoreCase('NumberProp')262 .and.that.containIgnoreCase('ObjectProp')263 .and.not.containIgnoreCase('BooleanProp')264 .and.not.containIgnoreCase('invalid');265 });266 it('should throw Error when called with missing and invalid property value', () => {267 // Arrange268 let properties = {269 NumberProp: '1234',270 BooleanProp: true271 };272 // Act and Assert273 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)274 .that.has.property('message').that.containIgnoreCase('missing')275 .and.that.containIgnoreCase('invalid')276 .and.that.containIgnoreCase('NumberProp')277 .and.that.containIgnoreCase('ObjectProp')278 .and.not.containIgnoreCase('BooleanProp');279 });280 it('should throw Error when called with a required object property being a non-empty string', () => {281 // Arrange282 let properties = {283 NumberProp: 1234,284 BooleanProp: true,285 ObjectProp: 'not-empty'286 };287 // Act and Assert288 expect(() => { typesSchemaCustomResourceProvider.validateProperties(properties, 'Create'); }).to.throw(Error)289 .that.has.property('message').that.containIgnoreCase('invalid')290 .and.that.containIgnoreCase('ObjectProp')291 .and.not.containIgnoreCase('missing')292 .and.not.containIgnoreCase('NumberProp')293 .and.not.containIgnoreCase('BooleanProp');294 });295 it('should throw Error when called with missing properties object', () => {296 // Arrange, Act, and Assert297 expect(() => { customResourceProvider.validateProperties(null, 'Create'); }).to.throw(Error)298 .that.has.property('message').that.containIgnoreCase('missing')299 .and.not.containIgnoreCase('invalid');300 });301 });302 describe('Create()', () =>{303 it('should return FAILED status when Create() is called', async () => {304 // Arrange305 TEST_EVENT.RequestType = 'Create';306 // Act307 let result = await customResourceProvider.Create(TEST_EVENT, TEST_CONTEXT);308 // Assert309 expect(result).to.be.an('object');310 expect(result.RequestType).to.equal(TEST_EVENT.RequestType);311 expect(result.ResourceType).to.equal(TEST_EVENT.ResourceType);...

Full Screen

Full Screen

validateInput.test.js

Source:validateInput.test.js Github

copy

Full Screen

...90 __meta: { type: true },91 extra: {},92 };93 expect(() => {94 validateProperties(body);95 }).toThrow('Invalid body.');96 });97 test('body keys length not valid', () => {98 const body = {};99 expect(() => {100 validateProperties(body);101 }).toThrow('Invalid body.');102 });103 test('provided object insted of array', () => {104 const body = { name: 'john' };105 expect(() => {106 validateProperties(body);107 }).toThrow(108 'Please provide entity with this structure { NAME: [{}, {}, {}] }',109 );110 });111 test('no errors', () => {112 const body = { users: [{ name: 'john' }, { name: 'michael' }] };113 validateProperties(body);114 });115 test('no meta in body', () => {116 const body = { users: [{ name: 'john' }, { name: 'michael' }], neta: {} };117 expect(() => {118 validateProperties(body);119 }).toThrow('Invalid body.');120 });121 test('type in meta but false', () => {122 const body = {123 users: [{ name: 'john' }, { name: 'michael' }],124 __meta: { type: false },125 };126 expect(() => {127 validateProperties(body);128 }).toThrow('Property __meta is invalid.');129 });130 test('force in meta but false', () => {131 const body = {132 users: [{ name: 'john' }, { name: 'michael' }],133 __meta: { force: false },134 };135 expect(() => {136 validateProperties(body);137 }).toThrow('Property __meta is invalid.');138 });139 test('type in meta, no error', () => {140 const body = {141 users: { name: 'string' },142 __meta: { type: true },143 };144 validateProperties(body);145 });146 test('force in meta, no error', () => {147 const body = {148 users: [{ name: 'john' }, { name: 'michael' }],149 __meta: { force: true },150 };151 validateProperties(body);152 });153});154describe('validate input', () => {155 test('invalid str', () => {156 const str =157 '"users":[{"name":"Rom","age":39},{"name":"Mark","age":39},{"name":"John","age":38}],"moreUser":[]}';158 const event = { body: str };159 expect(() => {160 validateInput(event);161 }).toThrow('Invalid body.');162 });163 test('body keys length not valid', () => {164 const event = {165 body: JSON.stringify({166 users: [{ name: 'john' }, { name: 'michael' }],167 __meta: { type: true },168 extra: {},169 }),170 };171 expect(() => {172 validateInput(event);173 }).toThrow('Invalid body.');174 });175 test('body keys length not valid', () => {176 const event = { body: JSON.stringify({}) };177 expect(() => {178 validateInput(event);179 }).toThrow('Invalid body.');180 });181 test('provided object insted of array', () => {182 const event = { body: JSON.stringify({ name: 'john' }) };183 expect(() => {184 validateProperties(event);185 }).toThrow(186 'Please provide entity with this structure { NAME: [{}, {}, {}] }',187 );188 });189 test('no errors', () => {190 const event = {191 body: JSON.stringify({ users: [{ name: 'john' }, { name: 'michael' }] }),192 };193 validateInput(event);194 });195 test('type in meta but false', () => {196 const event = {197 body: JSON.stringify({198 users: [{ name: 'john' }, { name: 'michael' }],...

Full Screen

Full Screen

AttributeCollection-spec.js

Source:AttributeCollection-spec.js Github

copy

Full Screen

...14 expect(coll.all()).toEqual({});15 //noinspection JSUnresolvedFunction16 expect(coll.defaults()).toEqual({});17 //noinspection JSUnresolvedFunction18 expect(coll.validateProperties({})).toEqual(true);19 //noinspection JSUnresolvedFunction20 expect(function () {21 coll.validateProperties({'myProperty': 'myValue'});22 }).toThrow(new Error('The attribute "myProperty" is not valid.'));23 });24 //noinspection JSUnresolvedFunction25 it('can add and validate values', function () {26 var coll = new AttributeCollection();27 coll.add('EMAIL', {28 name: 'email',29 validate: function (value) {30 return typeof value === 'string' && value.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);31 }32 });33 //noinspection JSUnresolvedFunction34 expect(coll.all()).toEqual({'EMAIL': 'email'});35 //noinspection JSUnresolvedFunction36 expect(coll.is('email')).toBe(true);37 //noinspection JSUnresolvedFunction38 expect(coll.default('email')).toBeUndefined();39 //noinspection JSUnresolvedFunction40 expect(function () {41 coll.validateProperties({'email': 'myValue'});42 }).toThrow(new Error('The value "myValue" is invalid for the property "email".'));43 //noinspection JSUnresolvedFunction44 expect(coll.validateProperties({'email': 'philipp.meisen@breinify.com'})).toBe(true);45 coll.add('SIMPLE');46 //noinspection JSUnresolvedFunction47 expect(coll.all()).toEqual({'EMAIL': 'email', 'SIMPLE': 'SIMPLE'});48 coll.add('ALSOSIMPLE', 'soSimple');49 //noinspection JSUnresolvedFunction50 expect(coll.all()).toEqual({'EMAIL': 'email', 'SIMPLE': 'SIMPLE', 'ALSOSIMPLE': 'soSimple'});51 //noinspection JSUnresolvedFunction52 expect(coll.is('email')).toBe(true);53 //noinspection JSUnresolvedFunction54 expect(coll.is('SIMPLE')).toBe(true);55 //noinspection JSUnresolvedFunction56 expect(coll.is('soSimple')).toBe(true);57 //noinspection JSUnresolvedFunction58 expect(coll.default('email')).toBeUndefined();59 //noinspection JSUnresolvedFunction60 expect(coll.default('SIMPLE')).toBeUndefined();61 //noinspection JSUnresolvedFunction62 expect(coll.default('soSimple')).toBeUndefined();63 //noinspection JSUnresolvedFunction64 expect(coll.validateProperties({'email': 'philipp.meisen@breinify.com'})).toBe(true);65 //noinspection JSUnresolvedFunction66 expect(coll.validateProperties({67 'email': 'philipp.meisen@breinify.com',68 'SIMPLE': null,69 'soSimple': 'value'70 })).toBe(true);71 });72 //noinspection JSUnresolvedFunction73 it('can validate groups', function () {74 var coll = new AttributeCollection();75 coll.add('FIRST', {76 name: 'first',77 group: 178 });79 coll.add('LAST', {80 name: 'last',81 group: 1,82 optional: false83 });84 coll.add('DATE', {85 name: 'date',86 group: 1,87 optional: false88 });89 coll.add('OTHER', {90 name: 'other',91 group: 292 });93 coll.add('MORE', {94 name: 'more',95 group: 3,96 optional: false97 });98 coll.add('ANOTHER', {99 name: 'another',100 group: 3,101 optional: false102 });103 //noinspection JSUnresolvedFunction104 expect(coll.validateProperties({105 'other': 'anotherValue'106 })).toBe(true);107 //noinspection JSUnresolvedFunction108 expect(coll.validateProperties({109 'first': 'Diane',110 'last': 'Keng',111 'date': '01/01/1980'112 })).toBe(true);113 //noinspection JSUnresolvedFunction114 expect(function () {115 coll.validateProperties({116 'first': 'Diane',117 'date': '01/01/1980'118 });119 }).toThrow(new Error('The group "1" expects a valid value for the attribute "last".'));120 //noinspection JSUnresolvedFunction121 expect(coll.validateProperties({122 'last': 'Keng',123 'date': '01/01/1980',124 'more': 'more is more',125 'another': 'less can be good'126 })).toBe(true);127 //noinspection JSUnresolvedFunction128 expect(function () {129 coll.validateProperties({130 'last': 'Keng',131 'date': '01/01/1980',132 'another': 'less can be good'133 });134 }).toThrow(new Error('The group "3" expects a valid value for the attribute "more".'));135 //noinspection JSUnresolvedFunction136 expect(function () {137 coll.validateProperties({138 'last': 'Keng',139 'more': 'more is more',140 'another': 'less can be good'141 });142 }).toThrow(new Error('The group "1" expects a valid value for the attribute "date".'));143 });...

Full Screen

Full Screen

validateProperties.test.js

Source:validateProperties.test.js Github

copy

Full Screen

...5 const person = {6 name: "Plo Koon",7 birth_year: "22BBY"8 }9 expect(validateProperties(person, properties)).toBeTruthy();10 });11 test("Returns false if person passed in is undefined", () => {12 expect(validateProperties(undefined, properties)).toBeFalsy();13 });14 test("Returns false if person passed in is missing name property", () => {15 const person = {16 birth_year: "22BBY"17 };18 expect(validateProperties(person, properties)).toBeFalsy();19 });20 test("Returns false if person passed in is missing birth year property", () => {21 const person = {22 name: "Plo Koon"23 };24 expect(validateProperties(person, properties)).toBeFalsy();25 });26 test("Returns false if person passed in has unknown name", () => {27 const person = {28 name: "unknown",29 birth_year: "22BBY"30 };31 expect(validateProperties(person, properties)).toBeFalsy();32 });33 test("Returns false if person passed in has unknown birth year", () => {34 const person = {35 name: "Plo Koon",36 birth_year: "unknown"37 };38 expect(validateProperties(person, properties)).toBeFalsy();39 });40 test("If no array of properties are passed in, only checks whether person object is not undefined", () => {41 const person = {};42 expect(validateProperties(person)).toBeTruthy();43 });44 test("Throws error if second argument is not an array", () => {45 const person = {46 name: "Plo Koon",47 birth_year: "22BBY"48 }49 expect(() => validateProperties(person, "bad arg"))50 .toThrow("First argument should be an object and the second an array of properties (eg: 'name', 'birth_year') in string representation");51 });...

Full Screen

Full Screen

validate-test.js

Source:validate-test.js Github

copy

Full Screen

...12 });13});14describe('validateProperties', function() {15 it('should validate valid AST node properties', function() {16 validateProperties({});17 validateProperties({ prop: { type: 'value', value: 2 } });18 validateProperties({ prop: { type: 'variable', value: 'foo' } });19 validateProperties({ prop: { type: 'expression', value: 'foo + 1' } });20 });21 it('should throw on invalid AST node properties', function() {22 expect(() => validateProperties(2)).to.throwError();23 expect(() => validateProperties({ prop: 'foo' })).to.throwError();24 expect(() =>25 validateProperties({ type: 'value', value: 2 })26 ).to.throwError();27 expect(() =>28 validateProperties({29 prop: { type: 'foo', value: 2 }30 })31 ).to.throwError();32 expect(() =>33 validateProperties({34 prop: { type: 'value', value: 2, extra: 3 }35 })36 ).to.throwError();37 });...

Full Screen

Full Screen

getRandomPersonWithProps.js

Source:getRandomPersonWithProps.js Github

copy

Full Screen

...9 for (let i = 0; i < 10; i ++) {10 randomId = getRandomWholeNumber(1, totalNumPeople);11 randomPerson = await utils.fetchItem(`https://swapi.py4e.com/api/people/${randomId}`);12 13 if (validateProperties(randomPerson, props)) {14 break;15 };16 };17 18 if (!validateProperties(randomPerson, props)) {19 throw new Error("Unable to retrieve a valid person after multiple attempts");20 };21 return randomPerson;...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('playwright');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.click('text="Get started"');8 const properties = await validateProperties(await page.$('text="Get started"'));9 console.log(properties);10 await browser.close();11})();12{

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('@playwright/test/lib/utils/utils');2const { test } = require('@playwright/test');3test('validateProperties', async ({ page }) => {4 const properties = {5 };6 const element = await page.$('#playwright-header');7 const result = await validateProperties(element, properties);8 console.log(result);9});10validateProperties (1s)11 1 passed (1s)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('@playwright/test/lib/server/validateProperties');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 await page.$('text=Get started');5 validateProperties(page);6});7const { validateProperties } = require('@playwright/test/lib/server/validateProperties');8const { test } = require('@playwright/test');9test('test', async ({ page }) => {10 await page.$('text=Get started');11 validateProperties(page);12});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('playwright/lib/utils/utils');2const { assert } = require('chai');3const { it, describe } = require('mocha');4describe('Validate Properties', () => {5 it('should check if the property is valid', () => {6 assert.doesNotThrow(() => {7 validateProperties({ foo: 'bar' }, { foo: { type: 'string' } });8 });9 });10});11const { validateProperties } = require('playwright/lib/utils/utils');12const { assert } = require('chai');13const { it, describe } = require('mocha');14describe('Validate Properties', () => {15 it('should check if the property is valid', () => {16 assert.doesNotThrow(() => {17 validateProperties({ foo: 'bar' }, { foo: { type: 'number' } });18 });19 });20});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('@playwright/test/lib/server/validateProperties');2const { assert } = require('chai');3const { test } = require('@playwright/test');4test('validateProperties', async ({}) => {5 const obj = {a: 1, b: 2, c: 3};6 const validProperties = ['a', 'b', 'c'];7 const actualResult = validateProperties(obj, validProperties);8 const expectedResult = obj;9 assert.deepEqual(actualResult, expectedResult);10});11test('validateProperties - invalid', async ({}) => {12 const obj = {a: 1, b: 2, c: 3};13 const validProperties = ['a', 'b'];14 const actualResult = validateProperties(obj, validProperties);15 const expectedResult = {a: 1, b: 2};16 assert.deepEqual(actualResult, expectedResult);17});18test('validateProperties - invalid', async ({}) => {19 const obj = {a: 1, b: 2, c: 3};20 const validProperties = ['a', 'b', 'd'];21 const actualResult = validateProperties(obj, validProperties);22 const expectedResult = {a: 1, b: 2};23 assert.deepEqual(actualResult, expectedResult);24});25test('validateProperties - invalid', async ({}) => {26 const obj = {a: 1, b: 2, c: 3};27 const validProperties = ['a', 'b', 'c', 'd'];28 const actualResult = validateProperties(obj, validProperties);29 const expectedResult = {a: 1, b: 2, c: 3};30 assert.deepEqual(actualResult, expectedResult);31});32test('validateProperties - invalid', async ({}) => {33 const obj = {a: 1, b: 2, c: 3};34 const validProperties = ['a', 'b', 'c', 'd'];35 const actualResult = validateProperties(obj, validProperties);36 const expectedResult = {a: 1, b: 2, c: 3};37 assert.deepEqual(actualResult, expectedResult);38});39test('validateProperties - invalid', async ({}) => {40 const obj = {a: 1, b: 2, c: 3};

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('playwright/lib/internal/utils');2const { expect } = require('chai');3const options = {4 corge: {},5 garply6: [{}, {}, {}],6};7const schema = {8 foo: { type: 'string' },9 bar: { type: 'number' },10 baz: { type: 'boolean' },11 qux: { type: 'null' },12 quux: { type: 'undefined' },13 corge: { type: 'object' },14 grault: { type: 'array' },15 garply: { type: 'array', items: { type: 'string' } },16 garply2: { type: 'array', items: { type: 'number' } },17 garply3: { type: 'array', items: { type: 'boolean' } },18 garply4: { type: 'array', items: { type: 'null' } },19 garply5: { type: 'array', items: { type: 'undefined' } },20 garply6: { type: 'array', items: { type: 'object' } },21 garply7: { type: 'array', items: { type: 'array' } },22};23const result = validateProperties(options, schema);24expect(result).to.be.true;25const { validateProperties } = require('playwright/lib/internal/utils');26const { expect } = require('chai');27const options = {28 corge: {},

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require('playwright-core/lib/server/frames');2const { assert } = require('console');3const properties = {4};5const object = {6 location: {7 },8 address: {9 },10};11const result = validateProperties(object, properties);12assert(result.success === true, 'Validation failed');13console.log('Validation passed');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { validateProperties } = require( 'playwright/lib/utils/utils' );2validateProperties( { name: 'foo' }, {3 name: { is: 'string' }4} );5const { test } = require( '@playwright/test' );6test( 'test', async ( { page } ) => {7 const { validateProperties } = require( 'playwright/lib/utils/utils' );8 validateProperties( { name: 'foo' }, {9 name: { is: 'string' }10 } );11} );

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful