1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-01-06 03:03:57 +02:00

Feature/new selector type (#657)

* Added remote type reference resolver

* Added support of XPath query selector

* Added CDP e2e testss covering XPath integration

* Added additional CDP e2e tests covering XPath integration

* Added type check to QuerySelector casting function

* Fixed XPath e2e tests

* Fixed vuln issue

* Added support of XPath selectors to http driver

* Added e2e tests for XPAth
This commit is contained in:
Tim Voronov 2021-09-16 21:40:20 -04:00 committed by GitHub
parent a000302259
commit 90427cd537
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
167 changed files with 2275 additions and 1102 deletions

View File

@ -1,7 +1,7 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
CLICK(page, "#wait-class-random button")
T::TRUE(CLICK(page, "#wait-class-random button"))
WAIT_CLASS(page, "#wait-class-random-content", "alert-success", 10000)

View File

@ -7,7 +7,7 @@ LET input = ELEMENT(page, "#text_input")
INPUT(input, "Foo")
CLICK(page, "#text_input", 2)
T::TRUE(CLICK(page, "#text_input", 2))
INPUT(input, "Bar")

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
T::TRUE(CLICK(page, X("//button[@id='wait-class-random-btn']")))
WAIT_CLASS(page, "#wait-class-random-content", "alert-success", 10000)
RETURN TRUE

View File

@ -0,0 +1,16 @@
LET url = @lab.cdn.dynamic + "/#/forms"
LET page = DOCUMENT(url, true)
WAIT_ELEMENT(page, "form")
LET input = ELEMENT(page, "#text_input")
INPUT(input, "Foo")
T::TRUE(CLICK(page, X(".//*[@id='text_input']"), 2))
INPUT(input, "Bar")
WAIT(100)
RETURN T::EQ(input.value, "Bar")

View File

@ -1,5 +1,5 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url)
LET doc = DOCUMENT(url, { driver: "cdp" })
T::TRUE(ELEMENT_EXISTS(doc, '.text-center'))
T::FALSE(ELEMENT_EXISTS(doc, '.foo-bar'))

View File

@ -0,0 +1,7 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, { driver: "cdp" })
T::TRUE(ELEMENT_EXISTS(doc, X(".//*[contains(@class, 'text-center')]")))
T::FALSE(ELEMENT_EXISTS(doc, X(".//*[contains(@class, 'foo-bar')]")))
RETURN NONE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, { driver: "cdp" })
FOCUS(page, "#focus-input")
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN TRUE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, { driver: "cdp" })
FOCUS(page, X("//*[@id='focus-input']"))
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN TRUE

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, { driver: "cdp" })
LET selector = X('//*[@id="root"]/div/main/div')
WAIT_ELEMENT(doc, "#layout")
LET expected = '<div><h1>Welcome to Ferret E2E test page!</h1></div><div><p class="lead">It has several pages for testing different possibilities of the library</p></div>'
LET actual = INNER_HTML(doc, selector)
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), '(\n|\s)', ''), REGEX_REPLACE(expected, '\s', ''))

View File

@ -0,0 +1,13 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET selector = X('//*[@id="root"]/div/main/div/*')
WAIT_ELEMENT(doc, "#layout")
LET expected = [
'<h1>Welcome to Ferret E2E test page!</h1>',
'<p class="lead">It has several pages for testing different possibilities of the library</p>'
]
LET actual = INNER_HTML_ALL(doc, selector)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, { driver: "cdp" })
LET selector = X('.//*[@id="root"]/div/main/div/*/h1')
WAIT_ELEMENT(doc, "#layout")
LET expected = 'Welcome to Ferret E2E test page!'
LET actual = INNER_TEXT(doc, selector)
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), '(\n|\s)', ''), REGEX_REPLACE(expected, '\s', ''))

View File

