Commit 3c6adac6 authored by Volker Krause's avatar Volker Krause
Browse files

Refactor analyzer code for being testable

This extracts product related data structures and REST API into a static
library, for use in the application and unit tests. This also adds a
unit test for the product-related REST API.
parent 236fe54a
......@@ -75,7 +75,7 @@ endif()
if(Qt5Core_FOUND)
set_package_properties(Qt5Core PROPERTIES TYPE REQUIRED)
find_package(Qt5 NO_MODULE REQUIRED COMPONENTS Network)
find_package(Qt5 NO_MODULE QUIET OPTIONAL_COMPONENTS Widgets Charts)
find_package(Qt5 NO_MODULE QUIET OPTIONAL_COMPONENTS Widgets Charts Test)
find_package(KF5WidgetsAddons NO_MODULE QUIET)
if(Qt5_POSITION_INDEPENDENT_CODE AND NOT WIN32)
......@@ -157,6 +157,7 @@ if(Qt5Charts_FOUND AND KF5WidgetsAddons_FOUND AND NOT CMAKE_VERSION VERSION_LESS
add_subdirectory(analyzer)
add_subdirectory(tests/manual)
endif()
add_subdirectory(tests/auto)
#
# CMake package config file generation
......
set(analyzer_lib_srcs
core/product.cpp
core/productschemaentry.cpp
rest/restapi.cpp
rest/restclient.cpp
rest/serverinfo.cpp
)
add_library(UserFeedbackAnalyzer STATIC ${analyzer_lib_srcs})
target_link_libraries(UserFeedbackAnalyzer Qt5::Network)
target_include_directories(UserFeedbackAnalyzer PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};>")
set(analyzer_srcs
aggregateddatamodel.cpp
categoryaggregationmodel.cpp
......@@ -7,25 +20,22 @@ set(analyzer_srcs
main.cpp
mainwindow.cpp
numericaggregationmodel.cpp
product.cpp
productmodel.cpp
productschemaentry.cpp
ratioset.cpp
ratiosetaggregationmodel.cpp
restclient.cpp
sample.cpp
schemamodel.cpp
schemaeditwidget.cpp
schemaentryitemeditorfactory.cpp
schemaentrytypecombobox.cpp
serverinfo.cpp
survey.cpp
surveydialog.cpp
surveymodel.cpp
timeaggregationmodel.cpp
)
add_executable(UserFeedbackAnalyzer ${analyzer_srcs})
target_link_libraries(UserFeedbackAnalyzer Qt5::Widgets Qt5::Network Qt5::Charts UserFeedbackWidgets)
add_executable(UserFeedbackAnalyzerApplication ${analyzer_srcs})
set_target_properties(UserFeedbackAnalyzerApplication PROPERTIES OUTPUT_NAME UserFeedbackAnalyzer)
target_link_libraries(UserFeedbackAnalyzerApplication Qt5::Widgets Qt5::Network Qt5::Charts UserFeedbackWidgets UserFeedbackAnalyzer)
install(TARGETS UserFeedbackAnalyzer ${INSTALL_TARGETS_DEFAULT_ARGS})
install(TARGETS UserFeedbackAnalyzerApplication ${INSTALL_TARGETS_DEFAULT_ARGS})
......@@ -18,7 +18,7 @@
#include "connectdialog.h"
#include "ui_connectdialog.h"
#include "serverinfo.h"
#include <rest/serverinfo.h>
#include <QIcon>
#include <QUrl>
......
......@@ -18,7 +18,7 @@
#include "datamodel.h"
#include "ratioset.h"
#include "restclient.h"
#include <rest/restclient.h>
#include "sample.h"
#include <QDebug>
......
......@@ -18,7 +18,7 @@
#ifndef USERFEEDBACK_ANALYZER_DATAMODEL_H
#define USERFEEDBACK_ANALYZER_DATAMODEL_H
#include "product.h"
#include <core/product.h>
#include <QAbstractTableModel>
#include <QJsonArray>
......
......@@ -27,12 +27,14 @@
#include "numericaggregationmodel.h"
#include "productmodel.h"
#include "ratiosetaggregationmodel.h"
#include "restclient.h"
#include "serverinfo.h"
#include "surveydialog.h"
#include "surveymodel.h"
#include "timeaggregationmodel.h"
#include <rest/restapi.h>
#include <rest/restclient.h>
#include <rest/serverinfo.h>
#include <provider/widgets/feedbackconfigdialog.h>
#include <provider/core/propertyratiosource.h>
#include <provider/core/provider.h>
......@@ -131,7 +133,7 @@ MainWindow::MainWindow() :
});
connect(ui->schemaEdit, &SchemaEditWidget::productChanged, this, [this](const Product &p) {
auto reply = m_restClient->put(QStringLiteral("products/") + p.name(), p.toJson());
auto reply = RESTApi::updateProduct(m_restClient, p);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error() != QNetworkReply::NoError)
return;
......@@ -226,7 +228,7 @@ void MainWindow::createProduct()
product.setSchema(schema);
auto reply = m_restClient->post(QStringLiteral("products"), product.toJson());
auto reply = RESTApi::createProduct(m_restClient, product);
connect(reply, &QNetworkReply::finished, this, [this, reply, name]() {
if (reply->error() == QNetworkReply::NoError) {
logMessage(QString::fromUtf8(reply->readAll()));
......@@ -242,7 +244,7 @@ void MainWindow::deleteProduct()
return;
const auto product = sel.first().data(ProductModel::ProductRole).value<Product>();
// TODO saftey question
auto reply = m_restClient->deleteResource(QStringLiteral("products/") + product.name());
auto reply = RESTApi::deleteProduct(m_restClient, product);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error() == QNetworkReply::NoError) {
logMessage(QString::fromUtf8(reply->readAll()));
......
......@@ -16,7 +16,9 @@
*/
#include "productmodel.h"
#include "restclient.h"
#include <rest/restapi.h>
#include <rest/restclient.h>
#include <QNetworkReply>
......@@ -42,7 +44,7 @@ void ProductModel::reload()
if (!m_restClient->isConnected())
return;
auto reply = m_restClient->get(QStringLiteral("products"));
auto reply = RESTApi::getProducts(m_restClient);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error() == QNetworkReply::NoError) {
beginResetModel();
......
......@@ -18,8 +18,8 @@
#ifndef USERFEEDBACK_ANALYZER_PRODUCTMODEL_H
#define USERFEEDBACK_ANALYZER_PRODUCTMODEL_H
#include "product.h"
#include "serverinfo.h"
#include <core/product.h>
#include <rest/serverinfo.h>
#include <QAbstractListModel>
#include <QVector>
......
/*
Copyright (C) 2016 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "restapi.h"
#include "restclient.h"
#include <core/product.h>
using namespace UserFeedback::Analyzer;
QNetworkReply* RESTApi::getProducts(RESTClient *client)
{
return client->get(QStringLiteral("products"));
}
QNetworkReply* RESTApi::createProduct(RESTClient *client, const Product &p)
{
Q_ASSERT(p.isValid());
return client->post(QStringLiteral("products"), p.toJson());
}
QNetworkReply* RESTApi::updateProduct(RESTClient *client, const Product &p)
{
Q_ASSERT(p.isValid());
return client->put(QStringLiteral("products/") + p.name(), p.toJson());
}
QNetworkReply* RESTApi::deleteProduct(RESTClient *client, const Product &p)
{
Q_ASSERT(p.isValid());
return client->deleteResource(QStringLiteral("products/") + p.name());
}
/*
Copyright (C) 2016 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERFEEDBACK_ANALYZER_RESTAPI_H
#define USERFEEDBACK_ANALYZER_RESTAPI_H
class QNetworkReply;
namespace UserFeedback {
namespace Analyzer {
class Product;
class RESTClient;
/** C++ wrapper for the server-side API.
* Precondition for all methods is that client->isConnected() returns @c true.
*/
namespace RESTApi
{
/** List all products. */
QNetworkReply* getProducts(RESTClient *client);
/** Add a new product.
* @param p The product to add. Must be valid.
*/
QNetworkReply* createProduct(RESTClient *client, const Product &p);
/** Update an existing product.
* @param p The product to add. Must be valid.
*/
QNetworkReply* updateProduct(RESTClient *client, const Product &p);
/** Deletes a product.
* @param p The product to add. Must be valid.
*/
QNetworkReply* deleteProduct(RESTClient *client, const Product &p);
}
}
}
#endif // USERFEEDBACK_ANALYZER_RESTAPI_H
......@@ -55,7 +55,8 @@ QNetworkReply* RESTClient::get(const QString& command)
QNetworkReply* RESTClient::post(const QString& command, const QByteArray& data)
{
const auto request = makeRequest(command);
auto request = makeRequest(command);
request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json"));
auto reply = m_networkAccessManager->post(request, data);
setupMessageHandler(reply);
return reply;
......
......@@ -16,8 +16,8 @@
*/
#include "sample.h"
#include "product.h"
#include "productschemaentry.h"
#include <core/product.h>
#include <core/productschemaentry.h>
#include "ratioset.h"
#include <QDateTime>
......@@ -95,4 +95,4 @@ QVector<Sample> Sample::fromJson(const QByteArray &json, const Product &product)
samples.push_back(s);
}
return samples;
}
\ No newline at end of file
}
......@@ -18,7 +18,7 @@
#include "schemaeditwidget.h"
#include "ui_schemaeditwidget.h"
#include "product.h"
#include <core/product.h>
#include "schemaentryitemeditorfactory.h"
#include "schemamodel.h"
......@@ -87,4 +87,4 @@ void SchemaEditWidget::updateState()
ui->addEntryButton->setEnabled(!ui->newEntryName->text().isEmpty());
ui->saveButton->setEnabled(m_schemaModel->product().isValid());
}
\ No newline at end of file
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment