text:
// Copyright 2018 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 <ctime>
#include <list>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_list.h"
#include "base/command_line.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/autofill/autofill_uitest_util.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/test/integration/sync_service_impl_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/autofill/payments/local_card_migration_bubble_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/local_card_migration_dialog_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h"
#include "chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.h"
#include "chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.h"
#include "chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h"
#include "chrome/browser/ui/views/autofill/payments/migratable_card_view.h"
#include "chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_container.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_controller.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_loading_indicator_view.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/browser/web_data_service_factory.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/form_data_importer.h"
#include "components/autofill/core/browser/payments/credit_card_save_manager.h"
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include "components/autofill/core/browser/payments/payments_util.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/test_event_waiter.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/sync/test/fake_server/fake_server.h"
#include "components/sync/test/fake_server/fake_server_network_resources.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/base_event_utils.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/layout/animating_layout_manager.h"
#include "ui/views/layout/animating_layout_manager_test_util.h"
#include "ui/views/test/widget_test.h"

using base::Bucket;
using testing::ElementsAre;

namespace autofill {

namespace {

ACTION_P(QuitMessageLoop, loop) {
  loop->Quit();
}

constexpr char kURLGetUploadDetailsRequest[] =
    "https://payments.google.com/payments/apis/chromepaymentsservice/"
    "getdetailsforsavecard";
constexpr char kURLMigrateCardRequest[] =
    "https://payments.google.com/payments/apis-secure/chromepaymentsservice/"
    "migratecards"
    "?s7e_suffix=chromewallet";

constexpr char kResponseGetUploadDetailsSuccess[] =
    "{\"legal_message\":{\"line\":[{\"template\":\"Legal message template with "
    "link: "
    "{0}.\",\"template_parameter\":[{\"display_text\":\"Link\",\"url\":\"https:"
    "//www.example.com/\"}]}]},\"context_token\":\"dummy_context_token\"}";
constexpr char kResponseGetUploadDetailsFailure[] =
    "{\"error\":{\"code\":\"FAILED_PRECONDITION\",\"user_error_message\":\"An "
    "unexpected error has occurred. Please try again later.\"}}";

constexpr char kResponseMigrateCardSuccess[] =
    "{\"save_result\":[{\"unique_id\":\"0\", \"status\":\"SUCCESS\"}, "
    "{\"unique_id\":\"1\", \"status\":\"SUCCESS\"}], "
    "\"value_prop_display_text\":\"example message.\"}";

constexpr char kCreditCardFormURL[] =
    "/credit_card_upload_form_address_and_cc.html";

constexpr char kFirstCardNumber[] = "5428424047572420";   // Mastercard
constexpr char kSecondCardNumber[] = "4782187095085933";  // Visa
constexpr char kThirdCardNumber[] = "4111111111111111";   // Visa
constexpr char kInvalidCardNumber[] = "4444444444444444";

constexpr double kFakeGeolocationLatitude = 1.23;
constexpr double kFakeGeolocationLongitude = 4.56;

}  // namespace

class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
 public:
  PersonalDataLoadedObserverMock() = default;
  ~PersonalDataLoadedObserverMock() = default;

  MOCK_METHOD0(OnPersonalDataChanged, void());
};

