root/chrome/browser/ui/webui/sync_internals_ui_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/sync_internals_ui.h"

#include <cstddef>
#include <string>

#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/sync/profile_sync_service_mock.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/profile_mock.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/test/test_browser_thread.h"
#include "sync/js/js_arg_list.h"
#include "sync/js/js_event_details.h"
#include "sync/js/js_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::ASCIIToUTF16;

// Rewrite to use WebUI testing infrastructure. Current code below is mostly
// testing how WebUI concrete class serializes function parameters, and that
// SyncInternalsUI::HandleJSEvent/HandleJsReply prefix the given function with
// "chrome.sync." and postfix it with ".fire" or ".handleReply".
// http://crbug.com/110517
/*

namespace {

using browser_sync::HasArgsAsList;
using syncer::JsArgList;
using syncer::JsEventDetails;
using content::BrowserThread;
using content::WebContents;
using testing::_;
using testing::Mock;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;

// Subclass of WebUI to mock out ExecuteJavascript.
class TestSyncWebUI: public WebUI {
 public:
  explicit TestSyncWebUI(WebContents* web_contents)
      : WebUI(web_contents) {}
  virtual ~TestSyncWebUI() {}

  MOCK_METHOD1(ExecuteJavascript, void(const base::string16&));
};

// Tests with non-NULL ProfileSyncService.
class SyncInternalsUITestWithService : public ChromeRenderViewHostTestHarness {
 protected:
  SyncInternalsUITestWithService() : sync_internals_ui_(NULL) {}

  virtual ~SyncInternalsUITestWithService() {}

  virtual void SetUp() {
    NiceMock<ProfileMock>* profile_mock = new NiceMock<ProfileMock>();
    StrictMock<ProfileSyncServiceMock> profile_sync_service_mock;
    EXPECT_CALL(*profile_mock, GetProfileSyncService())
        .WillOnce(Return(&profile_sync_service_mock));
    browser_context_.reset(profile_mock);

    ChromeRenderViewHostTestHarness::SetUp();

    EXPECT_CALL(profile_sync_service_mock, GetJsController())
        .WillOnce(Return(mock_js_controller_.AsWeakPtr()));

    EXPECT_CALL(mock_js_controller_, AddJsEventHandler(_));

    {
      // Needed by |sync_internals_ui_|'s constructor.  The
      // message loop is provided by ChromeRenderViewHostTestHarness.
      content::TestBrowserThread ui_thread_(BrowserThread::UI,
                                            base::MessageLoopForUI::current());
      // |sync_internals_ui_|'s constructor triggers all the
      // expectations above.
      web_ui_.reset(new TestSyncWebUI(web_contents()));
      sync_internals_ui_ = new SyncInternalsUI(web_ui_.get());
      web_ui_->SetController(sync_internals_ui_);
    }

    Mock::VerifyAndClearExpectations(profile_mock);
    Mock::VerifyAndClearExpectations(&mock_js_controller_);
  }

  virtual void TearDown() {
    Mock::VerifyAndClearExpectations(&mock_js_controller_);

    // Called by |sync_internals_ui_|'s destructor.
    EXPECT_CALL(mock_js_controller_,
                RemoveJsEventHandler(sync_internals_ui_));
    sync_internals_ui_ = NULL;
    web_ui_.reset();

    ChromeRenderViewHostTestHarness::TearDown();
  }

  StrictMock<browser_sync::MockJsController> mock_js_controller_;
  scoped_ptr<TestSyncWebUI> web_ui_;
  SyncInternalsUI* sync_internals_ui_;
};

TEST_F(SyncInternalsUITestWithService, HandleJsEvent) {
  EXPECT_CALL(*web_ui_,
              ExecuteJavascript(
                  ASCIIToUTF16("chrome.sync.testMessage.fire({});")));

  sync_internals_ui_->HandleJsEvent("testMessage", JsEventDetails());
}

TEST_F(SyncInternalsUITestWithService, HandleJsReply) {
  EXPECT_CALL(
      *web_ui_,
      ExecuteJavascript(
          ASCIIToUTF16("chrome.sync.testMessage.handleReply(5,true);")));

  base::ListValue args;
  args.Append(base::Value::CreateIntegerValue(5));
  args.Append(base::Value::CreateBooleanValue(true));
  sync_internals_ui_->HandleJsReply("testMessage", JsArgList(&args));
}

TEST_F(SyncInternalsUITestWithService, OnWebUISendBasic) {
  const std::string& name = "testName";
  base::ListValue args;
  args.Append(base::Value::CreateIntegerValue(10));

  EXPECT_CALL(mock_js_controller_,
              ProcessJsMessage(name, HasArgsAsList(args), _));

  sync_internals_ui_->OverrideHandleWebUIMessage(GURL(), name, args);
}

// Tests with NULL ProfileSyncService.
class SyncInternalsUITestWithoutService
    : public ChromeRenderViewHostTestHarness {
 protected:
  SyncInternalsUITestWithoutService() : sync_internals_ui_(NULL) {}

  virtual ~SyncInternalsUITestWithoutService() {}

  virtual void SetUp() {
    NiceMock<ProfileMock>* profile_mock = new NiceMock<ProfileMock>();
    EXPECT_CALL(*profile_mock, GetProfileSyncService())
        .WillOnce(Return(static_cast<ProfileSyncService*>(NULL)));
    browser_context_.reset(profile_mock);

    ChromeRenderViewHostTestHarness::SetUp();

    {
      // Needed by |sync_internals_ui_|'s constructor.  The
      // message loop is provided by ChromeRenderViewHostTestHarness.
      content::TestBrowserThread ui_thread_(BrowserThread::UI,
                                            base::MessageLoopForUI::current());
      // |sync_internals_ui_|'s constructor triggers all the
      // expectations above.
      web_ui_.reset(new TestSyncWebUI(web_contents()));
      sync_internals_ui_ = new SyncInternalsUI(web_ui_.get());
      web_ui_->SetController(sync_internals_ui_);
    }

    Mock::VerifyAndClearExpectations(profile_mock);
  }

  scoped_ptr<TestSyncWebUI> web_ui_;
  SyncInternalsUI* sync_internals_ui_;
};

TEST_F(SyncInternalsUITestWithoutService, HandleJsEvent) {
  EXPECT_CALL(*web_ui_,
              ExecuteJavascript(
                  ASCIIToUTF16("chrome.sync.testMessage.fire({});")));

  sync_internals_ui_->HandleJsEvent("testMessage", JsEventDetails());
}

TEST_F(SyncInternalsUITestWithoutService, HandleJsReply) {
  EXPECT_CALL(
      *web_ui_,
      ExecuteJavascript(
          ASCIIToUTF16("chrome.sync.testMessage.handleReply(5,true);")));

  base::ListValue args;
  args.Append(base::Value::CreateIntegerValue(5));
  args.Append(base::Value::CreateBooleanValue(true));
  sync_internals_ui_->HandleJsReply(
      "testMessage", JsArgList(&args));
}

TEST_F(SyncInternalsUITestWithoutService, OnWebUISendBasic) {
  const std::string& name = "testName";
  base::ListValue args;
  args.Append(base::Value::CreateIntegerValue(5));

  // Should drop the message.
  sync_internals_ui_->OverrideHandleWebUIMessage(GURL(), name, args);
}

// TODO(lipalani) - add a test case to test about:sync with a non null
// service.
TEST_F(SyncInternalsUITestWithoutService, OnWebUISendGetAboutInfo) {
  const char kAboutInfoCall[] =
      "chrome.sync.getAboutInfo.handleReply({\"summary\":\"SYNC DISABLED\"});";
  EXPECT_CALL(*web_ui_,
              ExecuteJavascript(ASCIIToUTF16(kAboutInfoCall)));

  base::ListValue args;
  sync_internals_ui_->OverrideHandleWebUIMessage(
      GURL(), "getAboutInfo", args);
}

}  // namespace

*/

/* [<][>][^][v][top][bottom][index][help] */