Skip to content

Commit dce7c4c

Browse files
authored
Add component() method to get scoped Browser instance (#1087)
* tap component * browser not component * docs * dont need proxy * handle page * tests * resolver match * fix cs * test chaining
1 parent 5e038c4 commit dce7c4c

File tree

2 files changed

+152
-6
lines changed

2 files changed

+152
-6
lines changed

src/Browser.php

+21
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,27 @@ public function elsewhereWhenAvailable($selector, Closure $callback, $seconds =
585585
});
586586
}
587587

588+
/**
589+
* Return a browser scoped to the given component.
590+
*
591+
* @param \Laravel\Dusk\Component $component
592+
* @return \Laravel\Dusk\Browser
593+
*/
594+
public function component(Component $component)
595+
{
596+
$browser = new static(
597+
$this->driver, new ElementResolver($this->driver, $this->resolver->format($component))
598+
);
599+
600+
if ($this->page) {
601+
$browser->onWithoutAssert($this->page);
602+
}
603+
604+
$browser->onComponent($component, $this->resolver);
605+
606+
return $browser;
607+
}
608+
588609
/**
589610
* Set the current component state.
590611
*

tests/Unit/ComponentTest.php

+131-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function test_within_method_triggers_assertion()
3030
});
3131
}
3232

33-
public function test_resolver_prefix()
33+
public function test_within_method_resolver_prefix()
3434
{
3535
$driver = m::mock(stdClass::class);
3636
$browser = new Browser($driver);
@@ -48,7 +48,7 @@ public function test_resolver_prefix()
4848
});
4949
}
5050

51-
public function test_component_macros()
51+
public function test_within_method_component_macros()
5252
{
5353
$driver = m::mock(stdClass::class);
5454
$browser = new Browser($driver);
@@ -64,7 +64,7 @@ public function test_component_macros()
6464
});
6565
}
6666

67-
public function test_component_elements()
67+
public function test_within_method_component_elements()
6868
{
6969
$driver = m::mock(stdClass::class);
7070
$browser = new Browser($driver);
@@ -85,7 +85,7 @@ public function test_component_elements()
8585
});
8686
}
8787

88-
public function test_root_selector_can_be_dusk_hook()
88+
public function test_within_method_root_selector_can_be_dusk_hook()
8989
{
9090
$driver = m::mock(stdClass::class);
9191
$browser = new Browser($driver);
@@ -98,7 +98,7 @@ public function test_root_selector_can_be_dusk_hook()
9898
});
9999
}
100100

101-
public function test_root_selector_can_be_element_alias()
101+
public function test_within_method_root_selector_can_be_element_alias()
102102
{
103103
$driver = m::mock(stdClass::class);
104104
$browser = new Browser($driver);
@@ -111,7 +111,7 @@ public function test_root_selector_can_be_element_alias()
111111
});
112112
}
113113

114-
public function test_component_overrides_page_macros()
114+
public function test_within_method_component_overrides_page_macros()
115115
{
116116
$driver = m::mock(stdClass::class);
117117
$browser = new Browser($driver);
@@ -129,6 +129,131 @@ public function test_component_overrides_page_macros()
129129
$this->assertTrue($browser->page->macroed);
130130
});
131131
}
132+
133+
public function test_within_method_chains()
134+
{
135+
$driver = m::mock(stdClass::class);
136+
$browser = new Browser($driver);
137+
138+
$browser->within(new TestComponent, function ($browser) {
139+
$this->assertInstanceOf(TestComponent::class, $browser->component);
140+
$this->assertTrue($browser->component->asserted);
141+
$this->assertSame('body #component-root', $browser->resolver->prefix);
142+
$this->assertFalse($browser->component->macroed);
143+
144+
$browser->doSomething();
145+
$this->assertTrue($browser->component->macroed);
146+
})->within(new TestNestedComponent, function ($browser) {
147+
$this->assertInstanceOf(TestNestedComponent::class, $browser->component);
148+
$this->assertTrue($browser->component->asserted);
149+
$this->assertSame('body #nested-root', $browser->resolver->prefix);
150+
$this->assertFalse($browser->component->macroed);
151+
152+
$browser->doSomething();
153+
$this->assertTrue($browser->component->macroed);
154+
});
155+
}
156+
157+
public function test_component_method_triggers_assertion()
158+
{
159+
$driver = m::mock(stdClass::class);
160+
$browser = new Browser($driver);
161+
162+
$scoped = $browser->component(new TestComponent);
163+
$this->assertTrue($scoped->component->asserted);
164+
165+
$nested = $scoped->component(new TestNestedComponent);
166+
$this->assertTrue($nested->component->asserted);
167+
}
168+
169+
public function test_component_method_resolver_prefix()
170+
{
171+
$driver = m::mock(stdClass::class);
172+
$browser = new Browser($driver);
173+
174+
$scoped = $browser->component(new TestComponent);
175+
$this->assertSame('body #component-root', $scoped->resolver->prefix);
176+
177+
$nested = $scoped->component(new TestNestedComponent);
178+
$this->assertSame('body #component-root #nested-root', $nested->resolver->prefix);
179+
180+
$nested->with('prefix', function (Browser $browser) {
181+
$this->assertSame('body #component-root #nested-root prefix', $browser->resolver->prefix);
182+
});
183+
}
184+
185+
public function test_component_method_component_macros()
186+
{
187+
$driver = m::mock(stdClass::class);
188+
$browser = new Browser($driver);
189+
190+
$scoped = $browser->component(new TestComponent);
191+
$scoped->doSomething();
192+
$this->assertTrue($scoped->component->macroed);
193+
194+
$nested = $scoped->component(new TestNestedComponent);
195+
$nested->doSomething();
196+
$this->assertTrue($nested->component->macroed);
197+
}
198+
199+
public function test_component_method_component_elements()
200+
{
201+
$driver = m::mock(stdClass::class);
202+
$browser = new Browser($driver);
203+
204+
$scoped = $browser->component(new TestComponent);
205+
$this->assertEquals([
206+
'@component-alias' => '#component-alias',
207+
'@overridden-alias' => '#not-overridden',
208+
], $scoped->resolver->elements);
209+
210+
$nested = $scoped->component(new TestNestedComponent);
211+
$this->assertEquals([
212+
'@nested-alias' => '#nested-alias',
213+
'@overridden-alias' => '#overridden',
214+
'@component-alias' => '#component-alias',
215+
], $nested->resolver->elements);
216+
}
217+
218+
public function test_component_method_root_selector_can_be_dusk_hook()
219+
{
220+
$driver = m::mock(stdClass::class);
221+
$browser = new Browser($driver);
222+
223+
$component = new TestComponent;
224+
$component->selector = '@dusk-hook-root';
225+
226+
$scoped = $browser->component($component);
227+
$this->assertSame('body [dusk="dusk-hook-root"]', $scoped->resolver->prefix);
228+
}
229+
230+
public function test_component_method_root_selector_can_be_element_alias()
231+
{
232+
$driver = m::mock(stdClass::class);
233+
$browser = new Browser($driver);
234+
235+
$component = new TestComponent;
236+
$component->selector = '@component-alias';
237+
238+
$scoped = $browser->component($component);
239+
$this->assertSame('body #component-alias', $scoped->resolver->prefix);
240+
}
241+
242+
public function test_component_method_overrides_page_macros()
243+
{
244+
$driver = m::mock(stdClass::class);
245+
$browser = new Browser($driver);
246+
247+
$browser->on($page = new TestPage);
248+
249+
$scoped = $browser->component(new TestComponent);
250+
$scoped->doSomething();
251+
$this->assertFalse($scoped->page->macroed);
252+
$this->assertTrue($scoped->component->macroed);
253+
254+
$scoped->doPageSpecificThing();
255+
$this->assertTrue($scoped->page->macroed);
256+
}
132257
}
133258

134259
class TestPage extends Page

0 commit comments

Comments
 (0)