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 "mojo/services/html_viewer/ax_provider_impl.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/stats_counters.h"
10 #include "gin/public/isolate_holder.h"
11 #include "mojo/services/html_viewer/blink_platform_impl.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebData.h"
14 #include "third_party/WebKit/public/platform/WebURL.h"
15 #include "third_party/WebKit/public/web/WebFrameClient.h"
16 #include "third_party/WebKit/public/web/WebKit.h"
17 #include "third_party/WebKit/public/web/WebLocalFrame.h"
18 #include "third_party/WebKit/public/web/WebView.h"
19 #include "third_party/WebKit/public/web/WebViewClient.h"
23 using blink::WebLocalFrame
;
24 using blink::WebFrameClient
;
27 using blink::WebViewClient
;
33 class TestWebFrameClient
: public WebFrameClient
{
35 virtual ~TestWebFrameClient() {}
36 virtual void didStopLoading() { base::MessageLoop::current()->Quit(); }
39 class TestWebViewClient
: public WebViewClient
{
41 virtual bool allowsBrokenNullLayerTreeView() const { return true; }
42 virtual ~TestWebViewClient() {}
45 class AxProviderImplTest
: public testing::Test
{
47 AxProviderImplTest() {
48 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
49 gin::IsolateHolder::LoadV8Snapshot();
51 blink::initialize(new BlinkPlatformImpl());
54 virtual ~AxProviderImplTest() override
{ blink::shutdown(); }
57 base::MessageLoopForUI message_loop
;
61 void OnNodes(Array
<AxNodePtr
> nodes
) { this->nodes
= nodes
.Pass(); }
62 Array
<AxNodePtr
> nodes
;
65 AxNodePtr
CreateNode(int id
,
68 const RectPtr
& bounds
,
69 const std::string
& url
,
70 const std::string
& text
) {
71 AxNodePtr
node(AxNode::New());
73 node
->parent_id
= parent_id
;
74 node
->next_sibling_id
= next_sibling_id
;
75 node
->bounds
= bounds
.Clone();
78 node
->link
= AxLink::New();
79 node
->link
->url
= url
;
82 node
->text
= AxText::New();
83 node
->text
->content
= text
;
90 TEST_F(AxProviderImplTest
, Basic
) {
91 TestWebViewClient web_view_client
;
92 TestWebFrameClient web_frame_client
;
93 WebView
* view
= WebView::create(&web_view_client
);
94 view
->setMainFrame(WebLocalFrame::create(&web_frame_client
));
95 view
->mainFrame()->loadHTMLString(
98 "href='http://monkey.net'>bar</a>baz</body></html>"),
99 WebURL(GURL("http://someplace.net")));
100 base::MessageLoop::current()->Run();
102 AxProviderImpl
ax_provider_impl(view
);
104 ax_provider_impl
.GetTree(
105 base::Bind(&NodeCatcher::OnNodes
, base::Unretained(&catcher
)));
107 std::map
<uint32
, AxNode
*> lookup
;
108 for (size_t i
= 0; i
< catcher
.nodes
.size(); ++i
) {
109 auto& node
= catcher
.nodes
[i
];
110 lookup
[node
->id
] = node
.get();
113 typedef decltype(lookup
)::value_type MapEntry
;
114 auto is_link
= [](MapEntry pair
) { return pair
.second
->link
.get(); };
115 auto is_text
= [](MapEntry pair
, const char* content
) {
116 return pair
.second
->text
.get() &&
117 pair
.second
->text
->content
.To
<std::string
>() == content
;
119 auto is_foo
= [&is_text
](MapEntry pair
) { return is_text(pair
, "foo"); };
120 auto is_bar
= [&is_text
](MapEntry pair
) { return is_text(pair
, "bar"); };
121 auto is_baz
= [&is_text
](MapEntry pair
) { return is_text(pair
, "baz"); };
123 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_link
));
124 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_foo
));
125 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_bar
));
126 EXPECT_EQ(1, std::count_if(lookup
.begin(), lookup
.end(), is_baz
));
128 auto root
= lookup
[1u];
129 auto link
= std::find_if(lookup
.begin(), lookup
.end(), is_link
)->second
;
130 auto foo
= std::find_if(lookup
.begin(), lookup
.end(), is_foo
)->second
;
131 auto bar
= std::find_if(lookup
.begin(), lookup
.end(), is_bar
)->second
;
132 auto baz
= std::find_if(lookup
.begin(), lookup
.end(), is_baz
)->second
;
134 // Test basic content of each node. The properties we copy (like parent_id)
135 // here are tested differently below.
136 EXPECT_TRUE(CreateNode(root
->id
, 0, 0, root
->bounds
, "", "")->Equals(*root
));
137 EXPECT_TRUE(CreateNode(foo
->id
, foo
->parent_id
, 0, foo
->bounds
, "", "foo")
139 EXPECT_TRUE(CreateNode(bar
->id
, bar
->parent_id
, 0, bar
->bounds
, "", "bar")
141 EXPECT_TRUE(CreateNode(baz
->id
, baz
->parent_id
, 0, baz
->bounds
, "", "baz")
143 EXPECT_TRUE(CreateNode(link
->id
,
145 link
->next_sibling_id
,
147 "http://monkey.net/",
150 auto is_descendant_of
= [&lookup
](uint32 id
, uint32 ancestor
) {
151 for (; (id
= lookup
[id
]->parent_id
) != 0;) {
158 EXPECT_TRUE(is_descendant_of(bar
->id
, link
->id
));
159 for (auto pair
: lookup
) {
160 AxNode
* node
= pair
.second
;
162 EXPECT_TRUE(is_descendant_of(node
->id
, 1u));
163 if (node
!= link
&& node
!= foo
&& node
!= bar
&& node
!= baz
) {
164 EXPECT_TRUE(CreateNode(node
->id
,
166 node
->next_sibling_id
,
173 // TODO(aa): Test bounds.
174 // TODO(aa): Test sibling ordering of foo/bar/baz.