forked from qt-creator/qt-creator
QmlDesigner: Add view management tests
Cannot really test the reweiter because it expects a rewriter view. So no mock can be used. Task-number: QDS-13406 Change-Id: I0191e3681ed288322dbd339d76288fa22bf0766a Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -928,13 +928,16 @@ void ModelPrivate::attachView(AbstractView *view)
|
||||
if (!view->isEnabled())
|
||||
return;
|
||||
|
||||
if (m_viewList.contains(view))
|
||||
return;
|
||||
if (view->isAttached()) {
|
||||
if (view->model() == m_model)
|
||||
return;
|
||||
else
|
||||
view->model()->detachView(view);
|
||||
}
|
||||
|
||||
m_viewList.append(view);
|
||||
|
||||
if (!view->isAttached())
|
||||
view->modelAttached(m_model);
|
||||
view->modelAttached(m_model);
|
||||
}
|
||||
|
||||
void ModelPrivate::detachView(AbstractView *view, bool notifyView)
|
||||
@@ -1641,6 +1644,9 @@ void ModelPrivate::setNodeInstanceView(AbstractView *nodeInstanceView)
|
||||
if (nodeInstanceView && nodeInstanceView->kind() != AbstractView::Kind::NodeInstance)
|
||||
return;
|
||||
|
||||
if (nodeInstanceView && nodeInstanceView->isAttached())
|
||||
nodeInstanceView->model()->setNodeInstanceView(nullptr);
|
||||
|
||||
if (m_nodeInstanceView)
|
||||
m_nodeInstanceView->modelAboutToBeDetached(m_model);
|
||||
|
||||
|
@@ -105,11 +105,13 @@ Internal::TextToModelMerger *RewriterView::textToModelMerger() const
|
||||
|
||||
void RewriterView::modelAttached(Model *model)
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return);
|
||||
m_modelAttachPending = false;
|
||||
|
||||
AbstractView::modelAttached(model);
|
||||
|
||||
if (!m_textModifier)
|
||||
return;
|
||||
|
||||
m_modelAttachPending = false;
|
||||
|
||||
ModelAmender differenceHandler(m_textToModelMerger.get());
|
||||
const QString qmlSource = m_textModifier->text();
|
||||
if (m_textToModelMerger->load(qmlSource, differenceHandler))
|
||||
|
@@ -14,7 +14,15 @@ class AbstractViewMock : public QmlDesigner::AbstractView
|
||||
public:
|
||||
AbstractViewMock(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr)
|
||||
: QmlDesigner::AbstractView{*externalDependencies}
|
||||
{}
|
||||
{
|
||||
ON_CALL(*this, modelAttached).WillByDefault([this](QmlDesigner::Model *model) {
|
||||
this->QmlDesigner::AbstractView::modelAttached(model);
|
||||
});
|
||||
|
||||
ON_CALL(*this, modelAboutToBeDetached).WillByDefault([this](QmlDesigner::Model *model) {
|
||||
this->QmlDesigner::AbstractView::modelAboutToBeDetached(model);
|
||||
});
|
||||
}
|
||||
MOCK_METHOD(void, nodeOrderChanged, (const QmlDesigner::NodeListProperty &listProperty), (override));
|
||||
MOCK_METHOD(void,
|
||||
variantPropertiesChanged,
|
||||
@@ -57,4 +65,9 @@ public:
|
||||
(override));
|
||||
MOCK_METHOD(void, nodeAboutToBeRemoved, (const QmlDesigner::ModelNode &removedNode), (override));
|
||||
MOCK_METHOD(void, refreshMetaInfos, (const QmlDesigner::TypeIds &), (override));
|
||||
|
||||
MOCK_METHOD(void, modelAttached, (QmlDesigner::Model *), (override));
|
||||
MOCK_METHOD(void, modelAboutToBeDetached, (QmlDesigner::Model *), (override));
|
||||
|
||||
using AbstractView::setKind;
|
||||
};
|
||||
|
@@ -5,24 +5,27 @@
|
||||
|
||||
#include <matchers/import-matcher.h>
|
||||
#include <mocks/abstractviewmock.h>
|
||||
#include <mocks/externaldependenciesmock.h>
|
||||
#include <mocks/modelresourcemanagementmock.h>
|
||||
#include <mocks/projectstoragemock.h>
|
||||
#include <mocks/projectstorageobservermock.h>
|
||||
#include <mocks/sourcepathcachemock.h>
|
||||
|
||||
#include <designercore/include/bindingproperty.h>
|
||||
#include <designercore/include/itemlibraryentry.h>
|
||||
#include <designercore/include/model.h>
|
||||
#include <designercore/include/modelnode.h>
|
||||
#include <designercore/include/nodeabstractproperty.h>
|
||||
#include <designercore/include/nodelistproperty.h>
|
||||
#include <designercore/include/nodemetainfo.h>
|
||||
#include <designercore/include/nodeproperty.h>
|
||||
#include <designercore/include/signalhandlerproperty.h>
|
||||
#include <designercore/include/variantproperty.h>
|
||||
#include <bindingproperty.h>
|
||||
#include <itemlibraryentry.h>
|
||||
#include <model.h>
|
||||
#include <modelnode.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <nodemetainfo.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <rewriterview.h>
|
||||
#include <signalhandlerproperty.h>
|
||||
#include <variantproperty.h>
|
||||
|
||||
namespace {
|
||||
using QmlDesigner::AbstractProperty;
|
||||
using QmlDesigner::AbstractView;
|
||||
using QmlDesigner::ModelNode;
|
||||
using QmlDesigner::ModelNodes;
|
||||
using QmlDesigner::ModelResourceSet;
|
||||
@@ -119,13 +122,13 @@ protected:
|
||||
NiceMock<ProjectStorageMockWithQtQuick> projectStorageMock{pathCacheMock.sourceId, "/path"};
|
||||
NiceMock<ModelResourceManagementMock> resourceManagementMock;
|
||||
QmlDesigner::Imports imports = {QmlDesigner::Import::createLibraryImport("QtQuick")};
|
||||
NiceMock<AbstractViewMock> viewMock;
|
||||
QmlDesigner::Model model{{projectStorageMock, pathCacheMock},
|
||||
"Item",
|
||||
imports,
|
||||
QUrl::fromLocalFile(pathCacheMock.path.toQString()),
|
||||
std::make_unique<ModelResourceManagementMockWrapper>(
|
||||
resourceManagementMock)};
|
||||
NiceMock<AbstractViewMock> viewMock;
|
||||
QmlDesigner::SourceId filePathId = pathCacheMock.sourceId;
|
||||
QmlDesigner::ModuleId qtQuickModuleId = projectStorageMock.moduleId("QtQuick",
|
||||
ModuleKind::QmlLibrary);
|
||||
@@ -1201,4 +1204,121 @@ TEST_F(Model_TypeAnnotation, item_library_entries)
|
||||
ElementsAre(u"/extra/file/path"))));
|
||||
}
|
||||
|
||||
class Model_ViewManagement : public Model
|
||||
{
|
||||
protected:
|
||||
NiceMock<AbstractViewMock> viewMock;
|
||||
};
|
||||
|
||||
TEST_F(Model_ViewManagement, set_rewriter)
|
||||
{
|
||||
NiceMock<ExternalDependenciesMock> externalDependenciesMock;
|
||||
QmlDesigner::RewriterView rewriter{externalDependenciesMock};
|
||||
|
||||
model.setRewriterView(&rewriter);
|
||||
|
||||
ASSERT_THAT(model.rewriterView(), Eq(&rewriter));
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, attach_rewriter)
|
||||
{
|
||||
NiceMock<ExternalDependenciesMock> externalDependenciesMock;
|
||||
QmlDesigner::RewriterView rewriter{externalDependenciesMock};
|
||||
|
||||
model.attachView(&rewriter);
|
||||
|
||||
ASSERT_THAT(model.rewriterView(), Eq(&rewriter));
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, set_node_instance_view)
|
||||
{
|
||||
viewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
|
||||
ASSERT_THAT(model.nodeInstanceView(), Eq(&viewMock));
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, call_modelAttached_if_node_instance_view_is_set)
|
||||
{
|
||||
viewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
|
||||
EXPECT_CALL(viewMock, modelAttached(&model));
|
||||
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, dont_call_modelAttached_if_node_instance_view_is_already_set)
|
||||
{
|
||||
viewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
|
||||
EXPECT_CALL(viewMock, modelAttached(&model)).Times(0);
|
||||
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, detach_node_instance_view_from_other_model_before_attach_to_new_model)
|
||||
{
|
||||
InSequence s;
|
||||
QmlDesigner::Model otherModel{{projectStorageMock, pathCacheMock},
|
||||
"Item",
|
||||
imports,
|
||||
QUrl::fromLocalFile(pathCacheMock.path.toQString()),
|
||||
std::make_unique<ModelResourceManagementMockWrapper>(
|
||||
resourceManagementMock)};
|
||||
viewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
otherModel.setNodeInstanceView(&viewMock);
|
||||
|
||||
EXPECT_CALL(viewMock, modelAboutToBeDetached(&otherModel));
|
||||
EXPECT_CALL(viewMock, modelAttached(&model));
|
||||
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, call_modelAboutToBeDetached_for_already_set_node_instance_view)
|
||||
{
|
||||
NiceMock<AbstractViewMock> otherViewMock;
|
||||
otherViewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
viewMock.setKind(AbstractView::Kind::NodeInstance);
|
||||
model.setNodeInstanceView(&otherViewMock);
|
||||
|
||||
EXPECT_CALL(otherViewMock, modelAboutToBeDetached(&model));
|
||||
|
||||
model.setNodeInstanceView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, attach_view_is_calling_modelAttached)
|
||||
{
|
||||
EXPECT_CALL(viewMock, modelAttached(&model));
|
||||
|
||||
model.attachView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, attach_view_is_not_calling_modelAttached_if_it_is_already_attached)
|
||||
{
|
||||
model.attachView(&viewMock);
|
||||
|
||||
EXPECT_CALL(viewMock, modelAttached(&model)).Times(0);
|
||||
|
||||
model.attachView(&viewMock);
|
||||
}
|
||||
|
||||
TEST_F(Model_ViewManagement, view_is_detached_before_it_is_attached_ot_new_model)
|
||||
{
|
||||
InSequence s;
|
||||
QmlDesigner::Model otherModel{{projectStorageMock, pathCacheMock},
|
||||
"Item",
|
||||
imports,
|
||||
QUrl::fromLocalFile(pathCacheMock.path.toQString()),
|
||||
std::make_unique<ModelResourceManagementMockWrapper>(
|
||||
resourceManagementMock)};
|
||||
otherModel.attachView(&viewMock);
|
||||
|
||||
EXPECT_CALL(viewMock, modelAboutToBeDetached(&otherModel));
|
||||
EXPECT_CALL(viewMock, modelAttached(&model));
|
||||
|
||||
model.attachView(&viewMock);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user