@@ -6,168 +6,168 @@ import org.hildan.chrome.devtools.domains.dom.*
66import org.hildan.chrome.devtools.domains.runtime.RemoteObjectSubtype
77import org.hildan.chrome.devtools.protocol.*
88import org.hildan.chrome.devtools.sessions.*
9+ import org.junit.jupiter.api.BeforeEach
910import org.junit.jupiter.api.Test
11+ import org.junit.jupiter.api.extension.RegisterExtension
1012import org.testcontainers.*
1113import kotlin.test.*
1214import kotlin.time.Duration.Companion.seconds
1315
1416abstract class LocalIntegrationTestBase : IntegrationTestBase () {
1517
18+ companion object {
19+ @RegisterExtension
20+ val resourceServer = TestResourcesServerExtension ()
21+ }
22+
23+ @BeforeEach
24+ fun register () {
25+ Testcontainers .exposeHostPorts(resourceServer.port)
26+ }
27+
28+ protected suspend fun PageSession.gotoTestPageResource (resourcePath : String ) {
29+ goto(" http://host.testcontainers.internal:${resourceServer.port} /$resourcePath " )
30+ }
31+
1632 @OptIn(ExperimentalChromeApi ::class )
1733 @Test
1834 fun basicFlow_fileScheme () = runTestWithRealTime {
19- withResourceServerForTestcontainers {
20- chromeWebSocket().use { browser ->
21- val pageSession = browser.newPage()
22- val targetId = pageSession.metaData.targetId
23-
24- pageSession.use { page ->
25- page.gotoTestPageResource(" basic.html" )
26- assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
27- assertTrue(browser.hasTarget(targetId), " the new target should be listed" )
28- }
29- assertFalse(browser.hasTarget(targetId), " the new target should be closed (not listed)" )
35+ chromeWebSocket().use { browser ->
36+ val pageSession = browser.newPage()
37+ val targetId = pageSession.metaData.targetId
38+
39+ pageSession.use { page ->
40+ page.gotoTestPageResource(" basic.html" )
41+ assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
42+ assertTrue(browser.hasTarget(targetId), " the new target should be listed" )
3043 }
44+ assertFalse(browser.hasTarget(targetId), " the new target should be closed (not listed)" )
3145 }
3246 }
3347
3448 @OptIn(ExperimentalChromeApi ::class )
3549 @Test
3650 fun basicFlow_httpScheme () = runTestWithRealTime {
37- withResourceServerForTestcontainers {
38- chromeWebSocket().use { browser ->
39- val pageSession = browser.newPage()
40- val targetId = pageSession.metaData.targetId
41-
42- pageSession.use { page ->
43- page.gotoTestPageResource(" basic.html" )
44- assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
45- assertTrue(browser.hasTarget(targetId), " the new target should be listed" )
46- }
47- assertFalse(browser.hasTarget(targetId), " the new target should be closed (not listed)" )
51+ chromeWebSocket().use { browser ->
52+ val pageSession = browser.newPage()
53+ val targetId = pageSession.metaData.targetId
54+
55+ pageSession.use { page ->
56+ page.gotoTestPageResource(" basic.html" )
57+ assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
58+ assertTrue(browser.hasTarget(targetId), " the new target should be listed" )
4859 }
60+ assertFalse(browser.hasTarget(targetId), " the new target should be closed (not listed)" )
4961 }
5062 }
5163
5264 @Test
5365 fun page_getTargets_fileScheme () = runTestWithRealTime {
54- withResourceServerForTestcontainers {
55- chromeWebSocket().use { browser ->
56- browser.newPage().use { page ->
57- page.gotoTestPageResource(" basic.html" )
58- val targets = page.target.getTargets().targetInfos
59- val targetInfo = targets.first { it.targetId == page.metaData.targetId }
60- assertEquals(" page" , targetInfo.type)
61- assertTrue(targetInfo.attached)
62- assertTrue(targetInfo.url.contains(" basic.html" ))
63- }
66+ chromeWebSocket().use { browser ->
67+ browser.newPage().use { page ->
68+ page.gotoTestPageResource(" basic.html" )
69+ val targets = page.target.getTargets().targetInfos
70+ val targetInfo = targets.first { it.targetId == page.metaData.targetId }
71+ assertEquals(" page" , targetInfo.type)
72+ assertTrue(targetInfo.attached)
73+ assertTrue(targetInfo.url.contains(" basic.html" ))
6474 }
6575 }
6676 }
6777
6878 @Test
6979 fun page_getTargets_httpScheme () = runTestWithRealTime {
70- withResourceServerForTestcontainers {
71- chromeWebSocket().use { browser ->
72- browser.newPage().use { page ->
73- page.gotoTestPageResource(" basic.html" )
74- val targets = page.target.getTargets().targetInfos
75- val targetInfo = targets.first { it.targetId == page.metaData.targetId }
76- assertEquals(" page" , targetInfo.type)
77- assertTrue(targetInfo.attached)
78- assertTrue(targetInfo.url.contains(" basic.html" ))
79- }
80+ chromeWebSocket().use { browser ->
81+ browser.newPage().use { page ->
82+ page.gotoTestPageResource(" basic.html" )
83+ val targets = page.target.getTargets().targetInfos
84+ val targetInfo = targets.first { it.targetId == page.metaData.targetId }
85+ assertEquals(" page" , targetInfo.type)
86+ assertTrue(targetInfo.attached)
87+ assertTrue(targetInfo.url.contains(" basic.html" ))
8088 }
8189 }
8290 }
8391
8492 @OptIn(ExperimentalChromeApi ::class )
8593 @Test
8694 fun page_goto () = runTestWithRealTime {
87- withResourceServerForTestcontainers {
88- chromeWebSocket().use { browser ->
89- browser.newPage().use { page ->
90- page.gotoTestPageResource(" basic.html" )
91- assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
92-
93- page.gotoTestPageResource(" other.html" )
94- assertEquals(" Other tab title" , page.target.getTargetInfo().targetInfo.title)
95- val nodeId = withTimeoutOrNull(5 .seconds) {
96- page.dom.awaitNodeBySelector(" p[class='some-p-class']" )
97- }
98- assertNotNull(
99- nodeId,
100- " timed out while waiting for DOM node with attribute: p[class='some-p-class']"
101- )
102-
103- val getOuterHTMLResponse = page.dom.getOuterHTML(GetOuterHTMLRequest (nodeId = nodeId))
104- assertTrue(getOuterHTMLResponse.outerHTML.contains(" <p class=\" some-p-class\" >" ))
95+ chromeWebSocket().use { browser ->
96+ browser.newPage().use { page ->
97+ page.gotoTestPageResource(" basic.html" )
98+ assertEquals(" Basic tab title" , page.target.getTargetInfo().targetInfo.title)
99+
100+ page.gotoTestPageResource(" other.html" )
101+ assertEquals(" Other tab title" , page.target.getTargetInfo().targetInfo.title)
102+ val nodeId = withTimeoutOrNull(5 .seconds) {
103+ page.dom.awaitNodeBySelector(" p[class='some-p-class']" )
105104 }
105+ assertNotNull(
106+ nodeId,
107+ " timed out while waiting for DOM node with attribute: p[class='some-p-class']"
108+ )
109+
110+ val getOuterHTMLResponse = page.dom.getOuterHTML(GetOuterHTMLRequest (nodeId = nodeId))
111+ assertTrue(getOuterHTMLResponse.outerHTML.contains(" <p class=\" some-p-class\" >" ))
106112 }
107113 }
108114 }
109115
110116 @OptIn(ExperimentalChromeApi ::class )
111117 @Test
112118 fun sessionThrowsIOExceptionIfAlreadyClosed () = runTestWithRealTime {
113- withResourceServerForTestcontainers {
114- val browser = chromeWebSocket()
115- val session = browser.newPage()
116- session.gotoTestPageResource(" basic.html" )
119+ val browser = chromeWebSocket()
120+ val session = browser.newPage()
121+ session.gotoTestPageResource(" basic.html" )
117122
118- browser.close()
123+ browser.close()
119124
120- assertFailsWith<RequestNotSentException > {
121- session.target.getTargetInfo().targetInfo
122- }
125+ assertFailsWith<RequestNotSentException > {
126+ session.target.getTargetInfo().targetInfo
123127 }
124128 }
125129
126130 @Test
127131 fun attributesAccess () = runTestWithRealTime {
128- withResourceServerForTestcontainers {
129- chromeWebSocket().use { browser ->
130- browser.newPage().use { page ->
131- page.gotoTestPageResource(" select.html" )
132-
133- val nodeId = page.dom.findNodeBySelector(" select[name=pets] option[selected]" )
134- assertNull(nodeId, " No option is selected in this <select>" )
135-
136- val attributes1 = page.dom.getTypedAttributes(" select[name=pets] option[selected]" )
137- assertNull(attributes1, " No option is selected in this <select>" )
138-
139- val attributes2 = page.dom.getTypedAttributes(" select[name=pets-selected] option[selected]" )
140- assertNotNull(attributes2, " There should be a selected option" )
141- assertEquals(true , attributes2.selected)
142- assertEquals(" cat" , attributes2.value)
143- val value = page.dom.getAttributeValue(" select[name=pets-selected] option[selected]" , " value" )
144- assertEquals(" cat" , value)
145- // Attributes without value (e.g. "selected" in <option name="x" selected />) are returned as empty
146- // strings by the protocol.
147- val selected = page.dom.getAttributeValue(" select[name=pets-selected] option[selected]" , " selected" )
148- assertEquals(" " , selected)
149-
150- val absentValue =
151- page.dom.getAttributeValue(" select[name=pets-selected-without-value] option[selected]" , " value" )
152- assertNull(absentValue, " There is no 'value' attribute in this select option" )
153- }
132+ chromeWebSocket().use { browser ->
133+ browser.newPage().use { page ->
134+ page.gotoTestPageResource(" select.html" )
135+
136+ val nodeId = page.dom.findNodeBySelector(" select[name=pets] option[selected]" )
137+ assertNull(nodeId, " No option is selected in this <select>" )
138+
139+ val attributes1 = page.dom.getTypedAttributes(" select[name=pets] option[selected]" )
140+ assertNull(attributes1, " No option is selected in this <select>" )
141+
142+ val attributes2 = page.dom.getTypedAttributes(" select[name=pets-selected] option[selected]" )
143+ assertNotNull(attributes2, " There should be a selected option" )
144+ assertEquals(true , attributes2.selected)
145+ assertEquals(" cat" , attributes2.value)
146+ val value = page.dom.getAttributeValue(" select[name=pets-selected] option[selected]" , " value" )
147+ assertEquals(" cat" , value)
148+ // Attributes without value (e.g. "selected" in <option name="x" selected />) are returned as empty
149+ // strings by the protocol.
150+ val selected = page.dom.getAttributeValue(" select[name=pets-selected] option[selected]" , " selected" )
151+ assertEquals(" " , selected)
152+
153+ val absentValue =
154+ page.dom.getAttributeValue(" select[name=pets-selected-without-value] option[selected]" , " value" )
155+ assertNull(absentValue, " There is no 'value' attribute in this select option" )
154156 }
155157 }
156158 }
157159
158160 @OptIn(ExperimentalChromeApi ::class )
159161 @Test
160162 fun test_deserialization_unknown_enum () = runTestWithRealTime {
161- withResourceServerForTestcontainers {
162- chromeWebSocket().use { browser ->
163- browser.newPage().use { page ->
164- page.gotoTestPageResource(" basic.html" )
165- val tree = page.accessibility.getFullAXTree() // just test that this doesn't fail
166-
167- assertTrue(" we are no longer testing that unknown AXPropertyName values are deserialized as NotDefinedInProtocol" ) {
168- tree.nodes.any { n ->
169- n.properties.anyUndefinedName() || n.ignoredReasons.anyUndefinedName()
170- }
163+ chromeWebSocket().use { browser ->
164+ browser.newPage().use { page ->
165+ page.gotoTestPageResource(" basic.html" )
166+ val tree = page.accessibility.getFullAXTree() // just test that this doesn't fail
167+
168+ assertTrue(" we are no longer testing that unknown AXPropertyName values are deserialized as NotDefinedInProtocol" ) {
169+ tree.nodes.any { n ->
170+ n.properties.anyUndefinedName() || n.ignoredReasons.anyUndefinedName()
171171 }
172172 }
173173 }
@@ -177,36 +177,20 @@ abstract class LocalIntegrationTestBase : IntegrationTestBase() {
177177 @OptIn(ExperimentalChromeApi ::class )
178178 @Test
179179 fun test_deserialization_RemoteObject_subtype_enum () = runTestWithRealTime {
180- withResourceServerForTestcontainers {
181- chromeWebSocket().use { browser ->
182- browser.newPage().use { page ->
183- page.runtime.enable()
184- val deferredEvent = async(start = CoroutineStart .UNDISPATCHED ) {
185- page.runtime.consoleAPICalledEvents().first()
186- }
187- page.gotoTestPageResource(" trustedtype.html" )
188- val event = deferredEvent.await()
189- // proof that we have to provide this subtype as enum value
190- assertEquals(RemoteObjectSubtype .trustedtype, event.args.first().subtype)
180+ chromeWebSocket().use { browser ->
181+ browser.newPage().use { page ->
182+ page.runtime.enable()
183+ val deferredEvent = async(start = CoroutineStart .UNDISPATCHED ) {
184+ page.runtime.consoleAPICalledEvents().first()
191185 }
186+ page.gotoTestPageResource(" trustedtype.html" )
187+ val event = deferredEvent.await()
188+ // proof that we have to provide this subtype as enum value
189+ assertEquals(RemoteObjectSubtype .trustedtype, event.args.first().subtype)
192190 }
193191 }
194192 }
195193
196- class TestServerContext (val baseUrl : String ) {
197-
198- suspend fun PageSession.gotoTestPageResource (resourcePath : String ) {
199- goto(" $baseUrl /$resourcePath " )
200- }
201- }
202-
203- protected suspend fun withResourceServerForTestcontainers (block : suspend TestServerContext .() -> Unit ) {
204- withResourceHttpServer { port ->
205- Testcontainers .exposeHostPorts(port)
206- TestServerContext (" http://host.testcontainers.internal:$port " ).block()
207- }
208- }
209-
210194 private fun List<AXProperty>?.anyUndefinedName (): Boolean =
211195 this != null && this .any { it.name is AXPropertyName .NotDefinedInProtocol }
212196}
0 commit comments