// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "sync/internal_api/js_mutation_event_observer.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/values.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/util/weak_handle.h" #include "sync/js/js_event_details.h" #include "sync/js/js_test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { namespace { using ::testing::InSequence; using ::testing::StrictMock; class JsMutationEventObserverTest : public testing::Test { protected: JsMutationEventObserverTest() { js_mutation_event_observer_.SetJsEventHandler( mock_js_event_handler_.AsWeakHandle()); } private: // This must be destroyed after the member variables below in order // for WeakHandles to be destroyed properly. base::MessageLoop message_loop_; protected: StrictMock mock_js_event_handler_; JsMutationEventObserver js_mutation_event_observer_; void PumpLoop() { base::RunLoop().RunUntilIdle(); } }; TEST_F(JsMutationEventObserverTest, OnChangesApplied) { InSequence dummy; // We don't test with passwords as that requires additional setup. // Build a list of example ChangeRecords. ChangeRecord changes[MODEL_TYPE_COUNT]; for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { changes[i].id = i; switch (i % 3) { case 0: changes[i].action = ChangeRecord::ACTION_ADD; break; case 1: changes[i].action = ChangeRecord::ACTION_UPDATE; break; default: changes[i].action = ChangeRecord::ACTION_DELETE; break; } } // For each i, we call OnChangesApplied() with the first arg equal // to i cast to ModelType and the second argument with the changes // starting from changes[i]. // Set expectations for each data type. for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { const std::string& model_type_str = ModelTypeToString(ModelTypeFromInt(i)); base::DictionaryValue expected_details; expected_details.SetString("modelType", model_type_str); expected_details.SetString("writeTransactionId", "0"); base::ListValue* expected_changes = new base::ListValue(); expected_details.Set("changes", expected_changes); for (int j = i; j < MODEL_TYPE_COUNT; ++j) { expected_changes->Append(changes[j].ToValue()); } EXPECT_CALL(mock_js_event_handler_, HandleJsEvent("onChangesApplied", HasDetailsAsDictionary(expected_details))); } // Fire OnChangesApplied() for each data type. for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { ChangeRecordList local_changes(changes + i, changes + arraysize(changes)); js_mutation_event_observer_.OnChangesApplied( ModelTypeFromInt(i), 0, ImmutableChangeRecordList(&local_changes)); } PumpLoop(); } TEST_F(JsMutationEventObserverTest, OnChangesComplete) { InSequence dummy; for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { base::DictionaryValue expected_details; expected_details.SetString( "modelType", ModelTypeToString(ModelTypeFromInt(i))); EXPECT_CALL(mock_js_event_handler_, HandleJsEvent("onChangesComplete", HasDetailsAsDictionary(expected_details))); } for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { js_mutation_event_observer_.OnChangesComplete( ModelTypeFromInt(i)); } PumpLoop(); } } // namespace } // namespace syncer