@ -0,0 +1,16 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET selector = X('.//*[@id="root"]/div/main/div/*')
WAIT_ELEMENT(doc, "#layout")
LET expected = [
'Welcome to Ferret E2E test page!',
'It has several pages for testing different possibilities of the library'
]
LET actual = (
FOR str IN INNER_TEXT_ALL(doc, selector)
RETURN REGEX_REPLACE(TRIM(str), '\n', '')
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "form")
LET output = ELEMENT(doc, "#text_output")
INPUT(doc, X("//*[@id='text_input']"), "foo")
RETURN T::EQ(output.innerText, "foo")

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.dynamic + "/#/pagination"
LET page = DOCUMENT(url, true)
LET items = (
FOR i IN PAGINATION(page, X("//li[contains(@class, 'page-item-next') and contains(@class, 'page-item') and not(contains(@class, 'disabled'))]"))
RETURN i
)
RETURN T::LEN(items, 5)

View File

@ -0,0 +1,12 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "form")
LET output = ELEMENT(doc, "#multi_select_output")
LET result = SELECT(doc, X("//*[@id='multi_select_input']"), ["1", "2", "4"])
T::EQ(output.innerText, "1, 2, 4")
T::EQ(JSON_STRINGIFY(result), '["1","2","4"]')
RETURN NONE

View File

@ -0,0 +1,12 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, { driver: "cdp" })
WAIT_ELEMENT(doc, "form")
LET output = ELEMENT(doc, "#select_output")
LET result = SELECT(doc, X("//*[@id='select_input']"), ["4"])
T::EQ(output.innerText, "4")
T::EQ(JSON_STRINGIFY(result), '["4"]')
RETURN NONE

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
CLICK_ALL(doc, "#wait-class-btn, #wait-class-random-btn")
T::LEN(ELEMENTS(doc, X("//*[@id='wait-class-content' or @id='wait-class-random-content']")), 2)
WAIT_ATTR_ALL(doc, X("//*[@id='wait-class-content' or @id='wait-class-random-content']"), "class", "alert alert-success", 10000)
RETURN TRUE

View File

@ -0,0 +1,20 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = X("//*[@id='wait-class-btn']")
LET attrName = "data-ferret-x"
LET attrVal = "foobar"
WAIT_ELEMENT(doc, "#page-events")
LET el = ELEMENT(doc, selector)
LET prev = el.attributes
ATTR_SET(el, attrName, attrVal)
WAIT_ATTR(doc, selector, attrName, attrVal, 30000)
LET curr = el.attributes
T::NONE(prev[attrName])
T::EQ(attrVal, curr[attrName], "attributes should be updated")
RETURN TRUE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
CLICK_ALL(doc, "#wait-class-btn, #wait-class-random-btn")
WAIT_CLASS_ALL(doc, X("//*[@id='wait-class-content' or @id='wait-class-random-content']"), "alert-success", 10000)
RETURN NONE

View File

@ -0,0 +1,14 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
// with fixed timeout
CLICK(doc, "#wait-class-btn")
WAIT_CLASS(doc, X("//*[@id='wait-class-content']"), "alert-success")
// with random timeout
CLICK(doc, "#wait-class-random-btn")
WAIT_CLASS(doc, X("//*[@id='wait-class-random-content']"), "alert-success", 10000)
RETURN NONE

View File

@ -0,0 +1,15 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET pageSelector = X("//*[@id='page-events']")
LET elemSelector = X("//*[@id='wait-element-content']")
LET btnSelector = "#wait-element-btn"
WAIT_ELEMENT(doc, pageSelector)
CLICK(doc, btnSelector)
WAIT_ELEMENT(doc, elemSelector, 10000)
T::TRUE(ELEMENT_EXISTS(doc, elemSelector), "element not found")
RETURN NONE

View File

@ -1,13 +1,8 @@
LET url = @lab.cdn.dynamic + "?redirect=/iframe&src=/iframe"
// LET url = "http://192.168.4.23:8080/?redirect=/iframe&src=/iframe"
LET page = DOCUMENT(url, { driver: 'cdp' })
LET original = FIRST(FRAMES(page, "url", "/\?redirect=/iframe$"))
INPUT(original, "#url_input", "https://getbootstrap.com/")
// WAIT(3000)
// LET btn = ELEMENT(original, "#submit")
// CLICK(btn)
CLICK(original, "#submit")

View File