class LocalCardMigrationBrowserTest
    : public SyncTest,
      public LocalCardMigrationManager::ObserverForTest {
 public:
  LocalCardMigrationBrowserTest(const LocalCardMigrationBrowserTest&) = delete;
  LocalCardMigrationBrowserTest& operator=(
      const LocalCardMigrationBrowserTest&) = delete;

 protected:
  // Various events that can be waited on by the DialogEventWaiter.
  enum class DialogEvent : int {
    REQUESTED_LOCAL_CARD_MIGRATION,
    RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
    SENT_MIGRATE_CARDS_REQUEST,
    RECEIVED_MIGRATE_CARDS_RESPONSE
  };

  LocalCardMigrationBrowserTest() : SyncTest(SINGLE_CLIENT) {}

  ~LocalCardMigrationBrowserTest() override {}

  void SetUpOnMainThread() override {
    SyncTest::SetUpOnMainThread();

    // Set up the HTTPS server (uses the embedded_test_server).
    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
    embedded_test_server()->ServeFilesFromSourceDirectory(
        "components/test/data/autofill");
    embedded_test_server()->StartAcceptingConnections();

    ASSERT_TRUE(SetupClients());
    chrome::NewTab(GetBrowser(0));

    // Set up the URL loader factory for the payments client so we can intercept
    // those network requests too.
    test_shared_loader_factory_ =
        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
            &test_url_loader_factory_);
    ContentAutofillDriver::GetForRenderFrameHost(
        GetActiveWebContents()->GetMainFrame())
        ->browser_autofill_manager()
        ->client()
        ->GetPaymentsClient()
        ->set_url_loader_factory_for_testing(test_shared_loader_factory_);

    // Set up this class as the ObserverForTest implementation.
    local_card_migration_manager_ =
        ContentAutofillDriver::GetForRenderFrameHost(
            GetActiveWebContents()->GetMainFrame())
            ->browser_autofill_manager()
            ->client()
            ->GetFormDataImporter()
            ->local_card_migration_manager_.get();

    local_card_migration_manager_->SetEventObserverForTesting(this);
    personal_data_ = PersonalDataManagerFactory::GetForProfile(GetProfile(0));

    // Wait for Personal Data Manager to be fully loaded to prevent that
    // spurious notifications deceive the tests.
    WaitForPersonalDataManagerToBeLoaded(GetProfile(0));

    // Set up the fake geolocation data.
    geolocation_overrider_ =
        std::make_unique<device::ScopedGeolocationOverrider>(
            kFakeGeolocationLatitude, kFakeGeolocationLongitude);

    ASSERT_TRUE(SetupSync());

    // Set the billing_customer_number to designate existence of a Payments
    // account.
    const PaymentsCustomerData data =
        PaymentsCustomerData(/*customer_id=*/"123456");
    SetPaymentsCustomerData(data);

    SetUploadDetailsRpcPaymentsAccepts();
    SetUpMigrateCardsRpcPaymentsAccepts();
  }

  void SetPaymentsCustomerDataOnDBSequence(
      AutofillWebDataService* wds,
      const PaymentsCustomerData& customer_data) {
    DCHECK(wds->GetDBTaskRunner()->RunsTasksInCurrentSequence());
    AutofillTable::FromWebDatabase(wds->GetDatabase())
        ->SetPaymentsCustomerData(&customer_data);
  }

  void SetPaymentsCustomerData(const PaymentsCustomerData& customer_data) {
    scoped_refptr<AutofillWebDataService> wds =
        WebDataServiceFactory::GetAutofillWebDataForProfile(
            GetProfile(0), ServiceAccessType::EXPLICIT_ACCESS);
    base::RunLoop loop;
    wds->GetDBTaskRunner()->PostTaskAndReply(
        FROM_HERE,
        base::BindOnce(
            &LocalCardMigrationBrowserTest::SetPaymentsCustomerDataOnDBSequence,
            base::Unretained(this), base::Unretained(wds.get()), customer_data),
        base::BindOnce(&base::RunLoop::Quit, base::Unretained(&loop)));
    loop.Run();
    WaitForOnPersonalDataChanged();
  }

  void WaitForOnPersonalDataChanged() {
    personal_data_->AddObserver(&personal_data_observer_);
    personal_data_->Refresh();

    base::RunLoop run_loop;
    EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
        .WillRepeatedly(QuitMessageLoop(&run_loop));
    run_loop.Run();
    testing::Mock::VerifyAndClearExpectations(&personal_data_observer_);
    personal_data_->RemoveObserver(&personal_data_observer_);
  }

  void NavigateTo(const std::string& file_path) {
    ASSERT_TRUE(ui_test_utils::NavigateToURL(
        GetBrowser(0), file_path.find("data:") == 0U
                           ? GURL(file_path)
                           : embedded_test_server()->GetURL(file_path)));
  }

  void OnDecideToRequestLocalCardMigration() override {
    if (event_waiter_)
      event_waiter_->OnEvent(DialogEvent::REQUESTED_LOCAL_CARD_MIGRATION);
  }

  void OnReceivedGetUploadDetailsResponse() override {
    if (event_waiter_)
      event_waiter_->OnEvent(DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE);
  }

  void OnSentMigrateCardsRequest() override {
    if (event_waiter_)
      event_waiter_->OnEvent(DialogEvent::SENT_MIGRATE_CARDS_REQUEST);
  }

  void OnReceivedMigrateCardsResponse() override {
    if (event_waiter_)
      event_waiter_->OnEvent(DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE);
  }

  CreditCard SaveLocalCard(std::string card_number,
                           bool set_as_expired_card = false,
                           bool set_nickname = false) {
    CreditCard local_card;
    test::SetCreditCardInfo(&local_card, "John Smith", card_number.c_str(),
                            "12",
                            set_as_expired_card ? test::LastYear().c_str()
                                                : test::NextYear().c_str(),
                            "1");
    local_card.set_guid("00000000-0000-0000-0000-" + card_number.substr(0, 12));
    local_card.set_record_type(CreditCard::LOCAL_CARD);
    if (set_nickname)
      local_card.SetNickname(u"card nickname");

    AddTestCreditCard(GetProfile(0), local_card);
    return local_card;
  }

  CreditCard SaveServerCard(std::string card_number) {
    CreditCard server_card;
    test::SetCreditCardInfo(&server_card, "John Smith", card_number.c_str(),
                            "12", test::NextYear().c_str(), "1");
    server_card.set_guid("00000000-0000-0000-0000-" +
                         card_number.substr(0, 12));
    server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
    server_card.set_server_id("full_id_" + card_number);
    AddTestServerCreditCard(GetProfile(0), server_card);
    return server_card;
  }

  void UseCardAndWaitForMigrationOffer(std::string card_number) {
    // Reusing a card should show the migration offer bubble.
    ResetEventWaiterForSequence(
        {DialogEvent::REQUESTED_LOCAL_CARD_MIGRATION,
         DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
    FillAndSubmitFormWithCard(card_number);
    WaitForObservedEvent();
    WaitForAnimationToComplete();
  }

  void ClickOnSaveButtonAndWaitForMigrationResults() {
    ResetEventWaiterForSequence({DialogEvent::SENT_MIGRATE_CARDS_REQUEST,
                                 DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE});
    ClickOnOkButton(GetLocalCardMigrationMainDialogView());
    WaitForObservedEvent();
  }

  void FillAndSubmitFormWithCard(std::string card_number) {
    NavigateTo(kCreditCardFormURL);
    content::WebContents* web_contents = GetActiveWebContents();

    const std::string click_fill_button_js =
        "(function() { document.getElementById('fill_form').click(); })();";
    ASSERT_TRUE(content::ExecuteScript(web_contents, click_fill_button_js));

    const std::string fill_cc_number_js =
        "(function() { document.getElementsByName(\"cc_number\")[0].value = " +
        card_number + "; })();";
    ASSERT_TRUE(content::ExecuteScript(web_contents, fill_cc_number_js));

    const std::string click_submit_button_js =
        "(function() { document.getElementById('submit').click(); })();";
    content::TestNavigationObserver nav_observer(web_contents);
    ASSERT_TRUE(content::ExecuteScript(web_contents, click_submit_button_js));
    nav_observer.Wait();
  }

  void SetUploadDetailsRpcPaymentsAccepts() {
    test_url_loader_factory()->AddResponse(kURLGetUploadDetailsRequest,
                                           kResponseGetUploadDetailsSuccess);
  }

  void SetUploadDetailsRpcPaymentsDeclines() {
    test_url_loader_factory()->AddResponse(kURLGetUploadDetailsRequest,
                                           kResponseGetUploadDetailsFailure);
  }

  void SetUpMigrateCardsRpcPaymentsAccepts() {
    test_url_loader_factory()->AddResponse(kURLMigrateCardRequest,
                                           kResponseMigrateCardSuccess);
  }

  void ClickOnView(views::View* view) {
    CHECK(view);
    ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                           ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                           ui::EF_LEFT_MOUSE_BUTTON);
    view->OnMousePressed(pressed);
    ui::MouseEvent released_event =
        ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
    view->OnMouseReleased(released_event);
  }

  void ClickOnDialogViewAndWait(
      views::View* view,
      views::BubbleDialogDelegateView* local_card_migration_view) {
    CHECK(local_card_migration_view);
    views::test::WidgetDestroyedWaiter destroyed_waiter(
        local_card_migration_view->GetWidget());
    local_card_migration_view->ResetViewShownTimeStampForTesting();
    views::BubbleFrameView* bubble_frame_view =
        static_cast<views::BubbleFrameView*>(
            local_card_migration_view->GetWidget()
                ->non_client_view()
                ->frame_view());
    bubble_frame_view->ResetViewShownTimeStampForTesting();
    ClickOnView(view);
    destroyed_waiter.Wait();
  }

  views::View* FindViewInDialogById(
      DialogViewId view_id,
      views::BubbleDialogDelegateView* local_card_migration_view) {
    CHECK(local_card_migration_view);

    views::View* specified_view =
        local_card_migration_view->GetViewByID(static_cast<int>(view_id));

    if (!specified_view) {
      specified_view =
          local_card_migration_view->GetWidget()->GetRootView()->GetViewByID(
              static_cast<int>(view_id));
    }

    return specified_view;
  }

  void ClickOnOkButton(
      views::BubbleDialogDelegateView* local_card_migration_view) {
    views::View* ok_button = local_card_migration_view->GetOkButton();

    ClickOnDialogViewAndWait(ok_button, local_card_migration_view);
  }

  void ClickOnCancelButton(
      views::BubbleDialogDelegateView* local_card_migration_view) {
    views::View* cancel_button = local_card_migration_view->GetCancelButton();
    ClickOnDialogViewAndWait(cancel_button, local_card_migration_view);
  }

  LocalCardMigrationBubbleViews* GetLocalCardMigrationOfferBubbleViews() {
    LocalCardMigrationBubbleControllerImpl*
        local_card_migration_bubble_controller_impl =
            LocalCardMigrationBubbleControllerImpl::FromWebContents(
                GetActiveWebContents());
    if (!local_card_migration_bubble_controller_impl)
      return nullptr;
    return static_cast<LocalCardMigrationBubbleViews*>(
        local_card_migration_bubble_controller_impl
            ->local_card_migration_bubble_view());
  }

  views::BubbleDialogDelegateView* GetLocalCardMigrationMainDialogView() {
    LocalCardMigrationDialogControllerImpl*
        local_card_migration_dialog_controller_impl =
            LocalCardMigrationDialogControllerImpl::FromWebContents(
                GetActiveWebContents());
    if (!local_card_migration_dialog_controller_impl)
      return nullptr;
    return static_cast<LocalCardMigrationDialogView*>(
        local_card_migration_dialog_controller_impl
            ->local_card_migration_dialog_view());
  }

  PageActionIconView* GetLocalCardMigrationIconView() {
    BrowserView* browser_view =
        BrowserView::GetBrowserViewForBrowser(GetBrowser(0));
    PageActionIconView* icon =
        browser_view->toolbar_button_provider()->GetPageActionIconView(
            PageActionIconType::kLocalCardMigration);
    if (base::FeatureList::IsEnabled(
            features::kAutofillEnableToolbarStatusChip)) {
      EXPECT_TRUE(
          browser_view->toolbar()->toolbar_account_icon_container()->Contains(
              icon));
    } else {
      EXPECT_TRUE(browser_view->GetLocationBarView()->Contains(icon));
    }
    return icon;
  }

  views::View* GetCloseButton() {
    LocalCardMigrationBubbleViews* local_card_migration_bubble_views =
        static_cast<LocalCardMigrationBubbleViews*>(
            GetLocalCardMigrationOfferBubbleViews());
    CHECK(local_card_migration_bubble_views);
    return local_card_migration_bubble_views->GetBubbleFrameView()
        ->GetCloseButtonForTesting();
  }

  views::View* GetCardListView() {
    return static_cast<LocalCardMigrationDialogView*>(
               GetLocalCardMigrationMainDialogView())
        ->card_list_view_;
  }

  content::WebContents* GetActiveWebContents() {
    return GetBrowser(0)->tab_strip_model()->GetActiveWebContents();
  }

  void ResetEventWaiterForSequence(std::list<DialogEvent> event_sequence) {
    event_waiter_ =
        std::make_unique<EventWaiter<DialogEvent>>(std::move(event_sequence));
  }

  void WaitForObservedEvent() { event_waiter_->Wait(); }

  network::TestURLLoaderFactory* test_url_loader_factory() {
    return &test_url_loader_factory_;
  }

  void WaitForCardDeletion() { WaitForPersonalDataChange(GetProfile(0)); }

  void WaitForAnimationToComplete() {
    if (base::FeatureList::IsEnabled(
            features::kAutofillEnableToolbarStatusChip)) {
      views::test::WaitForAnimatingLayoutManager(
          BrowserView::GetBrowserViewForBrowser(GetBrowser(0))
              ->toolbar()
              ->toolbar_account_icon_container());
    }
  }

  raw_ptr<LocalCardMigrationManager> local_card_migration_manager_;

  raw_ptr<PersonalDataManager> personal_data_;
  PersonalDataLoadedObserverMock personal_data_observer_;

 private:
  std::unique_ptr<autofill::EventWaiter<DialogEvent>> event_waiter_;
  std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
  network::TestURLLoaderFactory test_url_loader_factory_;
  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
  std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_;
};

// TODO(crbug.com/932818): Remove this class after experiment flag is cleaned
// up. Otherwise we need it because the toolbar is init-ed before each test is
// set up. Thus need to enable the feature in the general browsertest SetUp().
class LocalCardMigrationBrowserTestForStatusChip
    : public LocalCardMigrationBrowserTest {
 protected:
  LocalCardMigrationBrowserTestForStatusChip()
      : LocalCardMigrationBrowserTest() {
    feature_list_.InitWithFeatures(
        /*enabled_features=*/{features::kAutofillCreditCardUploadFeedback,
                              features::kAutofillEnableToolbarStatusChip,
                              features::kAutofillUpstream},
        /*disabled_features=*/{});
  }

  ~LocalCardMigrationBrowserTestForStatusChip() override = default;

 private:
  base::test::ScopedFeatureList feature_list_;
};

