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())
|
if (!view->isEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_viewList.contains(view))
|
if (view->isAttached()) {
|
||||||
return;
|
if (view->model() == m_model)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
view->model()->detachView(view);
|
||||||
|
}
|
||||||
|
|
||||||
m_viewList.append(view);
|
m_viewList.append(view);
|
||||||
|
|
||||||
if (!view->isAttached())
|
view->modelAttached(m_model);
|
||||||
view->modelAttached(m_model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelPrivate::detachView(AbstractView *view, bool notifyView)
|
void ModelPrivate::detachView(AbstractView *view, bool notifyView)
|
||||||
@@ -1641,6 +1644,9 @@ void ModelPrivate::setNodeInstanceView(AbstractView *nodeInstanceView)
|
|||||||
if (nodeInstanceView && nodeInstanceView->kind() != AbstractView::Kind::NodeInstance)
|
if (nodeInstanceView && nodeInstanceView->kind() != AbstractView::Kind::NodeInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (nodeInstanceView && nodeInstanceView->isAttached())
|
||||||
|
nodeInstanceView->model()->setNodeInstanceView(nullptr);
|
||||||
|
|
||||||
if (m_nodeInstanceView)
|
if (m_nodeInstanceView)
|
||||||
m_nodeInstanceView->modelAboutToBeDetached(m_model);
|
m_nodeInstanceView->modelAboutToBeDetached(m_model);
|
||||||
|
|
||||||
|
@@ -105,11 +105,13 @@ Internal::TextToModelMerger *RewriterView::textToModelMerger() const
|
|||||||
|
|
||||||
void RewriterView::modelAttached(Model *model)
|
void RewriterView::modelAttached(Model *model)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_textModifier, return);
|
|
||||||
m_modelAttachPending = false;
|
|
||||||
|
|
||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
|
|
||||||
|
if (!m_textModifier)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_modelAttachPending = false;
|
||||||
|
|
||||||
ModelAmender differenceHandler(m_textToModelMerger.get());
|
ModelAmender differenceHandler(m_textToModelMerger.get());
|
||||||
const QString qmlSource = m_textModifier->text();
|
const QString qmlSource = m_textModifier->text();
|
||||||
if (m_textToModelMerger->load(qmlSource, differenceHandler))
|
if (m_textToModelMerger->load(qmlSource, differenceHandler))
|
||||||
|
@@ -14,7 +14,15 @@ class AbstractViewMock : public QmlDesigner::AbstractView
|
|||||||
public:
|
public:
|
||||||
AbstractViewMock(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr)
|
AbstractViewMock(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr)
|
||||||
: QmlDesigner::AbstractView{*externalDependencies}
|
: 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, nodeOrderChanged, (const QmlDesigner::NodeListProperty &listProperty), (override));
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
variantPropertiesChanged,
|
variantPropertiesChanged,
|
||||||
@@ -57,4 +65,9 @@ public:
|
|||||||
(override));
|
(override));
|
||||||
MOCK_METHOD(void, nodeAboutToBeRemoved, (const QmlDesigner::ModelNode &removedNode), (override));
|
MOCK_METHOD(void, nodeAboutToBeRemoved, (const QmlDesigner::ModelNode &removedNode), (override));
|
||||||
MOCK_METHOD(void, refreshMetaInfos, (const QmlDesigner::TypeIds &), (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 <matchers/import-matcher.h>
|
||||||
#include <mocks/abstractviewmock.h>
|
#include <mocks/abstractviewmock.h>
|
||||||
|
#include <mocks/externaldependenciesmock.h>
|
||||||
#include <mocks/modelresourcemanagementmock.h>
|
#include <mocks/modelresourcemanagementmock.h>
|
||||||
#include <mocks/projectstoragemock.h>
|
#include <mocks/projectstoragemock.h>
|
||||||
#include <mocks/projectstorageobservermock.h>
|
#include <mocks/projectstorageobservermock.h>
|
||||||
#include <mocks/sourcepathcachemock.h>
|
#include <mocks/sourcepathcachemock.h>
|
||||||
|
|
||||||
#include <designercore/include/bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
#include <designercore/include/itemlibraryentry.h>
|
#include <itemlibraryentry.h>
|
||||||
#include <designercore/include/model.h>
|
#include <model.h>
|
||||||
#include <designercore/include/modelnode.h>
|
#include <modelnode.h>
|
||||||
#include <designercore/include/nodeabstractproperty.h>
|
#include <nodeabstractproperty.h>
|
||||||
#include <designercore/include/nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
#include <designercore/include/nodemetainfo.h>
|
#include <nodemetainfo.h>
|
||||||
#include <designercore/include/nodeproperty.h>
|
#include <nodeproperty.h>
|
||||||
#include <designercore/include/signalhandlerproperty.h>
|
#include <rewriterview.h>
|
||||||
#include <designercore/include/variantproperty.h>
|
#include <signalhandlerproperty.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
using QmlDesigner::AbstractProperty;
|
using QmlDesigner::AbstractProperty;
|
||||||
|
using QmlDesigner::AbstractView;
|
||||||
using QmlDesigner::ModelNode;
|
using QmlDesigner::ModelNode;
|
||||||
using QmlDesigner::ModelNodes;
|
using QmlDesigner::ModelNodes;
|
||||||
using QmlDesigner::ModelResourceSet;
|
using QmlDesigner::ModelResourceSet;
|
||||||
@@ -119,13 +122,13 @@ protected:
|
|||||||
NiceMock<ProjectStorageMockWithQtQuick> projectStorageMock{pathCacheMock.sourceId, "/path"};
|
NiceMock<ProjectStorageMockWithQtQuick> projectStorageMock{pathCacheMock.sourceId, "/path"};
|
||||||
NiceMock<ModelResourceManagementMock> resourceManagementMock;
|
NiceMock<ModelResourceManagementMock> resourceManagementMock;
|
||||||
QmlDesigner::Imports imports = {QmlDesigner::Import::createLibraryImport("QtQuick")};
|
QmlDesigner::Imports imports = {QmlDesigner::Import::createLibraryImport("QtQuick")};
|
||||||
|
NiceMock<AbstractViewMock> viewMock;
|
||||||
QmlDesigner::Model model{{projectStorageMock, pathCacheMock},
|
QmlDesigner::Model model{{projectStorageMock, pathCacheMock},
|
||||||
"Item",
|
"Item",
|
||||||
imports,
|
imports,
|
||||||
QUrl::fromLocalFile(pathCacheMock.path.toQString()),
|
QUrl::fromLocalFile(pathCacheMock.path.toQString()),
|
||||||
std::make_unique<ModelResourceManagementMockWrapper>(
|
std::make_unique<ModelResourceManagementMockWrapper>(
|
||||||
resourceManagementMock)};
|
resourceManagementMock)};
|
||||||
NiceMock<AbstractViewMock> viewMock;
|
|
||||||
QmlDesigner::SourceId filePathId = pathCacheMock.sourceId;
|
QmlDesigner::SourceId filePathId = pathCacheMock.sourceId;
|
||||||
QmlDesigner::ModuleId qtQuickModuleId = projectStorageMock.moduleId("QtQuick",
|
QmlDesigner::ModuleId qtQuickModuleId = projectStorageMock.moduleId("QtQuick",
|
||||||
ModuleKind::QmlLibrary);
|
ModuleKind::QmlLibrary);
|
||||||
@@ -1201,4 +1204,121 @@ TEST_F(Model_TypeAnnotation, item_library_entries)
|
|||||||
ElementsAre(u"/extra/file/path"))));
|
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
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user