@ -0,0 +1,16 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
// with fixed timeout
CLICK(doc, "#wait-no-class-btn")
WAIT(1000)
PRINT(ATTR_GET(ELEMENT(doc, "#wait-no-class-content"), "class"))
WAIT_NO_ATTR(doc, X("//*[@id='wait-no-class-content']"), "class", "alert alert-success")
// with random timeout
CLICK(doc, "#wait-no-class-random-btn")
WAIT_NO_ATTR(doc, X("//*[@id='wait-no-class-random-content']"), "class", "alert alert-success", 10000)
RETURN NONE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
CLICK_ALL(doc, "#wait-no-class-btn, #wait-no-class-random-btn")
WAIT_NO_CLASS_ALL(doc, X("//*[@id='wait-no-class-content' or @id='wait-no-class-random-content']"), "alert-success", 10000)
RETURN NONE

View File

@ -0,0 +1,14 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
// with fixed timeout
CLICK(doc, "#wait-no-class-btn")
WAIT_NO_CLASS(doc, X("//*[@id='wait-no-class-content']"), "alert-success")
// with random timeout
CLICK(doc, "#wait-no-class-random-btn")
WAIT_NO_CLASS(doc, X("//*[@id='wait-no-class-random-content']"), "alert-success", 10000)
RETURN NONE

View File

@ -0,0 +1,15 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET pageSelector = "#page-events"
LET elemSelector = X("//*[@id='wait-no-element-content']")
LET btnSelector = "#wait-no-element-btn"
WAIT_ELEMENT(doc, pageSelector)
CLICK(doc, btnSelector)
WAIT_NO_ELEMENT(doc, elemSelector, 10000)
T::FALSE(ELEMENT_EXISTS(doc, elemSelector), "element should not be found")
RETURN NONE

View File

@ -0,0 +1,32 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = X("//*[@id='wait-class-btn' or @id='wait-class-random-btn']")
WAIT_ELEMENT(doc, "#page-events")
LET n = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "color: black")
RETURN NONE
)
WAIT_STYLE_ALL(doc, selector, "color", "rgb(0, 0, 0)", 10000)
LET n2 = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "color: red")
RETURN NONE
)
WAIT_NO_STYLE_ALL(doc, selector, "color", "rgb(0, 0, 0)", 10000)
LET results = (
FOR el IN ELEMENTS(doc, selector)
RETURN el.style.color
)
T::EQ(results, ["rgb(255, 0, 0)","rgb(255, 0, 0)"])
RETURN NONE

View File

@ -0,0 +1,24 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = X("//*[@id='wait-class-btn']")
WAIT_ELEMENT(doc, "#page-events")
LET el = ELEMENT(doc, selector)
STYLE_SET(el, "color", "green")
WAIT(200)
WAIT_STYLE(doc, selector, "color", "rgb(0, 128, 0)")
LET prev = el.style
STYLE_SET(el, "color", "red")
WAIT_NO_STYLE(doc, selector, "color", "rgb(0, 128, 0)")
WAIT_STYLE(doc, selector, "color", "rgb(255, 0, 0)")
LET curr = el.style
T::EQ(prev.color, "rgb(0, 128, 0)")
T::EQ(curr.color, "rgb(255, 0, 0)")
RETURN NONE

View File

@ -0,0 +1,23 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = X("//*[@id='wait-class-btn' or @id='wait-class-random-btn']")
WAIT_ELEMENT(doc, "#page-events")
LET n = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "width: 200px")
RETURN NONE
)
WAIT_STYLE_ALL(doc, selector, "width", "200px", 10000)
LET results = (
FOR el IN ELEMENTS(doc, selector)
RETURN el.style.width
)
T::EQ(results, ["200px","200px"])
RETURN NONE

View File

@ -0,0 +1,18 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = X("//*[@id='wait-class-btn']")
WAIT_ELEMENT(doc, "#page-events")
LET el = ELEMENT(doc, selector)
LET prev = el.style
ATTR_SET(el, "style", "width: 200px")
WAIT_STYLE(doc, selector, "width", "200px")
LET curr = el.style
T::NOT::EQ(prev.width, "200px")
T::EQ(curr.width, "200px")
RETURN NONE