// Ensures that migration is not offered when user saves a new card.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       UsingNewCardDoesNotShowIntermediateMigrationOffer) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  FillAndSubmitFormWithCard(kSecondCardNumber);

  // No migration bubble should be showing, because the single card upload
  // bubble should be displayed instead.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // No metrics are recorded when migration is not offered.
  histogram_tester.ExpectTotalCount(
      "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}

// Ensures that migration is not offered when payments declines the cards.
IN_PROC_BROWSER_TEST_F(
    LocalCardMigrationBrowserTest,
    IntermediateMigrationOfferDoesNotShowWhenPaymentsDeclines) {
  base::HistogramTester histogram_tester;
  SetUploadDetailsRpcPaymentsDeclines();

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  FillAndSubmitFormWithCard(kFirstCardNumber);

  // No bubble should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // No metrics are recorded when migration is not offered.
  histogram_tester.ExpectTotalCount(
      "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}

// Ensures that the intermediate migration bubble is not shown after reusing
// a saved server card, if there are no other cards to migrate.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ReusingServerCardDoesNotShowIntermediateMigrationOffer) {
  base::HistogramTester histogram_tester;

  SaveServerCard(kFirstCardNumber);
  FillAndSubmitFormWithCard(kFirstCardNumber);

  // No bubble should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // No metrics are recorded when migration is not offered.
  histogram_tester.ExpectTotalCount(
      "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}

// Ensures that the intermediate migration bubble is shown after reusing
// a saved server card, if there is at least one card to migrate.
IN_PROC_BROWSER_TEST_F(
    LocalCardMigrationBrowserTest,
    ReusingServerCardWithMigratableLocalCardShowIntermediateMigrationOffer) {
  base::HistogramTester histogram_tester;

  SaveServerCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  // The intermediate migration bubble should show.
  EXPECT_TRUE(
      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
                           GetLocalCardMigrationOfferBubbleViews())
          ->GetVisible());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationBubbleOffer.FirstShow"),
      ElementsAre(
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
      AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
}

// Ensures that the intermediate migration bubble is not shown after reusing
// a previously saved local card, if there are no other cards to migrate.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ReusingLocalCardDoesNotShowIntermediateMigrationOffer) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  FillAndSubmitFormWithCard(kFirstCardNumber);

  // No migration bubble should be showing, because the single card upload
  // bubble should be displayed instead.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // No metrics are recorded when migration is not offered.
  histogram_tester.ExpectTotalCount(
      "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}

// Ensures that the intermediate migration bubble is triggered after reusing
// a saved local card, if there are multiple local cards available to migrate.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ReusingLocalCardShowsIntermediateMigrationOffer) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  // The intermediate migration bubble should show.
  EXPECT_TRUE(
      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
                           GetLocalCardMigrationOfferBubbleViews())
          ->GetVisible());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationBubbleOffer.FirstShow"),
      ElementsAre(
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
      AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
}

// Ensures that clicking [X] on the offer bubble makes the bubble disappear.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClickingCloseClosesBubble) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());

  // No bubble should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // Metrics
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
      AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
}

// Ensures that the credit card icon will show in location bar.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       CreditCardIconShownInLocationBar) {
  SaveServerCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
}

// Ensures that clicking on the credit card icon in the omnibox reopens the
// offer bubble after closing it.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClickingOmniboxIconReshowsBubble) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());
  ClickOnView(GetLocalCardMigrationIconView());

  // Clicking the icon should reshow the bubble.
  EXPECT_TRUE(
      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
                           GetLocalCardMigrationOfferBubbleViews())
          ->GetVisible());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1)));
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationBubbleOffer.Reshows"),
      ElementsAre(
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
}

// Ensures that accepting the intermediate migration offer opens up the main
// migration dialog.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClickingContinueOpensDialog) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());

  // Dialog should be visible.
  EXPECT_TRUE(FindViewInDialogById(
                  DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_OFFER_DIALOG,
                  GetLocalCardMigrationMainDialogView())
                  ->GetVisible());
  // Intermediate bubble should be gone.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1),
                  Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1),
                  Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1)));
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationBubbleResult.FirstShow",
      AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_ACCEPTED, 1);
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationDialogOffer",
      AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_SHOWN, 1);
}

// Ensures that the migration dialog contains all the valid card stored in
// Chrome browser local storage.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       DialogContainsAllValidMigratableCard) {
  base::HistogramTester histogram_tester;

  CreditCard first_card = SaveLocalCard(kFirstCardNumber);
  CreditCard second_card = SaveLocalCard(kSecondCardNumber);
  SaveLocalCard(kThirdCardNumber, /*set_as_expired_card=*/true);
  SaveLocalCard(kInvalidCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());

  views::View* card_list_view = GetCardListView();
  EXPECT_TRUE(card_list_view->GetVisible());
  ASSERT_EQ(2u, card_list_view->children().size());
  // Cards will be added to database in a reversed order.
  EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->children()[0])
                ->GetCardIdentifierString(),
            second_card.CardIdentifierStringForAutofillDisplay());
  EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->children()[1])
                ->GetCardIdentifierString(),
            first_card.CardIdentifierStringForAutofillDisplay());
}

// Ensures that rejecting the main migration dialog closes the dialog.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClickingCancelClosesDialog) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  // Click the [Cancel] button.
  ClickOnCancelButton(GetLocalCardMigrationMainDialogView());

  // No dialog should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1),
                  Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1),
                  Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1)));
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationDialogUserInteraction",
      AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_CLOSED_CANCEL_BUTTON_CLICKED,
      1);
}

// Ensures that accepting the main migration dialog closes the dialog.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClickingSaveClosesDialog) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button in the bubble.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  // Click the [Save] button in the dialog.
  ClickOnSaveButtonAndWaitForMigrationResults();

  // No dialog should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1),
                  Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1),
                  Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1),
                  Bucket(AutofillMetrics::MAIN_DIALOG_ACCEPTED, 1)));
  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationDialogUserInteraction",
      AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_CLOSED_SAVE_BUTTON_CLICKED,
      1);
}

// Ensures local cards will be deleted from browser local storage after being
// successfully migrated.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       DeleteSuccessfullyMigratedCardsFromLocal) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button in the bubble.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  // Click the [Save] button in the dialog.
  ClickOnSaveButtonAndWaitForMigrationResults();
  WaitForCardDeletion();

  EXPECT_EQ(nullptr, personal_data_->GetCreditCardByNumber(kFirstCardNumber));
  EXPECT_EQ(nullptr, personal_data_->GetCreditCardByNumber(kSecondCardNumber));
}

// Ensures that accepting the main migration dialog adds strikes.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       AcceptingDialogAddsLocalCardMigrationStrikes) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  // Click the [Save] button, should add and log strikes.
  ClickOnSaveButtonAndWaitForMigrationResults();

  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"),
      ElementsAre(Bucket(
          LocalCardMigrationStrikeDatabase::kStrikesToAddWhenDialogClosed, 1)));
}

// Ensures that rejecting the main migration dialog adds strikes.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       RejectingDialogAddsLocalCardMigrationStrikes) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  // Click the [Cancel] button, should add and log strikes.
  ClickOnCancelButton(GetLocalCardMigrationMainDialogView());

  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"),
      ElementsAre(Bucket(
          LocalCardMigrationStrikeDatabase::kStrikesToAddWhenDialogClosed, 1)));
}

// Ensures that rejecting the migration bubble adds strikes.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosingBubbleAddsLocalCardMigrationStrikes) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());

  // No bubble should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"),
      ElementsAre(Bucket(
          LocalCardMigrationStrikeDatabase::kStrikesToAddWhenBubbleClosed, 1)));
}

// Ensures that rejecting the migration bubble repeatedly adds strikes every
// time, even for the same tab. Currently, it adds 3 strikes (out of 6), so this
// test can reliably test it being added twice.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosingBubbleAgainAddsLocalCardMigrationStrikes) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());
  // Do it again for the same tab.
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());

  // No bubble should be showing.
  EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews());
  // Metrics: Added 3 strikes each time, for totals of 3 then 6.
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"),
      ElementsAre(
          Bucket(
              LocalCardMigrationStrikeDatabase::kStrikesToAddWhenBubbleClosed,
              1),
          Bucket(
              LocalCardMigrationStrikeDatabase::kStrikesToAddWhenBubbleClosed *
                  2,
              1)));
}

// Ensures that reshowing and closing bubble after previously closing it does
// not add strikes.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ReshowingBubbleDoesNotAddStrikes) {
  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());
  base::HistogramTester histogram_tester;
  ClickOnView(GetLocalCardMigrationIconView());

  // Clicking the icon should reshow the bubble.
  EXPECT_TRUE(
      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
                           GetLocalCardMigrationOfferBubbleViews())
          ->GetVisible());

  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());

  // Metrics
  histogram_tester.ExpectTotalCount(
      "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}

// TODO(crbug.com/932818): Remove the condition once the experiment is enabled
// on ChromeOS.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Ensures that the credit card icon will show in status chip.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
                       CreditCardIconShownInStatusChip) {
  SaveServerCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
}

// TODO(crbug.com/999510): Crashes flakily on Linux.
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#define MAYBE_ClickingOmniboxIconReshowsBubble \
  DISABLED_ClickingOmniboxIconReshowsBubble
#else
#define MAYBE_ClickingOmniboxIconReshowsBubble ClickingOmniboxIconReshowsBubble
#endif
// Ensures that clicking on the credit card icon in the status chip reopens the
// offer bubble after closing it.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
                       MAYBE_ClickingOmniboxIconReshowsBubble) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());
  ClickOnView(GetLocalCardMigrationIconView());

  // Clicking the icon should reshow the bubble.
  EXPECT_TRUE(
      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
                           GetLocalCardMigrationOfferBubbleViews())
          ->GetVisible());
  // Metrics
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1)));
  EXPECT_THAT(
      histogram_tester.GetAllSamples(
          "Autofill.LocalCardMigrationBubbleOffer.Reshows"),
      ElementsAre(
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
}

#if defined(OS_MAC)
// TODO(crbug.com/823543): Widget activation doesn't work on Mac.
#define MAYBE_ActivateFirstInactiveBubbleForAccessibility \
  DISABLED_ActivateFirstInactiveBubbleForAccessibility
#else
#define MAYBE_ActivateFirstInactiveBubbleForAccessibility \
  ActivateFirstInactiveBubbleForAccessibility
#endif
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
                       MAYBE_ActivateFirstInactiveBubbleForAccessibility) {
  BrowserView* browser_view =
      BrowserView::GetBrowserViewForBrowser(GetBrowser(0));
  ToolbarView* toolbar_view = browser_view->toolbar();
  EXPECT_FALSE(toolbar_view->toolbar_account_icon_container()
                   ->page_action_icon_controller()
                   ->ActivateFirstInactiveBubbleForAccessibility());

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  // Ensures the bubble's widget is visible, but inactive. Active widgets are
  // focused by accessibility, so not of concern.
  views::Widget* widget = GetLocalCardMigrationOfferBubbleViews()->GetWidget();
  widget->Deactivate();
  widget->ShowInactive();
  EXPECT_TRUE(widget->IsVisible());
  EXPECT_FALSE(widget->IsActive());

  EXPECT_TRUE(toolbar_view->toolbar_account_icon_container()
                  ->page_action_icon_controller()
                  ->ActivateFirstInactiveBubbleForAccessibility());

  // Ensure the bubble's widget refreshed appropriately.
  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_TRUE(widget->IsVisible());
  EXPECT_TRUE(widget->IsActive());
}

