File indexing completed on 2024-05-19 04:01:09

0001 /*
0002     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include "servercontroller.h"
0008 
0009 #include <rest/restapi.h>
0010 #include <rest/restclient.h>
0011 
0012 #include <core/product.h>
0013 #include <core/schemaentryelement.h>
0014 
0015 #include <QDebug>
0016 #include <QtTest/qtest.h>
0017 #include <QNetworkReply>
0018 #include <QObject>
0019 #include <QSignalSpy>
0020 #include <QStandardPaths>
0021 
0022 using namespace KUserFeedback::Console;
0023 
0024 class ProductApiTest : public QObject
0025 {
0026     Q_OBJECT
0027 private:
0028     ServerController m_server;
0029 
0030     ServerInfo testServer() const
0031     {
0032         ServerInfo s;
0033         s.setUrl(m_server.url());
0034         return s;
0035     }
0036 
0037     bool waitForFinished(QNetworkReply *reply)
0038     {
0039         Q_ASSERT(reply);
0040         QSignalSpy spy(reply, &QNetworkReply::finished);
0041         Q_ASSERT(spy.isValid());
0042         return spy.wait();
0043     }
0044 
0045     Product findProduct(const QVector<Product> &products, const QString &name)
0046     {
0047         const auto it = std::find_if(products.cbegin(), products.cend(), [name](const Product &p) {
0048             return p.name() == name;
0049         });
0050         if (it != products.cend())
0051             return *it;
0052         return {};
0053     }
0054 
0055 private Q_SLOTS:
0056     void initTestCase()
0057     {
0058         QStandardPaths::setTestModeEnabled(true);
0059         QVERIFY(m_server.start());
0060     }
0061 
0062     void testInvalidList()
0063     {
0064         RESTClient client;
0065         auto serverInfo = testServer();
0066         serverInfo.setPassword(QStringLiteral("wrong password"));
0067         client.setServerInfo(serverInfo);
0068         client.setConnected(true);
0069         QVERIFY(client.isConnected());
0070 
0071         auto reply = RESTApi::listProducts(&client);
0072         QVERIFY(waitForFinished(reply));
0073         QEXPECT_FAIL("", "local PHP tests don't authenticate", Continue);
0074         QVERIFY(reply->error() != QNetworkReply::NoError);
0075     }
0076 
0077     void testProductCRUD()
0078     {
0079         RESTClient client;
0080         client.setServerInfo(testServer());
0081         client.setConnected(true);
0082         QVERIFY(client.isConnected());
0083         Product newProduct;
0084         newProduct.setName(QStringLiteral("org.kde.UserFeedback.UnitTestProduct"));
0085 
0086         // clean up from previous failed runs, if needed
0087         auto reply = RESTApi::deleteProduct(&client, newProduct);
0088         waitForFinished(reply);
0089 
0090         // list existing products
0091         reply = RESTApi::listProducts(&client);
0092         QVERIFY(waitForFinished(reply));
0093         QCOMPARE(reply->error(), QNetworkReply::NoError);
0094         QVERIFY(reply->header(QNetworkRequest::ContentTypeHeader).toString().startsWith(QLatin1String("text/json")));
0095         const auto products = Product::fromJson(reply->readAll());
0096         QVERIFY(!findProduct(products, QLatin1String("org.kde.UserFeedback.UnitTestProduct")).isValid());
0097 
0098         // add new product
0099         SchemaEntry entry;
0100         entry.setName(QStringLiteral("entry1"));
0101         SchemaEntryElement elem1;
0102         elem1.setName(QStringLiteral("elem11"));
0103         entry.setElements({elem1});
0104         newProduct.setSchema({entry});
0105         QVERIFY(newProduct.isValid());
0106         reply = RESTApi::createProduct(&client, newProduct);
0107         QVERIFY(waitForFinished(reply));
0108         QCOMPARE(reply->error(), QNetworkReply::NoError);
0109 
0110         // verify the new product is there
0111         reply = RESTApi::listProducts(&client);
0112         QVERIFY(waitForFinished(reply));
0113         QCOMPARE(reply->error(), QNetworkReply::NoError);
0114         auto newProducts = Product::fromJson(reply->readAll());
0115         QCOMPARE(newProducts.size(), products.size() + 1);
0116         const auto createdProduct = findProduct(newProducts, QLatin1String("org.kde.UserFeedback.UnitTestProduct"));
0117         QVERIFY(createdProduct.isValid());
0118         QCOMPARE(createdProduct.schema(), newProduct.schema());
0119 
0120         // update a product
0121         reply = RESTApi::updateProduct(&client, newProduct);
0122         QVERIFY(waitForFinished(reply));
0123         QCOMPARE(reply->error(), QNetworkReply::NoError);
0124 
0125         // try to add an already existing product
0126         reply = RESTApi::createProduct(&client, newProduct);
0127         QVERIFY(waitForFinished(reply));
0128         QVERIFY(reply->error() != QNetworkReply::NoError);
0129 
0130         // verify it really wasn't added
0131         reply = RESTApi::listProducts(&client);
0132         QVERIFY(waitForFinished(reply));
0133         QCOMPARE(reply->error(), QNetworkReply::NoError);
0134         newProducts = Product::fromJson(reply->readAll());
0135         QCOMPARE(newProducts.size(), products.size() + 1);
0136 
0137         // delete a product
0138         reply = RESTApi::deleteProduct(&client, newProduct);
0139         QVERIFY(waitForFinished(reply));
0140         QCOMPARE(reply->error(), QNetworkReply::NoError);
0141 
0142         // verify it's gone, and nothing else was harmed
0143         reply = RESTApi::listProducts(&client);
0144         QVERIFY(waitForFinished(reply));
0145         QCOMPARE(reply->error(), QNetworkReply::NoError);
0146         newProducts = Product::fromJson(reply->readAll());
0147         QCOMPARE(newProducts.size(), products.size());
0148         QVERIFY(!findProduct(newProducts, QLatin1String("org.kde.UserFeedback.UnitTestProduct")).isValid());
0149     }
0150 
0151     void testInvalidProductOperations()
0152     {
0153         RESTClient client;
0154         client.setServerInfo(testServer());
0155         client.setConnected(true);
0156         QVERIFY(client.isConnected());
0157 
0158         Product invalidProduct;
0159         invalidProduct.setName(QStringLiteral("org.kde.UserFeedback.Invalid"));
0160         QVERIFY(invalidProduct.isValid());
0161 
0162         // update a non-existing product
0163         auto reply = RESTApi::updateProduct(&client, invalidProduct);
0164         QVERIFY(waitForFinished(reply));
0165         qDebug() << reply->readAll();
0166         QVERIFY(reply->error() != QNetworkReply::NoError);
0167 
0168         // delete a non-existing product
0169         reply = RESTApi::deleteProduct(&client, invalidProduct);
0170         QVERIFY(waitForFinished(reply));
0171         QVERIFY(reply->error() != QNetworkReply::NoError);
0172     }
0173 };
0174 
0175 QTEST_MAIN(ProductApiTest)
0176 
0177 #include "productapitest.moc"