View File

@ -9,4 +9,4 @@ BLUR(page, "#focus-input")
WAIT_NO_CLASS(page, "#focus-content", "alert-success")
RETURN ""
RETURN TRUE

View File

@ -0,0 +1,12 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
FOCUS(page, "#focus-input")
WAIT_CLASS(page, "#focus-content", "alert-success")
BLUR(page, X('.//*[@id="focus-input"]'))
WAIT_NO_CLASS(page, "#focus-content", "alert-success")
RETURN TRUE

View File

@ -0,0 +1,28 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "form")
LET form = ELEMENT(doc, "#page-form")
INPUT(form, "#text_input", "foo")
INPUT_CLEAR(form, X('//*[@id="text_input"]'))
LET input = ELEMENT(doc, "#text_input")
LET output = ELEMENT(doc, "#text_output")
T::EMPTY(output.innerText)
INPUT(form, "#text_input", "test0-test1", 100)
INPUT_CLEAR(form, X('//*[@id="text_input"]'))
T::EMPTY(output.innerText)
INPUT(form, "#text_input", "test0&test1", 100)
INPUT_CLEAR(form, X('//*[@id="text_input"]'))
T::EMPTY(output.innerText)
RETURN NONE

View File

@ -7,4 +7,4 @@ CLICK(div, "button")
WAIT_CLASS(page, "#wait-class-random-content", "alert-success", 10000)
RETURN ""
RETURN TRUE

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
LET div = ELEMENT(page, "#wait-class-random")
CLICK(div, X(".//button"))
WAIT_CLASS(page, "#wait-class-random-content", "alert-success", 10000)
RETURN TRUE

View File

@ -0,0 +1,16 @@
LET url = @lab.cdn.dynamic + "/#/forms"
LET page = DOCUMENT(url, true)
WAIT_ELEMENT(page, "form")
LET input = ELEMENT(page, "#text_input")
INPUT(input, "Foo")
CLICK(page, X('.//*[@id="text_input"]'), 2)
INPUT(input, "Bar")
WAIT(100)
RETURN T::EQ(input.value, "Bar")

View File

@ -5,4 +5,4 @@ FOCUS(page, "#focus-input")
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN ""
RETURN TRUE

View File

@ -1,8 +1,8 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
FOCUS(page, "#focus-input")
FOCUS(page, X('//*[@id="focus-input"]'))
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN ""
RETURN TRUE

View File

@ -0,0 +1,11 @@
LET url = @lab.cdn.dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "#page-events")
HOVER(doc, X('.//*[@id="hoverable-btn"]'))
WAIT_ELEMENT(doc, "#hoverable-content")
LET output = INNER_TEXT(doc, "#hoverable-content")
RETURN T::EQ(output, "Lorem ipsum dolor sit amet.")

View File