// Ensures the credit card icon updates its visibility when switching between
// tabs.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
                       IconAndBubbleVisibilityAfterTabSwitching) {
  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);

  // Ensures flow is triggered, and bubble and icon view are visible.
  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_TRUE(GetLocalCardMigrationOfferBubbleViews()->GetVisible());

  AddTabAtIndexToBrowser(GetBrowser(0), 1, GURL("http://example.com/"),
                         ui::PAGE_TRANSITION_TYPED,
                         /*check_navigation_success=*/true);
  TabStripModel* tab_model = GetBrowser(0)->tab_strip_model();
  tab_model->ActivateTabAt(1, {TabStripModel::GestureType::kOther});
  WaitForAnimationToComplete();

  // Ensures bubble and icon go away if user navigates to another tab.
  EXPECT_FALSE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_FALSE(GetLocalCardMigrationOfferBubbleViews());

  tab_model->ActivateTabAt(0, {TabStripModel::GestureType::kOther});
  WaitForAnimationToComplete();

  // If the user navigates back, shows only the icon not the bubble.
  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_FALSE(GetLocalCardMigrationOfferBubbleViews());
}

IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
                       Feedback_CardSavingAnimation) {
  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button in the bubble.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
  test_url_loader_factory()->ClearResponses();

  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_FALSE(GetLocalCardMigrationIconView()
                   ->loading_indicator_for_testing()
                   ->GetAnimating());

  // Click the [Save] button in the dialog.
  ResetEventWaiterForSequence({DialogEvent::SENT_MIGRATE_CARDS_REQUEST});
  ClickOnOkButton(GetLocalCardMigrationMainDialogView());
  WaitForObservedEvent();

  // No dialog should be showing, but icon should display throbber animation.
  EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView());
  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_TRUE(GetLocalCardMigrationIconView()
                  ->loading_indicator_for_testing()
                  ->GetAnimating());

  SetUpMigrateCardsRpcPaymentsAccepts();
  ResetEventWaiterForSequence({DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE});
  WaitForObservedEvent();

  // Icon animation should stop. Dialog stays hidden.
  EXPECT_TRUE(GetLocalCardMigrationIconView()->GetVisible());
  EXPECT_FALSE(GetLocalCardMigrationIconView()
                   ->loading_indicator_for_testing()
                   ->GetAnimating());
}

#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosedReason_BubbleAccepted) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());

  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationBubbleResult.FirstShow",
      AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_ACCEPTED, 1);
}

IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosedReason_BubbleClosed) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  ClickOnDialogViewAndWait(GetCloseButton(),
                           GetLocalCardMigrationOfferBubbleViews());

  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationBubbleResult.FirstShow",
      AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_CLOSED, 1);
}

IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosedReason_BubbleNotInteracted) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  views::test::WidgetDestroyedWaiter destroyed_waiter(
      GetLocalCardMigrationOfferBubbleViews()->GetWidget());
  GetBrowser(0)->tab_strip_model()->CloseAllTabs();
  destroyed_waiter.Wait();

  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationBubbleResult.FirstShow",
      AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_NOT_INTERACTED, 1);
}

IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                       ClosedReason_BubbleLostFocus) {
  base::HistogramTester histogram_tester;

  SaveLocalCard(kFirstCardNumber);
  SaveLocalCard(kSecondCardNumber);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  views::test::WidgetDestroyedWaiter destroyed_waiter(
      GetLocalCardMigrationOfferBubbleViews()->GetWidget());
  GetLocalCardMigrationOfferBubbleViews()->GetWidget()->CloseWithReason(
      views::Widget::ClosedReason::kLostFocus);
  destroyed_waiter.Wait();

  histogram_tester.ExpectUniqueSample(
      "Autofill.LocalCardMigrationBubbleResult.FirstShow",
      AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_LOST_FOCUS, 1);
}

// Tests to ensure the card nickname is shown correctly in the local card
// migration dialog.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, CardIdentifierString) {
  base::HistogramTester histogram_tester;

  CreditCard first_card = SaveLocalCard(
      kFirstCardNumber, /*set_as_expired_card=*/false, /*set_nickname=*/true);
  CreditCard second_card = SaveLocalCard(
      kSecondCardNumber, /*set_as_expired_card=*/false, /*set_nickname=*/false);
  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
  // Click the [Continue] button.
  ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());

  views::View* card_list_view = GetCardListView();
  EXPECT_TRUE(card_list_view->GetVisible());
  ASSERT_EQ(2u, card_list_view->children().size());
  // Cards will be added to database in a reversed order.
  EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->children()[0])
                ->GetCardIdentifierString(),
            second_card.NetworkAndLastFourDigits());
  EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->children()[1])
                ->GetCardIdentifierString(),
            first_card.NicknameAndLastFourDigitsForTesting());
}

// TODO(crbug.com/897998):
// - Add more tests for feedback dialog.

}  // namespace autofill


text:
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;

namespace GestAssoc.Model.Models.Mapping
{
    public class GroupeMap : EntityTypeConfiguration<Groupe>
    {
        public GroupeMap()
        {
            // Primary Key
            this.HasKey(t => t.ID);

            // Properties
            this.Property(t => t.Libelle)
                .HasMaxLength(4000);

            this.Property(t => t.Commentaire)
                .HasMaxLength(4000);

            // Table & Column Mappings
            this.ToTable("Groupes");
            this.Property(t => t.ID).HasColumnName("ID");
            this.Property(t => t.Libelle).HasColumnName("Libelle");
            this.Property(t => t.NbPlaces).HasColumnName("NbPlaces");
            this.Property(t => t.Commentaire).HasColumnName("Commentaire");
            this.Property(t => t.HeureDebut).HasColumnName("HeureDebut");
            this.Property(t => t.HeureFin).HasColumnName("HeureFin");
            this.Property(t => t.JourSemaine).HasColumnName("JourSemaine");
            this.Property(t => t.Saison_ID).HasColumnName("Saison_ID");

            // Relationships
            this.HasOptional(t => t.Saison)
                .WithMany(t => t.Groupes)
                .HasForeignKey(d => d.Saison_ID);

        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
ChatAdaptor::ChatAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) {
  setAutoRelaySignals(true);
}

ChatAdaptor::~ChatAdaptor() {}


text:
@interface JKEmptyView ()

#pragma mark - 私有属性
@property (nonatomic, strong) UIView *centerBackView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *titleLabel;

@end

@implementation JKEmptyView

#pragma mark - Life cycle

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        [self createSubViews];
        [self createSubViewsConstraints];
    }
    return self;
}

+ (BOOL)requiresConstraintBasedLayout {
    return YES;
}

- (void)dealloc {
    NSLog(@"%@ - dealloc", NSStringFromClass([self class]));
}

#pragma mark - Events

#pragma mark - UIOtherComponentDelegate

#pragma mark - Custom Delegates

#pragma mark - Public Methods

#pragma mark - Private Methods

// 添加子视图
- (void)createSubViews {
    [self addSubview:self.centerBackView];
    [self.centerBackView addSubview:self.imageView];
    [self.centerBackView addSubview:self.titleLabel];
}

// 添加约束
- (void)createSubViewsConstraints {
    [self.centerBackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.centerY.mas_equalTo(0);
    }];
    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.mas_equalTo(0);
    }];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.imageView.mas_bottom);
        make.left.right.mas_equalTo(0);
        make.width.mas_lessThanOrEqualTo(self.imageView.mas_width);
        make.bottom.mas_equalTo(0);
    }];
}

#pragma mark - Getters and Setters

- (void)setTitle:(NSString *)title {
    _title = title;
    self.titleLabel.text = _title;
}

- (void)setImage:(UIImage *)image {
    _image = image;
    self.imageView.image = _image;
}

- (void)setTitleFont:(UIFont *)titleFont {
    _titleFont = titleFont;
    self.titleLabel.font = _titleFont;
}

- (void)setTitleColor:(UIColor *)titleColor {
    _titleColor = titleColor;
    self.titleLabel.textColor = _titleColor;
}

- (UIView *)centerBackView {
    if (!_centerBackView) {
        _centerBackView = [[UIView alloc] init];
    }
    return _centerBackView;
}

- (UIImageView *)imageView {
    if (!_imageView) {
        _imageView = [[UIImageView alloc] init];
    }
    return _imageView;
}

- (UILabel *)titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc] init];
        _titleLabel.textColor = [UIColor blackColor];
        _titleLabel.font = [UIFont systemFontOfSize:30];
        _titleLabel.numberOfLines = 0;
    }
    return _titleLabel;
}

@end


text:
package com.jayway.textmining

import java.io.File
import org.apache.commons.io.FileUtils

trait TestData {

  private val resourcesDir = new File("src/test/resources")
  val files:List[File] = resourcesDir.listFiles().toList
  val docs = files.map( f => (f.getName, FileUtils.readFileToString(f, "UTF-8")))
  private val nlp = new NLP

  val documents:List[Document] = docs.map ( t => nlp.createDocumentFrom(t._1, t._2) )

}


text:
// Copyright (c) 2003  Per M.A. Bothner.
// This is free software;  for terms and warranty disclaimer see ./COPYING.

package gnu.kawa.xml;
import gnu.lists.*;

/** Used to implement a descendant:: step in a path expression. */

public class DescendantAxis extends TreeScanner
{
  public static DescendantAxis make (NodePredicate type)
  {
    DescendantAxis axis = new DescendantAxis();
    axis.type = type;
    return axis;
  }

  public void scan (AbstractSequence seq, int ipos, PositionConsumer out)
  {
    if (! (seq instanceof TreeList))
      { // AbstractSequence's nextMatching does not support descend.  FIXME.
	ipos = seq.firstChildPos(ipos);
	while (ipos != 0)
	  {
	    if (type.isInstancePos(seq, ipos))
	      out.writePosition(seq, ipos);
	    scan(seq, ipos, out);
	    ipos = seq.nextPos(ipos);
	  }
	return;
      }
    int limit = seq.nextPos(ipos);
    int child = ipos;
    for (;;)
      {
	child = seq.nextMatching(child, type, limit, true);
	if (child == 0)
	  break;
	out.writePosition(seq, child);
      }
  }
}


