1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/html_viewer/ax_provider_impl.h"
8 #include "base/message_loop/message_loop.h"
9 #include "components/html_viewer/blink_platform_impl.h"
10 #include "gin/v8_initializer.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/WebKit/public/platform/WebData.h"
13 #include "third_party/WebKit/public/platform/WebURL.h"
14 #include "third_party/WebKit/public/web/WebFrameClient.h"
15 #include "third_party/WebKit/public/web/WebKit.h"
16 #include "third_party/WebKit/public/web/WebLocalFrame.h"
17 #include "third_party/WebKit/public/web/WebView.h"
18 #include "third_party/WebKit/public/web/WebViewClient.h"
22 using blink::WebLocalFrame
;
23 using blink::WebFrameClient
;
26 using blink::WebViewClient
;
30 using mojo::AxNodePtr
;
34 class TestWebFrameClient
: public WebFrameClient
{
36 ~TestWebFrameClient() override
{}
37 void didStopLoading() override
{ base::MessageLoop::current()->Quit(); }
40 class TestWebViewClient
: public WebViewClient
{
42 bool allowsBrokenNullLayerTreeView() const override
{ return true; }
43 virtual ~TestWebViewClient() {}
46 class AxProviderImplTest
: public testing::Test
{
48 AxProviderImplTest() {
49 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
50 gin::V8Initializer::LoadV8Snapshot();
52 blink::initialize(new html_viewer::BlinkPlatformImpl(nullptr));
55 ~AxProviderImplTest() override
{ blink::shutdown(); }
58 base::MessageLoopForUI message_loop
;
62 void OnNodes(Array
<AxNodePtr
> nodes
) { this->nodes
= nodes
.Pass(); }
63 Array
<AxNodePtr
> nodes
;
66 AxNodePtr
CreateNode(int id
,
69 const mojo::RectPtr
& bounds
,
70 const std::string
& url
,
71 const std::string
& text
) {
72 AxNodePtr
node(AxNode::New());
74 node
->parent_id
= parent_id
;
75 node
->next_sibling_id
= next_sibling_id
;
76 node
->bounds
= bounds
.Clone();
79 node
->link
= mojo::AxLink::New();
80 node
->link
->url
= url
;
83 node
->text
= mojo::AxText::New();
84 node
->text
->content
= text
;
91 TEST_F(AxProviderImplTest
, Basic
) {
92 TestWebViewClient web_view_client
;
93 TestWebFrameClient web_frame_client
;
94 WebView
* view
= WebView::create(&web_view_client
);
95 view
->setMainFrame(WebLocalFrame::create(&web_frame_client
));
96 view
->mainFrame()->loadHTMLString(
99 "href='http://monkey.net'>bar</a>baz</body></html>"),
100 WebURL(GURL("http://someplace.net")));
101 base::MessageLoop::current()->Run();
103 html_viewer::AxProviderImpl
ax_provider_impl(view
);
105 ax_provider_impl
.GetTree(
106 base::Bind(&NodeCatcher::OnNodes
, base::Unretained(&catcher
)));
108 std::map
<uint32
, AxNode
*> lookup
;
109 for (size_t i
= 0; i
< catcher
.nodes
.size(); ++i
) {
110 auto& node
= catcher
.nodes
[i
];
111 lookup
[node
->id
] = node
.get();
114 typedef decltype(lookup
)::value_type MapEntry
;
115 auto is_link
= [](MapEntry pair
) { return !pair
.second
->link
.is_null(); };
116 auto is_text
= [](MapEntry pair
, const char* content
) {
117 return !pair
.second
->text
.is_null() &&
118 pair
.second
->text
->content
.To
<std::string
>() == content
;
120 auto is_foo
= [&is_text
](MapEntry pair
) { return is_text(pair
, "foo"); };
121 auto is_bar
= [&is_text
](MapEntry pair
) { return is_text(pair
, "bar"); };
122 auto is_baz
= [&is_text
](MapEntry pair
) { return is_text(pair
, "baz"); };
124 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_link
));
125 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_foo
));
126 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_bar
));
127 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_baz
));
129 auto root
= lookup
[1u];
130 auto link
= std::find_if(lookup
.begin(), lookup
.end(), is_link
)->second
;
131 auto foo
= std::find_if(lookup
.begin(), lookup
.end(), is_foo
)->second
;
132 auto bar
= std::find_if(lookup
.begin(), lookup
.end(), is_bar
)->second
;
133 auto baz
= std::find_if(lookup
.begin(), lookup
.end(), is_baz
)->second
;
135 // Test basic content of each node. The properties we copy (like parent_id)
136 // here are tested differently below.
137 EXPECT_TRUE(CreateNode(root
->id
, 0, 0, root
->bounds
, "", "")->Equals(*root
));
138 EXPECT_TRUE(CreateNode(foo
->id
, foo
->parent_id
, 0, foo
->bounds
, "", "foo")
140 EXPECT_TRUE(CreateNode(bar
->id
, bar
->parent_id
, 0, bar
->bounds
, "", "bar")
142 EXPECT_TRUE(CreateNode(baz
->id
, baz
->parent_id
, 0, baz
->bounds
, "", "baz")
144 EXPECT_TRUE(CreateNode(link
->id
,
146 link
->next_sibling_id
,
148 "http://monkey.net/",
151 auto is_descendant_of
= [&lookup
](uint32 id
, uint32 ancestor
) {
152 for (; (id
= lookup
[id
]->parent_id
) != 0;) {
159 EXPECT_TRUE(is_descendant_of(bar
->id
, link
->id
));
160 for (auto pair
: lookup
) {
161 AxNode
* node
= pair
.second
;
163 EXPECT_TRUE(is_descendant_of(node
->id
, 1u));
164 if (node
!= link
&& node
!= foo
&& node
!= bar
&& node
!= baz
) {
165 EXPECT_TRUE(CreateNode(node
->id
,
167 node
->next_sibling_id
,
174 // TODO(aa): Test bounds.
175 // TODO(aa): Test sibling ordering of foo/bar/baz.