@ -0,0 +1,34 @@
LET url = @lab.cdn.dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
LET expected = [
{"details":'<h5 class="track-artist">Lil Tecca</h5><small class="track-name">Ransom</small>'},
{"details":'<h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow (Feat. Blueface) [Remix]</small>'},
{"details":'<h5 class="track-artist">Baby Jesus (DaBaby)</h5><small class="track-name">Suge</small>'},
{"details":'<h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow 3</small>'},
{"details":'<h5 class="track-artist">Lil Tecca </h5><small class="track-name">Lil Tecca - Did It Again</small>'},
{"details":'<h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow</small>'},
{"details":'<h5 class="track-artist">Ynw Melly</h5><small class="track-name">Dangerously In Love (772 Love Pt. 2)</small>'},
{"details":'<h5 class="track-artist">POLO G</h5><small class="track-name">Polo G feat. Lil TJay - Pop Out</small>'},
{"details":`<h5 class="track-artist">MUSTARD</h5><small class="track-name">Ballin' (feat. Roddy Ricch)</small>`},
{"details":'<h5 class="track-artist">Lil Nas X</h5><small class="track-name">Panini</small>'},
{"details":'<h5 class="track-artist">Juice WRLD</h5><small class="track-name">Juice Wrld - RUN</small>'},
{"details":'<h5 class="track-artist">Shordie Shordie</h5><small class="track-name">Betchua (Bitchuary)</small>'},
{"details":'<h5 class="track-artist">Post Malone</h5><small class="track-name">Goodbyes (feat. Young Thug)</small>'},
{"details":'<h5 class="track-artist">LIL UZI VERT</h5><small class="track-name">Sanguine Paradise</small>'},
{"details":'<h5 class="track-artist">Calboy</h5><small class="track-name">Envy Me</small>'},
{"details":'<h5 class="track-artist">Ambjaay</h5><small class="track-name">Uno</small>'},
{"details":'<h5 class="track-artist">Lil Tecca</h5><small class="track-name">Lil Tecca - Bossanova</small>'},
{"details":'<h5 class="track-artist">Lil Baby</h5><small class="track-name">Baby</small>'},
{"details":'<h5 class="track-artist">Lil Tjay</h5><small class="track-name">Lil Tjay - Brothers (Prod by JDONTHATRACK &amp; Protegebeatz)</small>'},
{"details":'<h5 class="track-artist">YK Osiris</h5><small class="track-name">Worth It</small>'}
]
LET actual = (
FOR item IN ELEMENTS(doc, '.track-list li')
RETURN {
details: INNER_HTML(item, X(".//*[contains(@class, 'track-details')]")),
}
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,5 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, ".jumbotron")
RETURN INNER_HTML(el, X(".//h5"))

View File

@ -0,0 +1,25 @@
LET url = @lab.cdn.dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
LET expected = [
{"details":'<h5 class="track-artist">MEDUZA</h5><small class="track-name">Piece Of Your Heart (feat. Goodboys)</small>'},
{"details":'<h5 class="track-artist">Metanoia Music</h5><small class="track-name">Che Crozz x Orbis - Lift Me Up</small>'}
]
LET html = (
FOR t IN expected
RETURN '<li><div class="track-details">' + t.details + '</div></li>'
)
INNER_HTML_SET(doc, X(".//*[contains(@class, 'track-list')]"), CONCAT_SEPARATOR('\n', html))
LET list = ELEMENT(doc, '.track-list')
LET actual = (
FOR item IN ELEMENTS(doc, '.track-list li')
RETURN {
details: INNER_HTML(item, '.track-details'),
}
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,35 @@
LET url = @lab.cdn.dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
LET expected = [
{"artist":"Lil Tecca","track":"Ransom"},
{"artist":"NLE Choppa","track":"Shotta Flow (Feat. Blueface) [Remix]"},
{"artist":"Baby Jesus (DaBaby)","track":"Suge"},
{"artist":"NLE Choppa","track":"Shotta Flow 3"},
{"artist":"Lil Tecca","track":"Lil Tecca - Did It Again"},
{"artist":"NLE Choppa","track":"Shotta Flow"},
{"artist":"Ynw Melly","track":"Dangerously In Love (772 Love Pt. 2)"},
{"artist":"POLO G","track":"Polo G feat. Lil TJay - Pop Out"},
{"artist":"MUSTARD","track":"Ballin' (feat. Roddy Ricch)"},
{"artist":"Lil Nas X","track":"Panini"},
{"artist":"Juice WRLD","track":"Juice Wrld - RUN"},
{"artist":"Shordie Shordie","track":"Betchua (Bitchuary)"},
{"artist":"Post Malone","track":"Goodbyes (feat. Young Thug)"},
{"artist":"LIL UZI VERT","track":"Sanguine Paradise"},
{"artist":"Calboy","track":"Envy Me"},
{"artist":"Ambjaay","track":"Uno"},
{"artist":"Lil Tecca","track":"Lil Tecca - Bossanova"},
{"artist":"Lil Baby","track":"Baby"},
{"artist":"Lil Tjay","track":"Lil Tjay - Brothers (Prod by JDONTHATRACK & Protegebeatz)"},
{"artist":"YK Osiris","track":"Worth It"}
]
LET actual = (
FOR item IN ELEMENTS(doc, '.track-list li')
RETURN {
artist: TRIM(INNER_TEXT(item, X(".//*[contains(@class, 'track-artist')]"))),
track: TRIM(INNER_TEXT(item, X(".//*[contains(@class, 'track-name')]")))
}
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,5 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, ".jumbotron")
RETURN INNER_TEXT(el, X(".//h5"))

View File

@ -0,0 +1,5 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, ".jumbotron")
RETURN INNER_TEXT_SET(el, X(".//h4"), "foobar")