text:
package com.google.cloud.osconfig.v1.samples;

// [START osconfig_v1_generated_OsConfigZonalService_CreateOSPolicyAssignment_LocationnameOspolicyassignmentString_sync]
import com.google.cloud.osconfig.v1.LocationName;
import com.google.cloud.osconfig.v1.OSPolicyAssignment;
import com.google.cloud.osconfig.v1.OsConfigZonalServiceClient;

public class SyncCreateOSPolicyAssignmentLocationnameOspolicyassignmentString {

  public static void main(String[] args) throws Exception {
    syncCreateOSPolicyAssignmentLocationnameOspolicyassignmentString();
  }

  public static void syncCreateOSPolicyAssignmentLocationnameOspolicyassignmentString()
      throws Exception {
    // This snippet has been automatically generated and should be regarded as a code template only.
    // It will require modifications to work:
    // - It may require correct/in-range values for request initialization.
    // - It may require specifying regional endpoints when creating the service client as shown in
    // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
    try (OsConfigZonalServiceClient osConfigZonalServiceClient =
        OsConfigZonalServiceClient.create()) {
      LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]");
      OSPolicyAssignment osPolicyAssignment = OSPolicyAssignment.newBuilder().build();
      String osPolicyAssignmentId = "osPolicyAssignmentId-44079074";
      OSPolicyAssignment response =
          osConfigZonalServiceClient
              .createOSPolicyAssignmentAsync(parent, osPolicyAssignment, osPolicyAssignmentId)
              .get();
    }
  }
}
// [END osconfig_v1_generated_OsConfigZonalService_CreateOSPolicyAssignment_LocationnameOspolicyassignmentString_sync]


text:
rm $PREFIX/bin/activate
rm $PREFIX/bin/deactivate

$PYTHON setup.py install


