forked from qt-creator/qt-creator
Some examples are defined in a Qt module (and therefore examples- manifest), but have dependencies on other modules. The example-manifests contain a `module` attribute for their `instructionals` tag, and examples can contain "docdependencies" items in their meta data, which are comma-separated lists of these module names. Read the `module` attributes (the meta data is already generically read) and check if the current set of examples-manifest contains all required ones for an example. Hide it, if not. Task-number: QTBUG-120759 Change-Id: Ib8ff80cf8a13965e57b5c4317e5d121c4127278b Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Kai Köhne <kai.koehne@qt.io>
241 lines
9.5 KiB
C++
241 lines
9.5 KiB
C++
// Copyright (C) 2022 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include <utils/filepath.h>
|
|
#include <qtsupport/examplesparser.h>
|
|
|
|
#include <QtTest>
|
|
|
|
using namespace Core;
|
|
using namespace Utils;
|
|
using namespace QtSupport::Internal;
|
|
|
|
class tst_Examples : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
tst_Examples();
|
|
~tst_Examples();
|
|
|
|
private slots:
|
|
void parsing_data();
|
|
void parsing();
|
|
};
|
|
|
|
tst_Examples::tst_Examples() = default;
|
|
tst_Examples::~tst_Examples() = default;
|
|
|
|
using MetaData = QHash<QString, QStringList>;
|
|
|
|
static ExampleItem fetchItem()
|
|
{
|
|
QFETCH(QString, name);
|
|
QFETCH(QString, description);
|
|
QFETCH(QString, imageUrl);
|
|
QFETCH(QStringList, tags);
|
|
QFETCH(FilePath, projectPath);
|
|
QFETCH(QString, docUrl);
|
|
QFETCH(FilePaths, filesToOpen);
|
|
QFETCH(FilePath, mainFile);
|
|
QFETCH(FilePaths, dependencies);
|
|
QFETCH(InstructionalType, type);
|
|
QFETCH(bool, hasSourceCode);
|
|
QFETCH(bool, isVideo);
|
|
QFETCH(bool, isHighlighted);
|
|
QFETCH(QString, videoUrl);
|
|
QFETCH(QString, videoLength);
|
|
QFETCH(QStringList, platforms);
|
|
QFETCH(MetaData, metaData);
|
|
ExampleItem item;
|
|
item.name = name;
|
|
item.description = description;
|
|
item.imageUrl = imageUrl;
|
|
item.tags = tags;
|
|
item.projectPath = projectPath;
|
|
item.docUrl = docUrl;
|
|
item.filesToOpen = filesToOpen;
|
|
item.mainFile = mainFile;
|
|
item.dependencies = dependencies;
|
|
item.type = type;
|
|
item.hasSourceCode = hasSourceCode;
|
|
item.isVideo = isVideo;
|
|
item.isHighlighted = isHighlighted;
|
|
item.videoUrl = videoUrl;
|
|
item.videoLength = videoLength;
|
|
item.platforms = platforms;
|
|
item.metaData = metaData;
|
|
return item;
|
|
}
|
|
|
|
void tst_Examples::parsing_data()
|
|
{
|
|
QTest::addColumn<QByteArray>("data");
|
|
QTest::addColumn<QString>("instructionalsModule");
|
|
QTest::addColumn<bool>("isExamples");
|
|
QTest::addColumn<QString>("name");
|
|
QTest::addColumn<QString>("description");
|
|
QTest::addColumn<QString>("imageUrl");
|
|
QTest::addColumn<QStringList>("tags");
|
|
QTest::addColumn<FilePath>("projectPath");
|
|
QTest::addColumn<QString>("docUrl");
|
|
QTest::addColumn<FilePaths>("filesToOpen");
|
|
QTest::addColumn<FilePath>("mainFile");
|
|
QTest::addColumn<FilePaths>("dependencies");
|
|
QTest::addColumn<InstructionalType>("type");
|
|
QTest::addColumn<bool>("hasSourceCode");
|
|
QTest::addColumn<bool>("isVideo");
|
|
QTest::addColumn<bool>("isHighlighted");
|
|
QTest::addColumn<QString>("videoUrl");
|
|
QTest::addColumn<QString>("videoLength");
|
|
QTest::addColumn<QStringList>("platforms");
|
|
QTest::addColumn<MetaData>("metaData");
|
|
QTest::addColumn<QStringList>("categories");
|
|
QTest::addColumn<QStringList>("categoryOrder");
|
|
|
|
QTest::addRow("example")
|
|
<< QByteArray(R"raw(
|
|
<instructionals module="QtGui">
|
|
<examples>
|
|
<example docUrl="qthelp://org.qt-project.qtwidgets.660/qtwidgets/qtwidgets-widgets-analogclock-example.html"
|
|
imageUrl="qthelp://org.qt-project.qtwidgets.660/qtwidgets/images/analogclock-example.png"
|
|
name="Analog Clock" projectPath="widgets/widgets/analogclock/CMakeLists.txt">
|
|
<description><![CDATA[The Analog Clock example shows how to draw the contents of a custom widget.]]></description>
|
|
<tags>ios,widgets</tags>
|
|
<fileToOpen>widgets/widgets/analogclock/main.cpp</fileToOpen>
|
|
<fileToOpen>widgets/widgets/analogclock/analogclock.h</fileToOpen>
|
|
<fileToOpen mainFile="true">widgets/widgets/analogclock/analogclock.cpp</fileToOpen>
|
|
<meta>
|
|
<entry name="category">Graphics</entry>
|
|
<entry name="category">Graphics</entry>
|
|
<entry name="category">Foobar</entry>
|
|
<entry name="tags">widgets</entry>
|
|
</meta>
|
|
</example>
|
|
</examples>
|
|
<categories>
|
|
<category>Application Examples</category>
|
|
<category>Desktop</category>
|
|
<category>Mobile</category>
|
|
<category>Embedded</category>
|
|
</categories>
|
|
</instructionals>
|
|
)raw") << "QtGui"
|
|
<< /*isExamples=*/true << "Analog Clock"
|
|
<< "The Analog Clock example shows how to draw the contents of a custom widget."
|
|
<< "qthelp://org.qt-project.qtwidgets.660/qtwidgets/images/analogclock-example.png"
|
|
<< QStringList{"ios", "widgets"}
|
|
<< FilePath::fromUserInput("examples/widgets/widgets/analogclock/CMakeLists.txt")
|
|
<< "qthelp://org.qt-project.qtwidgets.660/qtwidgets/"
|
|
"qtwidgets-widgets-analogclock-example.html"
|
|
<< FilePaths{FilePath::fromUserInput("examples/widgets/widgets/analogclock/main.cpp"),
|
|
FilePath::fromUserInput("examples/widgets/widgets/analogclock/analogclock.h"),
|
|
FilePath::fromUserInput(
|
|
"examples/widgets/widgets/analogclock/analogclock.cpp")}
|
|
<< FilePath::fromUserInput("examples/widgets/widgets/analogclock/analogclock.cpp")
|
|
<< FilePaths() << Example << true << false << false << ""
|
|
<< "" << QStringList()
|
|
<< MetaData({{"category", {"Graphics", "Graphics", "Foobar"}}, {"tags", {"widgets"}}})
|
|
<< QStringList{"Foobar", "Graphics"}
|
|
<< QStringList{"Application Examples", "Desktop", "Mobile", "Embedded"};
|
|
|
|
QTest::addRow("no category, highlighted")
|
|
<< QByteArray(R"raw(
|
|
<instructionals module="QtQuick3D">
|
|
<examples>
|
|
<example name="No Category, highlighted"
|
|
isHighlighted="true">
|
|
</example>
|
|
</examples>
|
|
</instructionals>
|
|
)raw") << "QtQuick3D"
|
|
<< /*isExamples=*/true << "No Category, highlighted" << QString() << QString()
|
|
<< QStringList() << FilePath("examples") << QString() << FilePaths() << FilePath()
|
|
<< FilePaths() << Example << /*hasSourceCode=*/false << false << /*isHighlighted=*/true
|
|
<< ""
|
|
<< "" << QStringList() << MetaData() << QStringList{"Featured"} << QStringList();
|
|
|
|
QTest::addRow("tutorial with category")
|
|
<< QByteArray(R"raw(
|
|
<instructionals module="Qt">
|
|
<categories>
|
|
<category>Help</category>
|
|
<category>Learning</category>
|
|
<category>Online</category>
|
|
<category>Talk</category>
|
|
</categories>
|
|
<tutorials>
|
|
<tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/dummytutorial.html" projectPath="" name="A tutorial">
|
|
<description><![CDATA[A dummy tutorial.]]></description>
|
|
<tags>qt creator,build,compile,help</tags>
|
|
<meta>
|
|
<entry name="category">Help</entry>
|
|
</meta>
|
|
</tutorial>
|
|
</tutorials>
|
|
</instructionals>
|
|
)raw") << "Qt"
|
|
<< /*isExamples=*/false << "A tutorial"
|
|
<< "A dummy tutorial."
|
|
<< ":qtsupport/images/icons/tutorialicon.png"
|
|
<< QStringList{"qt creator", "build", "compile", "help"} << FilePath()
|
|
<< "qthelp://org.qt-project.qtcreator/doc/dummytutorial.html" << FilePaths() << FilePath()
|
|
<< FilePaths() << Tutorial << /*hasSourceCode=*/false << /*isVideo=*/false
|
|
<< /*isHighlighted=*/false << QString() << QString() << QStringList()
|
|
<< MetaData({{"category", {"Help"}}}) << QStringList("Help")
|
|
<< QStringList{"Help", "Learning", "Online", "Talk"};
|
|
}
|
|
|
|
void tst_Examples::parsing()
|
|
{
|
|
QFETCH(QByteArray, data);
|
|
QFETCH(QString, instructionalsModule);
|
|
QFETCH(bool, isExamples);
|
|
QFETCH(QStringList, categories);
|
|
QFETCH(QStringList, categoryOrder);
|
|
const ExampleItem expected = fetchItem();
|
|
const expected_str<ParsedExamples> result = parseExamples(data,
|
|
FilePath(
|
|
"manifest/examples-manifest.xml"),
|
|
FilePath("examples"),
|
|
FilePath("demos"),
|
|
isExamples);
|
|
QVERIFY(result);
|
|
QCOMPARE(result->instructionalsModule, instructionalsModule);
|
|
QCOMPARE(result->categoryOrder, categoryOrder);
|
|
QCOMPARE(result->items.size(), 1);
|
|
const ExampleItem item = *result->items.at(0);
|
|
QCOMPARE(item.name, expected.name);
|
|
QCOMPARE(item.description, expected.description);
|
|
QCOMPARE(item.imageUrl, expected.imageUrl);
|
|
QCOMPARE(item.tags, expected.tags);
|
|
QCOMPARE(item.projectPath, expected.projectPath);
|
|
QCOMPARE(item.docUrl, expected.docUrl);
|
|
QCOMPARE(item.filesToOpen, expected.filesToOpen);
|
|
QCOMPARE(item.mainFile, expected.mainFile);
|
|
QCOMPARE(item.dependencies, expected.dependencies);
|
|
QCOMPARE(item.type, expected.type);
|
|
QCOMPARE(item.hasSourceCode, expected.hasSourceCode);
|
|
QCOMPARE(item.isVideo, expected.isVideo);
|
|
QCOMPARE(item.isHighlighted, expected.isHighlighted);
|
|
QCOMPARE(item.videoUrl, expected.videoUrl);
|
|
QCOMPARE(item.videoLength, expected.videoLength);
|
|
QCOMPARE(item.platforms, expected.platforms);
|
|
QCOMPARE(item.metaData, expected.metaData);
|
|
|
|
const QList<std::pair<Section, QList<ExampleItem *>>> resultCategories
|
|
= getCategories(result->items, true, {}, true);
|
|
QCOMPARE(resultCategories.size(), categories.size());
|
|
for (int i = 0; i < resultCategories.size(); ++i) {
|
|
QCOMPARE(resultCategories.at(i).first.name, categories.at(i));
|
|
QCOMPARE(resultCategories.at(i).second.size(), 1);
|
|
}
|
|
|
|
for (const auto &category : resultCategories)
|
|
qDeleteAll(category.second);
|
|
}
|
|
|
|
QTEST_APPLESS_MAIN(tst_Examples)
|
|
|
|
#include "tst_examples.moc"
|