View File

@ -0,0 +1,37 @@
LET url = @lab.cdn.dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
LET expected = [
{
"artist":'MEDUZA',
"track": 'Piece Of Your Heart (feat. Goodboys)'
},
{
"artist": 'Metanoia Music',
"track": 'Che Crozz x Orbis - Lift Me Up'
}
]
LET f = (
FOR item, idx IN ELEMENTS(doc, '.track-list li')
LIMIT 2
LET value = expected[idx]
INNER_HTML_SET(item, X(".//*[contains(@class, 'track-artist')]"), value.artist)
INNER_HTML_SET(item, X(".//*[contains(@class, 'track-name')]"), value.track)
RETURN NONE
)
LET list = ELEMENT(doc, '.track-list')
LET actual = (
FOR item IN ELEMENTS(doc, '.track-list li')
LIMIT 2
RETURN {
artist: TRIM(INNER_TEXT(item, '.track-artist')),
track: TRIM(INNER_TEXT(item, '.track-name'))
}
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,12 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "form")
LET form = ELEMENT(doc, "#page-form")
INPUT(form, X('//*[@id="text_input"]'), "foo")
LET output = ELEMENT(doc, "#text_output")
RETURN T::EQ(output.innerText, "foo")

View File

@ -0,0 +1,12 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
WAIT_ELEMENT(doc, "form")
LET form = ELEMENT(doc, "#page-form")
INPUT(form, X('//*[@id="text_input"]'), "foo", 100)
LET output = ELEMENT(doc, "#text_output")
RETURN T::EQ(output.innerText, "foo")

View File

@ -0,0 +1,10 @@
LET url = @lab.cdn.dynamic + "/#/events"
LET page = DOCUMENT(url, true)
PRESS_SELECTOR(page, X("//*[@id='press-input']"), "Enter")
WAIT(100)
T::EQ(INNER_TEXT(page, "#press-content"), "Enter")
RETURN NONE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, "#root")?
T::NOT::NONE(el)
RETURN TRUE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, X("//*[@id='root']"))?
T::NOT::NONE(el)
RETURN TRUE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
LET els = ELEMENTS(doc, ".form-control")
T::NOT::EMPTY(els)
RETURN TRUE

View File

@ -0,0 +1,8 @@
LET url = @lab.cdn.dynamic + "?redirect=/forms"
LET doc = DOCUMENT(url, true)
LET els = ELEMENTS(doc, X(".//*[contains(@class, 'form-control')]"))
T::NOT::EMPTY(els)
RETURN TRUE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.dynamic
LET doc = DOCUMENT(url, true)
LET el = ELEMENT(doc, "#root")
T::TRUE(ELEMENT_EXISTS(el, X(".//*[contains(@class, 'jumbotron')]")))
T::FALSE(ELEMENT_EXISTS(el, X(".//*[contains(@class, 'foo-bar')]")))
RETURN NONE

View File

@ -0,0 +1,7 @@
LET url = @lab.cdn.static + '/overview.html'
LET doc = DOCUMENT(url)
T::TRUE(ELEMENT_EXISTS(doc, X("//[contains(@class, 'section-nav')]")))
T::FALSE(ELEMENT_EXISTS(doc, X("//[contains(@class, 'foo-bar')]")))
RETURN NONE

View File

@ -0,0 +1,7 @@
LET url = @lab.cdn.static + '/overview.html'
LET doc = DOCUMENT(url)
LET expected = '<li class="toc-entry toc-h2"><a href="#containers">Containers</a></li><li class="toc-entry toc-h2"><a href="#responsive-breakpoints">Responsive breakpoints</a></li><li class="toc-entry toc-h2"><a href="#z-index">Z-index</a></li>'
LET actual = INNER_HTML(doc, X("//[contains(@class, 'section-nav')]"))
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), '(\n|\s)', ''), REGEX_REPLACE(expected, '\s', ''))