text:
namespace SantasToyFactory.DataLayer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using MongoDB.Bson;
    using MongoDB.Driver;
    using System.Data.OleDb;

    using SantasToyFactory.DataOperations;
    using SantasToyFactory.Models;

    public class SantasToyFactoryMongoData
    {
        private const string MongoDBConnection = @"mongodb://localhost";
        private const string DbName = "SantasToyFactoryDB";
        private const string ToysCollectionName = "Toys";
        private const string ProducersCollectionName = "Producers";
        private const string ToyTypesName = "ToyTypes";
        private const string AddressesName = "Addresses";
        private const string TownsName = "Towns";
        private const string CountriesName = "Countries";
        private const string ChildrenName = "Children";
        private const string YearDateName = "Year";

        private const string DataInitializationDocumentString ="Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=../../../dataInfo.xls;";

        private readonly MongoServer server;
        private MongoDatabase db;

        public SantasToyFactoryMongoData()
        {
            this.server = new MongoClient(MongoDBConnection).GetServer();
            this.db = this.server.GetDatabase(DbName);
            InitializeDatabase();
        }

        public void InitializeDatabase()
        {
            OleDbConnection excelConnection = new OleDbConnection(DataInitializationDocumentString);
            excelConnection.Open();
            var excelData = new ExcelDataReader(excelConnection);
            using (excelConnection)
            {
                var collection = this.db.GetCollection(ToysCollectionName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetToys(ToysCollectionName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(ProducersCollectionName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetProducers(ProducersCollectionName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(ToyTypesName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetToyType(ToyTypesName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(AddressesName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetAddresses(AddressesName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(TownsName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetTowns(TownsName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(CountriesName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetCountries(CountriesName);
                    collection.InsertBatch(data);
                }

                collection = db.GetCollection(ChildrenName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetChilds(ChildrenName);
                    collection.InsertBatch(data);
                }

                /*
                collection = db.GetCollection(YearDateName);
                if (collection.Count() == 0)
                {
                    var data = excelData.GetYears(YearDateName);
                    collection.InsertBatch(data);
                }
                 */
            }
        }

        public void DropCollectionsFromDatabase()
        {
            this.db.Drop();
        }

        public IEnumerable<Toy> GetToys()
        {
            var collection = this.db.GetCollection<Toy>(ToysCollectionName).FindAll().AsEnumerable<Toy>();
            return collection;
        }

        public IEnumerable<Producer> GetProducers()
        {
            var collection = this.db.GetCollection<Producer>(ProducersCollectionName).FindAll().AsEnumerable<Producer>();
            return collection;
        }

        public IEnumerable<ToyType> GetToyTypes()
        {
            var collection = this.db.GetCollection<ToyType>(ToyTypesName).FindAll().AsEnumerable<ToyType>();
            return collection;
        }

        public IEnumerable<Address> GetAddresses()
        {
            var collection = this.db.GetCollection<Address>(AddressesName).FindAll().AsEnumerable<Address>();
            return collection;
        }

        public IEnumerable<Town> GetTowns()
        {
            var collection = this.db.GetCollection<Town>(TownsName).FindAll().AsEnumerable<Town>();
            return collection;
        }

        public IEnumerable<Country> GetCountries()
        {
            var collection = this.db.GetCollection<Country>(CountriesName).FindAll().AsEnumerable<Country>();
            return collection;
        }

        public IEnumerable<Child> GetChildren()
        {
            var collection = this.db.GetCollection<Child>(ChildrenName).FindAll().AsEnumerable<Child>();
            return collection;
        }
    }
}


text:
Incubation for projects is covered here: https://github.com/IBMStreams/administration/wiki/Project-Incubation-Process

## Status

- [ ] :white_check_mark: Stable release(s)
  * Status: https://github.com/IBMStreams/streamsx.topology/releases/tag/v1.1.2
- [ ] :white_check_mark: Project is properly documented
  * Status: http://ibmstreams.github.io/streamsx.topology/doc.html and http://ibmstreams.github.io/streamsx.documentation/docs/4.1/java/java-appapi-devguide/
- [ ] :red_circle: Project has samples and instructions to help users get started easily
  * Status: **TBD**
- [ ] :white_check_mark: Sufficient testing
  * Status: Project has unittests in Java, Scala & SPL running standalone and distributed, with JUnit and code coverage reports.
- [ ] :white_check_mark: Instructions on how to get started with development and contributing to project
  * Status: [DEVELOPMENT.md](DEVELOPMENT.md)
- [ ] :white_check_mark: Website that contains information and documentation of the project
  * Status: http://ibmstreams.github.io/streamsx.topology
- [ ] :red_circle: Clear release plan
  * Status: **TBD**
- [ ] :large_orange_diamond: At least one active committer
  * Status: Committers who have made many commits but not that many recently, new contributions from non-committers.

### Key
* :white_check_mark: - Complete
* :large_orange_diamond: - Partially complete
* :red_circle: - Not complete/started or unknown

## Instructions
A project should have this file copied to `GRADUATION_STATUS.md` at the top-level.

Projects self-report their status though IBMStreams admins may override any status.


text:
"""
Example:
    - Solve 8th-order Chebyshev polynomial coefficients with Powell's method.
    - Uses LatticeSolver to provide 'pseudo-global' optimization
    - Plot of fitting to Chebyshev polynomial.

Demonstrates:
    - standard models
    - minimal solver interface
"""
# the Lattice solver
from mystic.solvers import LatticeSolver

# Powell's Directonal solver
from mystic.solvers import PowellDirectionalSolver

# Chebyshev polynomial and cost function
from mystic.models.poly import chebyshev8, chebyshev8cost
from mystic.models.poly import chebyshev8coeffs

# if available, use a pathos worker pool
try:
    from pathos.pools import ProcessPool as Pool
   #from pathos.pools import ParallelPool as Pool
except ImportError:
    from mystic.pools import SerialPool as Pool

# tools
from mystic.termination import NormalizedChangeOverGeneration as NCOG
from mystic.math import poly1d
from mystic.monitors import VerboseMonitor
from mystic.tools import getch
import pylab
pylab.ion()

# draw the plot
def plot_exact():
    pylab.title("fitting 8th-order Chebyshev polynomial coefficients")
    pylab.xlabel("x")
    pylab.ylabel("f(x)")
    import numpy
    x = numpy.arange(-1.2, 1.2001, 0.01)
    exact = chebyshev8(x)
    pylab.plot(x,exact,'b-')
    pylab.legend(["Exact"])
    pylab.axis([-1.4,1.4,-2,8],'k-')
    pylab.draw()
    return

# plot the polynomial
def plot_solution(params,style='y-'):
    import numpy
    x = numpy.arange(-1.2, 1.2001, 0.01)
    f = poly1d(params)
    y = f(x)
    pylab.plot(x,y,style)
    pylab.legend(["Exact","Fitted"])
    pylab.axis([-1.4,1.4,-2,8],'k-')
    pylab.draw()
    return

if __name__ == '__main__':
    from pathos.helpers import freeze_support
    freeze_support() # help Windows use multiprocessing

    print "Powell's Method"
    print "==============="

    # dimensional information
    from mystic.tools import random_seed
    random_seed(123)
    ndim = 9
    nbins = 8 #[2,1,2,1,2,1,2,1,1]

    # draw frame and exact coefficients
    plot_exact()

    # configure monitor
    stepmon = VerboseMonitor(1)

    # use lattice-Powell to solve 8th-order Chebyshev coefficients
    solver = LatticeSolver(ndim, nbins)
    solver.SetNestedSolver(PowellDirectionalSolver)
    solver.SetMapper(Pool().map)
    solver.SetGenerationMonitor(stepmon)
    solver.SetStrictRanges(min=[-300]*ndim, max=[300]*ndim)
    solver.Solve(chebyshev8cost, NCOG(1e-4), disp=1)
    solution = solver.Solution()

    # use pretty print for polynomials
    print poly1d(solution)

    # compare solution with actual 8th-order Chebyshev coefficients
    print "\nActual Coefficients:\n %s\n" % poly1d(chebyshev8coeffs)

    # plot solution versus exact coefficients
    plot_solution(solution)
    getch()

# end of file


text:
package iso20022

type TaxType4Code string


text:
package com.intellij.psi.codeStyle.arrangement;

import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * Holds arrangement rules.
 *

 * Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations.
 *
 * @author Denis Zhdanov
 * @since 9/17/12 11:51 AM
 */
public interface ArrangementSettings extends Cloneable {

  @NotNull
  List<ArrangementGroupingRule> getGroupings();

  @NotNull
  List<ArrangementSectionRule> getSections();

  /**
   * @deprecated collect match rules from {@link #getSections()}
   * @return
   */
  @Deprecated
  @NotNull
  List<? extends ArrangementMatchRule> getRules();

  /**
   * Note: It's expected that rules sort is stable
   *

   * Example: 'public static' rule would have higher priority then 'public'
   * @return list of rules sorted in order of matching
   */
  @NotNull
  List<? extends ArrangementMatchRule> getRulesSortedByPriority();

  @NotNull
  ArrangementSettings clone();
}


text:
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.TokenAttributes;
using Lucene.Net.Index;
using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;

namespace Lucene.Net.Search.Highlight
{

    ///<summary>
    /// <see cref="IScorer"/> implementation which scores text fragments by the number of
    /// unique query terms found. This class converts appropriate <see cref="Query"/>s to
    /// <see cref="Search.Spans.SpanQuery"/>s and attempts to score only those terms that participated in
    /// generating the 'hit' on the document.
    /// </summary>
    public class QueryScorer : IScorer
    {
        private float totalScore;
        private ISet<string> foundTerms;
        private IDictionary<string, WeightedSpanTerm> fieldWeightedSpanTerms;
        private float maxTermWeight;
        private int position = -1;
        private string defaultField;
        private ICharTermAttribute termAtt;
        private IPositionIncrementAttribute posIncAtt;
        private bool expandMultiTermQuery = true;
        private Query query;
        private string field;
        private IndexReader reader;
        private bool skipInitExtractor;
        private bool wrapToCaching = true;
        private int maxCharsToAnalyze;

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="query"><see cref="Query"/> to use for highlighting</param>
        public QueryScorer(Query query)
        {
            Init(query, null, null, true);
        }

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="query"><see cref="Query"/> to use for highlighting</param>
        /// <param name="field">Field to highlight - pass null to ignore fields</param>
        public QueryScorer(Query query, string field)
        {
            Init(query, field, null, true);
        }

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="query"><see cref="Query"/> to use for highlighting</param>
        /// <param name="reader"><see cref="IndexReader"/> to use for quasi tf/idf scoring</param>
        /// <param name="field">Field to highlight - pass null to ignore fields</param>
        public QueryScorer(Query query, IndexReader reader, string field)
        {
            Init(query, field, reader, true);
        }

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="query"><see cref="Query"/> to use for highlighting</param>
        /// <param name="reader"><see cref="IndexReader"/> to use for quasi tf/idf scoring</param>
        /// <param name="field">Field to highlight - pass null to ignore fields</param>
        /// <param name="defaultField">The default field for queries with the field name unspecified</param>
        public QueryScorer(Query query, IndexReader reader, string field, string defaultField)
        {
            this.defaultField = defaultField.Intern();
            Init(query, field, reader, true);
        }

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="query"><see cref="Query"/> to use for highlighting</param>
        /// <param name="field">Field to highlight - pass null to ignore fields</param>
        /// <param name="defaultField">The default field for queries with the field name unspecified</param>
        public QueryScorer(Query query, string field, string defaultField)
        {
            this.defaultField = defaultField.Intern();
            Init(query, field, null, true);
        }

        /// <summary>
        /// Constructs a new <see cref="QueryScorer"/> instance
        /// </summary>
        /// <param name="weightedTerms">an array of pre-created <see cref="WeightedSpanTerm"/>s</param>
        public QueryScorer(WeightedSpanTerm[] weightedTerms)
        {
            this.fieldWeightedSpanTerms = new HashMap<string, WeightedSpanTerm>(weightedTerms.Length);

            foreach (WeightedSpanTerm t in weightedTerms)
            {
                WeightedSpanTerm existingTerm = fieldWeightedSpanTerms[t.Term];

                if ((existingTerm == null) ||
                    (existingTerm.Weight < t.Weight))
                {
                    // if a term is defined more than once, always use the highest
                    // scoring Weight
                    fieldWeightedSpanTerms[t.Term] = t;
                    maxTermWeight = Math.Max(maxTermWeight, t.Weight);
                }
            }
            skipInitExtractor = true;
        }

        /// <seealso cref="IScorer.FragmentScore"/>
        public virtual float FragmentScore
        {
            get { return totalScore; }
        }

        /// <summary>
        /// The highest weighted term (useful for passing to <see cref="GradientFormatter"/> to set top end of coloring scale).
        /// </summary>
        public virtual float MaxTermWeight
        {
            get { return maxTermWeight; }
        }

        /// <seealso cref="IScorer.GetTokenScore()"/>
        public virtual float GetTokenScore()
        {
            position += posIncAtt.PositionIncrement;
            string termText = termAtt.ToString();

            WeightedSpanTerm weightedSpanTerm;
            if (!fieldWeightedSpanTerms.TryGetValue(termText, out weightedSpanTerm) || weightedSpanTerm == null)
            {
                return 0;
            }

            if (weightedSpanTerm.IsPositionSensitive &&
                !weightedSpanTerm.CheckPosition(position))
            {
                return 0;
            }

            float score = weightedSpanTerm.Weight;

            // found a query term - is it unique in this doc?
            if (!foundTerms.Contains(termText))
            {
                totalScore += score;
                foundTerms.Add(termText);
            }

            return score;
        }

        /// <seealso cref="IScorer.Init"/>
        public virtual TokenStream Init(TokenStream tokenStream)
        {
            position = -1;
            termAtt = tokenStream.AddAttribute<ICharTermAttribute>();
            posIncAtt = tokenStream.AddAttribute<IPositionIncrementAttribute>();
            if (!skipInitExtractor)
            {
                fieldWeightedSpanTerms?.Clear();
                return InitExtractor(tokenStream);
            }
            return null;
        }

        /// <summary>
        /// Retrieve the <see cref="WeightedSpanTerm"/> for the specified token. Useful for passing
        /// Span information to a <see cref="IFragmenter"/>.
        /// </summary>
        /// <param name="token">token to get <see cref="WeightedSpanTerm"/> for</param>
        /// <returns><see cref="WeightedSpanTerm"/> for token</returns>
        public virtual WeightedSpanTerm GetWeightedSpanTerm(string token)
        {
            WeightedSpanTerm result;
            fieldWeightedSpanTerms.TryGetValue(token, out result);
            return result;
        }

        private void Init(Query query, string field, IndexReader reader, bool expandMultiTermQuery)
        {
            this.reader = reader;
            this.expandMultiTermQuery = expandMultiTermQuery;
            this.query = query;
            this.field = field;
        }

        private TokenStream InitExtractor(TokenStream tokenStream)
        {
            WeightedSpanTermExtractor qse = NewTermExtractor(defaultField);

            qse.SetMaxDocCharsToAnalyze(maxCharsToAnalyze);
            qse.ExpandMultiTermQuery = expandMultiTermQuery;
            qse.SetWrapIfNotCachingTokenFilter(wrapToCaching);
            if (reader == null)
            {
                this.fieldWeightedSpanTerms = qse.GetWeightedSpanTerms(query,
                                                                       tokenStream, field);
            }
            else
            {
                this.fieldWeightedSpanTerms = qse.GetWeightedSpanTermsWithScores(query,
                                                             tokenStream, field, reader);
            }
            if (qse.IsCachedTokenStream)
            {
                return qse.TokenStream;
            }

            return null;
        }

        protected virtual WeightedSpanTermExtractor NewTermExtractor(string defaultField)
        {
            return defaultField == null ? new WeightedSpanTermExtractor()
                : new WeightedSpanTermExtractor(defaultField);
        }

        /// <seealso cref="IScorer.StartFragment"/>
        public virtual void StartFragment(TextFragment newFragment)
        {
            foundTerms = Support.Compatibility.SetFactory.CreateHashSet<string>();
            totalScore = 0;
        }

        /// <summary>
        /// Controls whether or not multi-term queries are expanded
        /// against a <see cref="Index.Memory.MemoryIndex"/> <see cref="IndexReader"/>.
        /// <c>true</c> if multi-term queries should be expanded
        /// </summary>
        public virtual bool ExpandMultiTermQuery
        {
            get { return expandMultiTermQuery; }
            set { this.expandMultiTermQuery = value; }
        }

        /// <summary>
        /// By default, <see cref="TokenStream"/>s that are not of the type
        /// <see cref="CachingTokenFilter"/> are wrapped in a <see cref="CachingTokenFilter"/> to
        /// ensure an efficient reset - if you are already using a different caching
        /// <see cref="TokenStream"/> impl and you don't want it to be wrapped, set this to
        /// false.
        /// </summary>
        public virtual void SetWrapIfNotCachingTokenFilter(bool wrap)
        {
            this.wrapToCaching = wrap;
        }

        public virtual void SetMaxDocCharsToAnalyze(int maxDocCharsToAnalyze)
        {
            this.maxCharsToAnalyze = maxDocCharsToAnalyze;
        }
    }
}


text:
namespace bust::svg {

    struct Style {
        private:
            std::string name;
            bust::util::Color fill;
            bust::util::Color stroke;
            uint8_t stroke_width;
            std::string style;

        public:
            Style(std::string n, bust::util::Color f, bust::util::Color s, uint8_t sw, std::string style) : name(n), fill(f), stroke(s), stroke_width(sw), style(style) {};
            Style(std::string n, bust::util::Color f, bust::util::Color s, uint8_t sw) : name(n), fill(f), stroke(s), stroke_width(sw), style("") {};
            Style(std::string n, bust::util::Color f) : name(n), fill(f), stroke(bust::util::colors::None), stroke_width(0) {};

            inline std::string getName() const { return this->name; }
            inline bust::util::Color getFill() const { return this->fill; }
            inline bust::util::Color getStroke() const { return this->stroke; }
            inline std::uint8_t getStrokeWidth() const { return this->stroke_width; }
            inline std::string getStyle() const { return this->style; }
    };

    namespace styles {
        static const Style Default("default", bust::util::colors::None, bust::util::colors::Black, 2);
    }

}

#endif


text:
<?php

use kartik\helpers\Html;
//use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use kartik\widgets\ActiveForm;
use kartik\builder\Form;
use kartik\builder\FormGrid;
use kartik\widgets\DepDrop;
use yii\helpers\Url;
use kartik\datecontrol\DateControl;

// table reference
use app\models\RefNegeri;
use app\models\RefSukan;

// contant values
use app\models\general\Placeholder;
use app\models\general\GeneralLabel;
use app\models\general\GeneralVariable;
use app\models\general\GeneralMessage;

/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
?>

* <?= GeneralLabel::lapangan_mandatori ?>

    <?php $form = ActiveForm::begin(['type'=>ActiveForm::TYPE_VERTICAL, 'staticOnly'=>$readonly]); ?>
    <?php echo $form->errorSummary($model); ?>
    <?php $model->isNewRecord ? $model->aktif = 1: $model->aktif = $model->aktif ;  ?>
    <?php
        echo FormGrid::widget([
    'model' => $model,
    'form' => $form,
    'autoGenerateColumns' => true,
    'rows' => [
        [
            'columns'=>12,
            'autoGenerateColumns'=>false, // override columns setting
            'attributes' => [
                'desc' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>6],'options'=>['maxlength'=>80]],
                'no_kad_pengenalan' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>3],'options'=>['maxlength'=>12]],
            ],
        ],
        [
            'columns'=>12,
            'autoGenerateColumns'=>false, // override columns setting
            'attributes' => [
                'sukan' => [
                    'type'=>Form::INPUT_WIDGET,
                    'widgetClass'=>'\kartik\widgets\Select2',
                    'options'=>[
                        'addon' => (isset(Yii::$app->user->identity->peranan_akses['Admin']['is_admin'])) ?
                        [
                            'append' => [
                                'content' => Html::a(Html::icon('edit'), ['/ref-sukan/index'], ['class'=>'btn btn-success', 'target' => '_blank']),
                                'asButton' => true
                            ]
                        ] : null,
                        'data'=>ArrayHelper::map(RefSukan::find()->where(['=', 'aktif', 1])->all(),'id', 'desc'),
                        'options' => ['placeholder' => Placeholder::sukan],
                        'pluginOptions' => [
                            'allowClear' => true
                        ],],
                    'columnOptions'=>['colspan'=>3]],
                'jawatan' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>3],'options'=>['maxlength'=>80]],
                'negeri' => [
                    'type'=>Form::INPUT_WIDGET,
                    'widgetClass'=>'\kartik\widgets\Select2',
                    'options'=>[
                        'addon' => (isset(Yii::$app->user->identity->peranan_akses['Admin']['is_admin'])) ?
                        [
                            'append' => [
                                'content' => Html::a(Html::icon('edit'), ['/ref-negeri/index'], ['class'=>'btn btn-success', 'target' => '_blank']),
                                'asButton' => true
                            ]
                        ] : null,
                        'data'=>ArrayHelper::map(RefNegeri::find()->where(['=', 'aktif', 1])->all(),'id', 'desc'),
                        'options' => ['placeholder' => Placeholder::negeri],
'pluginOptions' => [
                            'allowClear' => true
                        ],],
                    'columnOptions'=>['colspan'=>3]],
            ]
        ],
        [
            'columns'=>12,
            'autoGenerateColumns'=>false, // override columns setting
            'attributes' => [
                'tel_no_pejabat' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>3],'options'=>['maxlength'=>14]],
                'tel_no_bimbit' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>3],'options'=>['maxlength'=>14]],
                'emel' => ['type'=>Form::INPUT_TEXT,'columnOptions'=>['colspan'=>3],'options'=>['maxlength'=>255]],
            ]
        ],
        [
            'columns'=>12,
            'autoGenerateColumns'=>false, // override columns setting
            'attributes' => [
                'aktif' => [
                    'type'=>Form::INPUT_RADIO_LIST,
                    'items'=>[true=>GeneralLabel::yes, false=>GeneralLabel::no],
                    'value'=>false,
                    'options'=>['inline'=>true],
                    'columnOptions'=>['colspan'=>2]],
            ]
        ],
    ]
]);
        ?>

    <?php //echo $form->field($model, 'aktif')->radioList(array(true=>GeneralLabel::yes,false=>GeneralLabel::no)); ?>

        <?php if(!$readonly): ?>
        <?= Html::submitButton($model->isNewRecord ? GeneralLabel::create : GeneralLabel::update, ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
        <?php endif; ?>

    <?php ActiveForm::end(); ?>


text:
import jwt from 'jsonwebtoken';
import models from '../models/index';

/**
 * This class handles all middlewares for authorization
 */
export default class Middlewares {

  /**
   * This method checks if a user is logged in and prevents jumping routes
   * @param {object} req
   * @param {object} res
   * @param {function} next
   * @returns {void}
   */
  static isAuthenticated(req, res, next) {
    const authorizationHeader = req.headers.authorization;

    if (authorizationHeader) {
      const token = authorizationHeader.split(' ')[1];
      jwt.verify(token, process.env.secret, (err, decoded) => {
        if (err) {
          res.status(401).json({ globals: 'You need to be logged first!' });
        } else {
          models.User.findOne({
            where: { id: decoded.id },
            attributes: ['fullname', 'email', 'telephone',
              'profileImage', 'id', 'username']
          }).then((foundUser) => {
            if (!foundUser) {
              res.status(404).json({
                globals: 'No such user, please create an account!'
              });
            } else {
              req.user = foundUser;
              next();
            }
          });
        }
      });
    } else {
      return res.status(401).json({
        globals: 'Access denied! Please create an account or login first!'
      });
    }
  }

  /**
   * This method checks if the user is in a group before
   * allowing the user to perform
   * any action in that group
   * @param {object} req
   * @param {object} res
   * @param {function} next
   * @returns {void}
   */
  static isAuthorized(req, res, next) {
    models.UserGroup.findOne({
      where: { $and: [
        { UserId: req.user.dataValues.id },
        { GroupId: req.params.id }]
      },
    }).then((found) => {
      if (found === null) {
        res.status(401).json({
          globals: 'You are not authorized to access this group!'
        });
      } else {
        next();
      }
    }).catch((err) => {
      res.status(500).json({
        globals: err.message || err.errors[0].message
      });
    });
  }
}


text:
package io.awacs.component.org.jetbrains.java.decompiler.code.optinstructions;

import io.awacs.component.org.jetbrains.java.decompiler.code.Instruction;

import java.io.DataOutputStream;
import java.io.IOException;

public class MULTIANEWARRAY extends Instruction {

  public void writeToStream(DataOutputStream out, int offset) throws IOException {
    out.writeByte(opc_multianewarray);
    out.writeShort(getOperand(0));
    out.writeByte(getOperand(1));
  }

  public int length() {
    return 4;
  }
}


text:
goog.module('goog.ui.ZippyTest');
goog.setTestOnly();

const KeyCodes = goog.require('goog.events.KeyCodes');
const TagName = goog.require('goog.dom.TagName');
const Zippy = goog.require('goog.ui.Zippy');
const aria = goog.require('goog.a11y.aria');
const classlist = goog.require('goog.dom.classlist');
const dom = goog.require('goog.dom');
const events = goog.require('goog.events');
const googObject = goog.require('goog.object');
const testSuite = goog.require('goog.testing.testSuite');
const testingEvents = goog.require('goog.testing.events');

let buttonZippy;
let contentlessZippy;
let fakeZippy1;
let fakeZippy2;
let headerlessZippy;
let zippy;

let lazyZippy;
let lazyZippyCallCount;
let lazyZippyContentEl;
let dualHeaderZippy;
let dualHeaderZippyCollapsedHeaderEl;
let dualHeaderZippyExpandedHeaderEl;

function hasCollapseOrExpandClasses(el) {
  const isCollapsed = classlist.contains(el, 'goog-zippy-collapsed');
  const isExpanded = classlist.contains(el, 'goog-zippy-expanded');
  return isCollapsed || isExpanded;
}

testSuite({
  setUp() {
    zippy = new Zippy(dom.getElement('t1'), dom.getElement('c1'));

    const fakeControlEl = dom.createElement(TagName.BUTTON);
    const fakeContentEl = dom.createElement(TagName.DIV);

    fakeZippy1 = new Zippy(
        fakeControlEl.cloneNode(true), fakeContentEl.cloneNode(true), true);
    fakeZippy2 = new Zippy(
        fakeControlEl.cloneNode(true), fakeContentEl.cloneNode(true), false);
    contentlessZippy =
        new Zippy(fakeControlEl.cloneNode(true), undefined, true);
    headerlessZippy = new Zippy(null, fakeContentEl.cloneNode(true), true);
    buttonZippy = new Zippy(
        null, fakeContentEl.cloneNode(true), true, null, null,
        aria.Role.BUTTON);

    lazyZippyCallCount = 0;
    lazyZippyContentEl = fakeContentEl.cloneNode(true);
    lazyZippy = new Zippy(dom.getElement('t1'), () => {
      lazyZippyCallCount++;
      return lazyZippyContentEl;
    });
    dualHeaderZippyCollapsedHeaderEl = fakeControlEl.cloneNode(true);
    dualHeaderZippyExpandedHeaderEl = fakeControlEl.cloneNode(true);
    dualHeaderZippy = new Zippy(
        dualHeaderZippyCollapsedHeaderEl, fakeContentEl.cloneNode(true), false,
        dualHeaderZippyExpandedHeaderEl);
  },

  testConstructor() {
    assertNotNull('must not be null', zippy);
  },

  testIsExpanded() {
    assertEquals('Default expanded must be false', false, zippy.isExpanded());
    assertEquals('Expanded must be true', true, fakeZippy1.isExpanded());
    assertEquals('Expanded must be false', false, fakeZippy2.isExpanded());
    assertEquals('Expanded must be true', true, headerlessZippy.isExpanded());
    assertEquals('Expanded must be false', false, lazyZippy.isExpanded());
    assertEquals('Expanded must be false', false, dualHeaderZippy.isExpanded());
    assertEquals('Expanded must be true', true, buttonZippy.isExpanded());
  },

  tearDown() {
    zippy.dispose();
    fakeZippy1.dispose();
    fakeZippy2.dispose();
    contentlessZippy.dispose();
    headerlessZippy.dispose();
    lazyZippy.dispose();
    dualHeaderZippy.dispose();
    buttonZippy.dispose();
  },

  testExpandCollapse() {
    zippy.expand();
    headerlessZippy.expand();
    assertEquals('expanded must be true', true, zippy.isExpanded());
    assertEquals('expanded must be true', true, headerlessZippy.isExpanded());

    zippy.collapse();
    headerlessZippy.collapse();
    assertEquals('expanded must be false', false, zippy.isExpanded());
    assertEquals('expanded must be false', false, headerlessZippy.isExpanded());
  },

  testExpandCollapse_lazyZippy() {
    assertEquals('callback should not be called #1.', 0, lazyZippyCallCount);
    lazyZippy.collapse();
    assertEquals('callback should not be called #2.', 0, lazyZippyCallCount);

    lazyZippy.expand();
    assertEquals('callback should be called once #1.', 1, lazyZippyCallCount);
    assertEquals('expanded must be true', true, lazyZippy.isExpanded());
    assertEquals(
        'contentEl should be visible', '', lazyZippyContentEl.style.display);

    lazyZippy.collapse();
    assertEquals('callback should be called once #2.', 1, lazyZippyCallCount);
    assertEquals('expanded must be false', false, lazyZippy.isExpanded());
    assertEquals(
        'contentEl should not be visible', 'none',
        lazyZippyContentEl.style.display);

    lazyZippy.expand();
    assertEquals('callback should be called once #3.', 1, lazyZippyCallCount);
    assertEquals('expanded must be true #2', true, lazyZippy.isExpanded());
    assertEquals(
        'contentEl should be visible #2', '', lazyZippyContentEl.style.display);
  },

  testExpandCollapse_dualHeaderZippy() {
    dualHeaderZippy.expand();
    assertEquals('expanded must be true', true, dualHeaderZippy.isExpanded());
    assertFalse(
        'collapsed header should not have state class name #1',
        hasCollapseOrExpandClasses(dualHeaderZippyCollapsedHeaderEl));
    assertFalse(
        'expanded header should not have state class name #1',
        hasCollapseOrExpandClasses(dualHeaderZippyExpandedHeaderEl));

    dualHeaderZippy.collapse();
    assertEquals('expanded must be false', false, dualHeaderZippy.isExpanded());
    assertFalse(
        'collapsed header should not have state class name #2',
        hasCollapseOrExpandClasses(dualHeaderZippyCollapsedHeaderEl));
    assertFalse(
        'expanded header should not have state class name #2',
        hasCollapseOrExpandClasses(dualHeaderZippyExpandedHeaderEl));
  },

  testSetExpand() {
    const expanded = !zippy.isExpanded();
    zippy.setExpanded(expanded);
    assertEquals(`expanded must be ${expanded}`, expanded, zippy.isExpanded());
  },

  testCssClassesAndAria() {
    assertTrue(
        'goog-zippy-header is enabled',
        classlist.contains(zippy.elHeader_, 'goog-zippy-header'));
    assertNotNull(zippy.elHeader_);
    assertEquals(
        'header aria-expanded is false', 'false',
        aria.getState(zippy.elHeader_, 'expanded'));
    zippy.setExpanded(true);
    assertTrue(
        'goog-zippy-content is enabled',
        classlist.contains(zippy.getContentElement(), 'goog-zippy-content'));
    assertEquals(
        'header aria role is TAB', 'tab', aria.getRole(zippy.elHeader_));
    assertEquals(
        'header aria-expanded is true', 'true',
        aria.getState(zippy.elHeader_, 'expanded'));
  },

  testAreaRoleOverride() {
    assertEquals(
        'Aria role override is goog.a11y.aria.Role.BUTTON', aria.Role.BUTTON,
        buttonZippy.getAriaRole());
  },

  testHeaderTabIndex() {
    assertEquals('Header tabIndex is 0', 0, zippy.elHeader_.tabIndex);
  },

  testGetVisibleHeaderElement() {
    dualHeaderZippy.setExpanded(false);
    assertEquals(
        dualHeaderZippyCollapsedHeaderEl,
        dualHeaderZippy.getVisibleHeaderElement());
    dualHeaderZippy.setExpanded(true);
    assertEquals(
        dualHeaderZippyExpandedHeaderEl,
        dualHeaderZippy.getVisibleHeaderElement());
  },

  testToggle() {
    const expanded = !zippy.isExpanded();
    zippy.toggle();
    assertEquals(`expanded must be ${expanded}`, expanded, zippy.isExpanded());
  },

  testCustomEventTOGGLE() {
    let dispatchedActionCount;
    const handleAction = () => {
      dispatchedActionCount++;
    };

    const doTest = (zippyObj) => {
      dispatchedActionCount = 0;
      events.listen(zippyObj, Zippy.Events.TOGGLE, handleAction);
      zippy.toggle();
      assertEquals('Custom Event must be called ', 1, dispatchedActionCount);
    };

    doTest(zippy);
    doTest(fakeZippy1);
    doTest(contentlessZippy);
    doTest(headerlessZippy);
  },

  testActionEvent() {
    let actionEventCount = 0;
    let toggleEventCount = 0;
    const handleEvent = (e) => {
      if (e.type == Zippy.Events.TOGGLE) {
        toggleEventCount++;
      } else if (e.type == Zippy.Events.ACTION) {
        actionEventCount++;
        assertNotNull(
            'action event must have triggering event', e.triggeringEvent);
        assertTrue(
            'toggle must have been called first',
            toggleEventCount >= actionEventCount);
      }
    };
    events.listen(zippy, googObject.getValues(Zippy.Events), handleEvent);
    testingEvents.fireClickSequence(zippy.elHeader_);
    assertEquals('Zippy ACTION event fired', 1, actionEventCount);
    assertEquals('Zippy TOGGLE event fired', 1, toggleEventCount);

    zippy.toggle();
    assertEquals('Zippy ACTION event NOT fired', 1, actionEventCount);
    assertEquals('Zippy TOGGLE event fired', 2, toggleEventCount);
  },

  testBasicZippyBehavior() {
    let dispatchedActionCount = 0;
    const handleAction = () => {
      dispatchedActionCount++;
    };

    events.listen(zippy, Zippy.Events.TOGGLE, handleAction);
    testingEvents.fireClickSequence(zippy.elHeader_);
    assertEquals(
        'Zippy  must have dispatched TOGGLE on click', 1,
        dispatchedActionCount);
  },

  testIsHandleKeyEvent() {
    zippy.setHandleKeyboardEvents(false);
    assertFalse('Zippy is not handling key events', zippy.isHandleKeyEvents());
    assertTrue(
        'Zippy setHandleKeyEvents does not affect handling mouse events',
        zippy.isHandleMouseEvents());
    assertEquals(0, zippy.keyboardEventHandler_.getListenerCount());

    zippy.setHandleKeyboardEvents(true);
    assertTrue('Zippy is handling key events', zippy.isHandleKeyEvents());
    assertTrue(
        'Zippy setHandleKeyEvents does not affect handling mouse events',
        zippy.isHandleMouseEvents());
    assertNotEquals(0, zippy.keyboardEventHandler_.getListenerCount());
  },

  testIsHandleMouseEvent() {
    zippy.setHandleMouseEvents(false);
    assertFalse(
        'Zippy is not handling mouse events', zippy.isHandleMouseEvents());
    assertTrue(
        'Zippy setHandleMouseEvents does not affect handling key events',
        zippy.isHandleKeyEvents());
    assertEquals(0, zippy.mouseEventHandler_.getListenerCount());

    zippy.setHandleMouseEvents(true);
    assertTrue('Zippy is handling mouse events', zippy.isHandleMouseEvents());
    assertTrue(
        'Zippy setHandleMouseEvents does not affect handling key events',
        zippy.isHandleKeyEvents());
    assertNotEquals(0, zippy.mouseEventHandler_.getListenerCount());
  },

  testKeyDownEventTriggersHeader() {
    let actionEventCount = 0;
    let toggleEventCount = 0;
    const handleEvent = (e) => {
      if (e.type == Zippy.Events.TOGGLE) {
        toggleEventCount++;
      } else if (e.type == Zippy.Events.ACTION) {
        actionEventCount++;
        assertTrue(
            'toggle must have been called first',
            toggleEventCount >= actionEventCount);
      }
    };
    zippy.setHandleKeyboardEvents(true);
    events.listen(zippy, googObject.getValues(Zippy.Events), handleEvent);

    testingEvents.fireKeySequence(zippy.elHeader_, KeyCodes.SPACE);

    assertEquals('Zippy ACTION event fired', 1, actionEventCount);
    assertEquals('Zippy TOGGLE event fired', 1, toggleEventCount);
  },
});


text:
To integrate MySqlConnector with Microsoft.Extensions.Logging, add the following line of code to `Program.cs` method (before any `MySqlConnector` objects have been used):

```csharp
app.Services.UseMySqlConnectorLogging();
```

Alternatively, obtain an `ILoggerFactory` through dependency injection and add:

```csharp
MySqlConnectorLogManager.Provider = new MicrosoftExtensionsLoggingLoggerProvider(loggerFactory);
```