View File

@ -0,0 +1,14 @@
LET url = @lab.cdn.static + '/overview.html'
LET doc = DOCUMENT(url)
LET expected = [
'<a href="#containers">Containers</a>',
'<a href="#responsive-breakpoints">Responsive breakpoints</a>',
'<a href="#z-index">Z-index</a>'
]
LET actual = (
FOR i IN INNER_HTML_ALL(doc, X("//*[contains(@class, 'section-nav')]/li"))
RETURN TRIM(i)
)
RETURN T::EQ(actual, expected)

View File

@ -0,0 +1,7 @@
LET url = @lab.cdn.static + '/overview.html'
LET doc = DOCUMENT(url)
LET expected = 'ContainersResponsive breakpointsZ-index'
LET actual = INNER_TEXT(doc, '.section-nav')
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), '(\n|\s)', ''), REGEX_REPLACE(expected, '\s', ''))

View File

@ -1,10 +0,0 @@
LET url = @lab.cdn.static + '/simple.html'
LET doc = DOCUMENT(url)
LET expected = `Title Hello world`
LET actual = INNER_TEXT(doc)
LET r1 = '(\s|\")'
LET r2 = '(\n|\s|\")'
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), r2, ''), REGEX_REPLACE(expected, r1, ''))

View File

@ -0,0 +1,7 @@
LET url = @lab.cdn.static + '/overview.html'
LET doc = DOCUMENT(url)
LET expected = 'ContainersResponsive breakpointsZ-index'
LET actual = INNER_TEXT(doc, X("//*[contains(@class, 'section-nav')]"))
RETURN T::EQ(REGEX_REPLACE(TRIM(actual), '(\n|\s)', ''), REGEX_REPLACE(expected, '\s', ''))

View File

@ -0,0 +1,18 @@
LET url = @lab.cdn.static + '/grid.html'
LET doc = DOCUMENT(url)
LET expected = [
"Containers provide a means to center and horizontally pad your site’s contents. Use .container for a responsive pixel width or .container-fluid for width: 100% across all viewport and device sizes.",
"Rows are wrappers for columns. Each column has horizontal padding (called a gutter) for controlling the space between them. This padding is then counteracted on the rows with negative margins. This way, all the content in your columns is visually aligned down the left side.",
"In a grid layout, content must be placed within columns and only columns may be immediate children of rows.",
"Thanks to flexbox, grid columns without a specified width will automatically layout as equal width columns. For example, four instances of .col-sm will each automatically be 25% wide from the small breakpoint and up. See the auto-layout columns section for more examples.",
"Column classes indicate the number of columns you’d like to use out of the possible 12 per row. So, if you want three equal-width columns across, you can use .col-4.",
"Column widths are set in percentages, so they’re always fluid and sized relative to their parent element.",
"Columns have horizontal padding to create the gutters between individual columns, however, you can remove the margin from rows and padding from columns with .no-gutters on the .row.",
"To make the grid responsive, there are five grid breakpoints, one for each responsive breakpoint: all breakpoints (extra small), small, medium, large, and extra large.",
"Grid breakpoints are based on minimum width media queries, meaning they apply to that one breakpoint and all those above it (e.g., .col-sm-4 applies to small, medium, large, and extra large devices, but not the first xs breakpoint).",
"You can use predefined grid classes (like .col-4) or Sass mixins for more semantic markup."
]
LET actual = INNER_TEXT_ALL(doc, X('//body/div[contains(@class, "container-fluid")]/div/main/ul/li'))
RETURN T::EQ(actual, expected)

View File

@ -1,6 +1,6 @@
LET url = @lab.cdn.static + '/simple.html'
LET page = DOCUMENT(url)
LET actual = XPATH(page, "//meta/@charset")
LET actual = XPATH(page, "string(//meta/@charset)")
RETURN T::EQ(actual, ["UTF-8"])
RETURN T::EQ(actual, "UTF-8")

Some files were not shown because too many files have changed in this diff Show More