// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tst_qmlformat_base.h" using namespace QQmlJS::Dom; // TODO refactor extension helpers const QString QML_EXT = ".qml"; const QString JS_EXT = ".js"; const QString MJS_EXT = ".mjs"; static QStringView fileExt(QStringView filename) { if (filename.endsWith(QML_EXT)) { return QML_EXT; } if (filename.endsWith(JS_EXT)) { return JS_EXT; } if (filename.endsWith(MJS_EXT)) { return MJS_EXT; } Q_UNREACHABLE(); }; class TestQmlformatCli : public TestQmlformatBase { Q_OBJECT public: enum class RunOption { OnCopy, OrigToCopy }; TestQmlformatCli(); private Q_SLOTS: void initTestCase() override; // actually testFormat tests CLI of qmlformat void testFormat(); void testFormat_data(); void testLineEndings(); void testBackupFileLimit(); void testFilesOption_data(); void testFilesOption(); void commandLineOptions_data(); void commandLineOptions(); void writeDefaults(); void outputOptions(); void settingsKeysStayStable(); void settingsFromFileOrCommandLine_data(); void settingsFromFileOrCommandLine(); void multipleSettingsFiles(); private: // TODO(QTBUG-117849) refactor this helper function QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true, RunOption rOption = RunOption::OnCopy, QStringView ext = QML_EXT); QString m_qmlformatPath; }; // Don't fail on warnings because we read a lot of QML files that might intentionally be malformed. TestQmlformatCli::TestQmlformatCli() : TestQmlformatBase(QT_QMLTEST_DATADIR, FailOnWarningsPolicy::DoNotFailOnWarnings) { } void TestQmlformatCli::initTestCase() { QQmlDataTest::initTestCase(); m_qmlformatPath = QLibraryInfo::path(QLibraryInfo::BinariesPath) + QLatin1String("/qmlformat"); #ifdef Q_OS_WIN m_qmlformatPath += QLatin1String(".exe"); #endif if (!QFileInfo(m_qmlformatPath).exists()) { QString message = QStringLiteral("qmlformat executable not found (looked for %0)").arg(m_qmlformatPath); QFAIL(qPrintable(message)); } } QString TestQmlformatCli::runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed, RunOption rOptions, QStringView ext) { // Copy test file to temporary location QTemporaryDir tempDir; const QString tempFile = (tempDir.path() + QDir::separator() + "to_format") % ext; if (rOptions == RunOption::OnCopy) { QFile::copy(fileToFormat, tempFile); QFile::copy(testFile(".qmlformat.ini"), tempDir.filePath(".qmlformat.ini")); args << QLatin1String("-i"); args << tempFile; } else { args << fileToFormat; } auto verify = [&]() { QProcess process; if (rOptions == RunOption::OrigToCopy) process.setStandardOutputFile(tempFile); process.start(m_qmlformatPath, args); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); if (shouldSucceed) QCOMPARE(process.exitCode(), 0); }; verify(); QFile temp(tempFile); if (!temp.open(QIODevice::ReadOnly)) qFatal("Could not open %s", qPrintable(tempFile)); QString formatted = QString::fromUtf8(temp.readAll()); return formatted; } void TestQmlformatCli::testLineEndings() { // macos const QString macosContents = runQmlformat(testFile("Example1.formatted.qml"), { "-l", "macos" }); QVERIFY(!macosContents.contains("\n")); QVERIFY(macosContents.contains("\r")); // windows const QString windowsContents = runQmlformat(testFile("Example1.formatted.qml"), { "-l", "windows" }); QVERIFY(windowsContents.contains("\r\n")); // unix const QString unixContents = runQmlformat(testFile("Example1.formatted.qml"), { "-l", "unix" }); QVERIFY(unixContents.contains("\n")); QVERIFY(!unixContents.contains("\r")); } void TestQmlformatCli::testFormat_data() { QTest::addColumn("file"); QTest::addColumn("fileFormatted"); QTest::addColumn("args"); QTest::addColumn("runOption"); QTest::newRow("example1 (tabs)") << "Example1.qml" << "Example1.formatted.tabs.qml" << QStringList { "-t" } << RunOption::OnCopy; QTest::newRow("example1 (two spaces)") << "Example1.qml" << "Example1.formatted.2spaces.qml" << QStringList { "-w", "2" } << RunOption::OnCopy; QTest::newRow("settings") << "settings/Example1.qml" << "settings/Example1.formatted_mac_cr.qml" << QStringList {} << RunOption::OrigToCopy; QTest::newRow("objects spacing (no changes)") << "objectsSpacing.qml" << "objectsSpacing.formatted.qml" << QStringList { "--objects-spacing" } << RunOption::OnCopy; QTest::newRow("normalize + objects spacing") << "normalizedObjectsSpacing.qml" << "normalizedObjectsSpacing.formatted.qml" << QStringList { "-n", "--objects-spacing" } << RunOption::OnCopy; QTest::newRow("sorting imports") << "sortingImports.qml" << "sortingImports.formatted.qml" << QStringList { "-S" } << RunOption::OnCopy; QTest::newRow("ids new lines") << "checkIdsNewline.qml" << "checkIdsNewline.formatted.qml" << QStringList { "-n" } << RunOption::OnCopy; QTest::newRow("functions spacing (no changes)") << "functionsSpacing.qml" << "functionsSpacing.formatted.qml" << QStringList { "--functions-spacing" } << RunOption::OnCopy; QTest::newRow("normalize + functions spacing") << "normalizedFunctionsSpacing.qml" << "normalizedFunctionsSpacing.formatted.qml" << QStringList { "-n", "--functions-spacing" } << RunOption::OnCopy; QTest::newRow("normalize + keep attributes order") << "normalizedGroupAttributesTogether.qml" << "normalizedGroupAttributesTogether.formatted.qml" << QStringList{ "-n", "--group-attributes-together" } << RunOption::OnCopy; QTest::newRow("indentEquals2") << "threeFunctionsOneLine.js" << "threeFunctions.formattedW2.js" << QStringList{"-w=2"} << RunOption::OnCopy; QTest::newRow("tabIndents") << "threeFunctionsOneLine.js" << "threeFunctions.formattedTabs.js" << QStringList{"-t"} << RunOption::OnCopy; QTest::newRow("normalizedFunctionSpacing") << "threeFunctionsOneLine.js" << "threeFunctions.formattedFuncSpacing.js" << QStringList{ "-n", "--functions-spacing" } << RunOption::OnCopy; QTest::newRow("esm_tabIndents") << "mini_esm.mjs" << "mini_esm.formattedTabs.mjs" << QStringList{ "-t" } << RunOption::OnCopy; QTest::newRow("singeLineEmptyObjects") << "singleLineEmptyObjects.qml" << "singleLineEmptyObjects.formatted.qml" << QStringList{ "--single-line-empty-objects" } << RunOption::OnCopy; } void TestQmlformatCli::testFormat() { QFETCH(QString, file); QFETCH(QString, fileFormatted); QFETCH(QStringList, args); QFETCH(RunOption, runOption); auto formatted = runQmlformat(testFile(file), args, true, runOption, fileExt(file)); QEXPECT_FAIL("normalizedFunctionSpacing", "Normalize && function spacing are not yet supported for JS", Abort); auto exp = readTestFile(fileFormatted); QCOMPARE(formatted, exp); } void TestQmlformatCli::testBackupFileLimit() { // Create a temporary directory QTemporaryDir tempDir; // Unformatted file to format const QString fileToFormat{ testFile("Annotations.qml") }; { const QString tempFile = tempDir.path() + QDir::separator() + "test_0.qml"; const QString backupFile = tempFile + QStringLiteral("~"); QFile::copy(fileToFormat, tempFile); QProcess process; process.start(m_qmlformatPath, QStringList{ "--verbose", "--inplace", tempFile }); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); QVERIFY(QFileInfo::exists(tempFile)); QVERIFY(!QFileInfo::exists(backupFile)); }; } void TestQmlformatCli::testFilesOption_data() { QTest::addColumn("containerFile"); QTest::addColumn("individualFiles"); QTest::newRow("initial") << "fileListToFormat" << QStringList{ "valid1.qml", "valid2.qml" }; } void TestQmlformatCli::testFilesOption() { QFETCH(QString, containerFile); QFETCH(QStringList, individualFiles); // Create a temporary directory QTemporaryDir tempDir; QStringList actualFormattedFilesPath; // Iterate through files in the source directory and copy them to the temporary directory const auto sourceDir = dataDirectory() + QDir::separator() + "filesOption"; // Create a file that contains the list of files to be formatted const QString tempFilePath = tempDir.path() + QDir::separator() + containerFile; QFile container(tempFilePath); QVERIFY2(container.open(QIODevice::Text | QIODevice::WriteOnly), "Cannot create temp test file"); QFile::copy(testFile(".qmlformat.ini"), tempDir.filePath(".qmlformat.ini")); QTextStream out(&container); for (const auto &file : individualFiles) { QString destinationFilePath = tempDir.path() + QDir::separator() + file; if (QFile::copy(sourceDir + QDir::separator() + file, destinationFilePath)) actualFormattedFilesPath << destinationFilePath; out << destinationFilePath << "\n"; } container.close(); { QProcess process; process.start(m_qmlformatPath, QStringList{"-F", tempFilePath}); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); } const auto readFile = [](const QString &filePath){ QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Error on opening the file " << filePath; return QByteArray{}; } return file.readAll(); }; for (const auto &filePath : std::as_const(actualFormattedFilesPath)) { auto expectedFormattedFile = QFileInfo(filePath).fileName(); const auto expectedFormattedFilePath = sourceDir + QDir::separator() + expectedFormattedFile.replace(".qml", ".formatted.qml"); QCOMPARE(readFile(filePath), readFile(expectedFormattedFilePath)); } } void TestQmlformatCli::commandLineOptions_data() { QTest::addColumn("args"); QTest::addColumn("expectedErrorMessage"); const QString dummy = testFile("dummy.qml"); const QString empty = testFile("empty"); QTest::newRow("columnWidthError") << QStringList{ dummy, "-W", "-11111" } << "Error: Invalid value passed to -W. Must be an integer >= -1\n"; QTest::newRow("columnWidthNoError") << QStringList{ dummy, "-W", "80" } << ""; QTest::newRow("indentWidthError") << QStringList{ dummy, "--indent-width", "expect integer" } << "Error: Invalid value passed to -w\n"; QTest::newRow("indentWidthNoError") << QStringList{ dummy, "--indent-width", "4" } << ""; QTest::newRow("noInputFiles.qml") << QStringList{} << "Error: Expected at least one input file.\n"; QTest::newRow("fOptionFileDoesNotExist") << QStringList{ "-F", "nope" } << "Error: Could not open file \"nope\" for option -F.\n"; QTest::newRow("fOptionFileIsEmpty") << QStringList{ "-F", empty } << "Error: File \"" + empty + "\" for option -F is empty.\n"; QTest::newRow("fOptionFileContainsNope") << QStringList{ "-F", testFile("filesToFormatNope") } << "Error: Entry \"nope\" of file \"" + testFile("filesToFormatNope") + "\" passed to option -F could not be found.\n"; QTest::newRow("positionalArgumentDoesNotExist") << QStringList{ "nope" } << "Error: Could not find file \"nope\".\n"; } void TestQmlformatCli::commandLineOptions() { QFETCH(QStringList, args); QFETCH(QString, expectedErrorMessage); auto verify = [&]() { QTemporaryDir tempDir; const QString tempFile = tempDir.path() + QDir::separator() + "test_0.qml"; QProcess process; process.setStandardOutputFile(tempFile); process.start(m_qmlformatPath, args); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); // normalized error message auto rawError = process.readAllStandardError(); QTextStream stream(&rawError, QIODeviceBase::ReadOnly | QIODeviceBase::Text); QCOMPARE(stream.readAll(), expectedErrorMessage.toUtf8()); if (expectedErrorMessage.isEmpty()) QCOMPARE(process.exitCode(), 0); else QCOMPARE_NE(process.exitCode(), 0); }; verify(); } void TestQmlformatCli::writeDefaults() { QTemporaryDir tempDir; const QString qmlformatIni = tempDir.path() + QDir::separator() + ".qmlformat.ini"; QProcess process; process.setWorkingDirectory(tempDir.path()); process.start(m_qmlformatPath, QStringList{ "--write-defaults" }); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QQmlToolingSettings settings("qmlformat"); QVERIFY(settings.search(qmlformatIni).isValid()); QVERIFY(settings.isSet(QQmlFormatSettings::s_useTabsSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_useTabsSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_indentWidthSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_indentWidthSetting).toInt(), 4); QVERIFY(settings.isSet(QQmlFormatSettings::s_maxColumnWidthSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_maxColumnWidthSetting).toInt(), -1); QVERIFY(settings.isSet(QQmlFormatSettings::s_normalizeSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_normalizeSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_newlineSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_newlineSetting).toString(), "native"); QVERIFY(settings.isSet(QQmlFormatSettings::s_objectsSpacingSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_objectsSpacingSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_functionsSpacingSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_functionsSpacingSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_groupAttributesTogetherSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_groupAttributesTogetherSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_sortImportsSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_sortImportsSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_singleLineEmptyObjectsSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_singleLineEmptyObjectsSetting).toBool(), false); QVERIFY(settings.isSet(QQmlFormatSettings::s_semiColonRuleSetting)); QCOMPARE(settings.value(QQmlFormatSettings::s_semiColonRuleSetting).toString(), "always"_L1); } void TestQmlformatCli::outputOptions() { QProcess process; process.start(m_qmlformatPath, QStringList{ "--output-options" }); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QJsonDocument doc = QJsonDocument::fromJson(process.readAllStandardOutput()); auto findJsonObject = [doc](const QString &name){ QJsonObject rootObj = doc.object(); QJsonArray optionsArray = rootObj["options"].toArray(); for (const QJsonValue &optionValue : optionsArray) { if (!optionValue.isObject()) continue; QJsonObject optionObj = optionValue.toObject(); if (optionObj["name"].toString() == name) return optionObj; } return QJsonObject(); }; { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_useTabsSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_indentWidthSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], 4); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_maxColumnWidthSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], -1); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_normalizeSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_newlineSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], "native"_L1); QCOMPARE(obj["hint"], QStringList({ "unix", "windows", "macos", "native" }).join(',')); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_objectsSpacingSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_functionsSpacingSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_groupAttributesTogetherSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_sortImportsSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_singleLineEmptyObjectsSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], false); QCOMPARE(obj["hint"], QMetaType::fromType().name()); } { QJsonObject obj = findJsonObject(QQmlFormatSettings::s_semiColonRuleSetting); QVERIFY(!obj.isEmpty()); QCOMPARE(obj["value"], "always"_L1); QCOMPARE(obj["hint"], QStringList({ "always", "essential" }).join(',')); } } void TestQmlformatCli::settingsKeysStayStable() { QCOMPARE(QQmlFormatSettings::s_useTabsSetting, "UseTabs"_L1); QCOMPARE(QQmlFormatSettings::s_indentWidthSetting, "IndentWidth"_L1); QCOMPARE(QQmlFormatSettings::s_maxColumnWidthSetting, "MaxColumnWidth"_L1); QCOMPARE(QQmlFormatSettings::s_normalizeSetting, "NormalizeOrder"_L1); QCOMPARE(QQmlFormatSettings::s_newlineSetting, "NewlineType"_L1); QCOMPARE(QQmlFormatSettings::s_objectsSpacingSetting, "ObjectsSpacing"_L1); QCOMPARE(QQmlFormatSettings::s_functionsSpacingSetting, "FunctionsSpacing"_L1); QCOMPARE(QQmlFormatSettings::s_groupAttributesTogetherSetting, "GroupAttributesTogether"_L1); QCOMPARE(QQmlFormatSettings::s_sortImportsSetting, "SortImports"_L1); QCOMPARE(QQmlFormatSettings::s_semiColonRuleSetting, "SemicolonRule"_L1); } void TestQmlformatCli::settingsFromFileOrCommandLine_data() { QTest::addColumn("qmlformatIniPath"); QTest::addColumn("qmlformatInitOptions"); QTest::addColumn("expectedOptions"); { QQmlFormatOptions options; options.setIndentWidth(20); // In settings file, indentwidth is set to 4000, while cli overrides it to 20 // 20 should be the final value QTest::newRow("clOverridesIndentWidth") << testFile("iniFiles/dummySettingsFile.ini") << QStringList{ m_qmlformatPath, "--indent-width", "20" } << options; options.setIndentWidth(4000); // In settings file, indentwidth is set to 4000, and nothing overrides it. // 4000 should be the final value QTest::newRow("iniFileIndentWidth") << testFile("iniFiles/dummySettingsFile.ini") << QStringList{ m_qmlformatPath } << options; options.setMaxColumnWidth(100); // In settings file, maxcolumnwidth is set to -1, but cli overrides it 100. // 100 should be the final value QTest::newRow("clOverridesColumnWidth") << testFile("iniFiles/dummySettingsFile.ini") << QStringList{ m_qmlformatPath, "-W", "100" } << options; } { QQmlFormatOptions options; // settings file sets all bools excepts Tabs to true. options.setTabsEnabled(false); options.setNormalizeEnabled(true); options.setObjectsSpacing(true); options.setFunctionsSpacing(true); QTest::newRow("iniFileSetsBools") << testFile("iniFiles/toggledBools.ini") << QStringList{ m_qmlformatPath } << options; // cli overrides the Tabs option to true options.setTabsEnabled(true); QTest::newRow("cliOverridesTabs") << testFile("iniFiles/toggledBools.ini") << QStringList{ m_qmlformatPath, "--tabs" } << options; } { // settings should apply when -F is passed QQmlFormatOptions options; options.setIndentWidth(4000); QTest::newRow("settingOnFilesOption") << testFile("iniFiles/dummySettingsFile.ini") << QStringList{ m_qmlformatPath, "-F", "dummyFilesPath" } << options; } { // In settings file, semicolonRule is set to Essential and cli does not override it. // Essential should be the final value QQmlFormatOptions expectedOptions; expectedOptions.setSemicolonRule(QQmlJS::Dom::LineWriterOptions::SemicolonRule::Essential); QTest::newRow("semiColonRuleFromIniFile") << testFile("iniFiles/semicolonRule.ini") << QStringList{ m_qmlformatPath} << expectedOptions; } } void TestQmlformatCli::settingsFromFileOrCommandLine() { QFETCH(QString, qmlformatIniPath); QFETCH(QStringList, qmlformatInitOptions); QFETCH(QQmlFormatOptions, expectedOptions); auto verify = [&]() { QTemporaryDir tempDir; const QString qmlformatIni = tempDir.path() + QDir::separator() + ".qmlformat.ini"; const QString dummyQmlFile = tempDir.path() + QDir::separator() + "test.qml"; QFile::copy(qmlformatIniPath, qmlformatIni); QQmlFormatSettings settings("qmlformat"); QStringList cmdlineOptions; if ((qstrcmp(QTest::currentDataTag(), "settingOnFilesOption") == 0)) cmdlineOptions = qmlformatInitOptions << "-F" << dummyQmlFile; else cmdlineOptions = QStringList(dummyQmlFile) << qmlformatInitOptions; QQmlFormatOptions options = QQmlFormatOptions::buildCommandLineOptions(cmdlineOptions); auto overridenOptions = options.optionsForFile(dummyQmlFile, &settings); QCOMPARE(overridenOptions.tabsEnabled(), expectedOptions.tabsEnabled()); QCOMPARE(overridenOptions.indentWidth(), expectedOptions.indentWidth()); QCOMPARE(overridenOptions.maxColumnWidth(), expectedOptions.maxColumnWidth()); QCOMPARE(overridenOptions.normalizeEnabled(), expectedOptions.normalizeEnabled()); QCOMPARE(overridenOptions.newline(), expectedOptions.newline()); QCOMPARE(overridenOptions.objectsSpacing(), expectedOptions.objectsSpacing()); QCOMPARE(overridenOptions.functionsSpacing(), expectedOptions.functionsSpacing()); QCOMPARE(overridenOptions.sortImports(), expectedOptions.sortImports()); QCOMPARE(overridenOptions.semicolonRule(), expectedOptions.semicolonRule()); }; verify(); } /* * Create a temporary directory with the following structure |--dir1 | |--.qmlformat.ini | |-- test1.qml |--dir2 | |-- test2.qml * test2.qml should differ from the test2.qml options on indentwidth, because test1 gets it from * its settings file. */ void TestQmlformatCli::multipleSettingsFiles() { QTemporaryDir tempDir; QTemporaryDir dir1(tempDir.path() + "/dir1"); QTemporaryDir dir2(tempDir.path() + "/dir2"); const QString qmlformat1Ini = dir1.path() + "/.qmlformat.ini"; const QString test1Qml = dir1.path() + "/test.qml"; const QString test2Qml = dir2.path() + "/test.qml"; QFile::copy(testFile("iniFiles/dummySettingsFile.ini"), qmlformat1Ini); QQmlFormatSettings settings("qmlformat"); QQmlFormatOptions options = QQmlFormatOptions::buildCommandLineOptions(QStringList{ m_qmlformatPath }); auto test1Options = options.optionsForFile(test1Qml, &settings); auto test2Options = options.optionsForFile(test2Qml, &settings); QCOMPARE(test1Options.tabsEnabled(), test2Options.tabsEnabled()); QCOMPARE_NE(test1Options.indentWidth(), test2Options.indentWidth()); QCOMPARE(test1Options.maxColumnWidth(), test2Options.maxColumnWidth()); QCOMPARE(test1Options.normalizeEnabled(), test2Options.normalizeEnabled()); QCOMPARE(test1Options.newline(), test2Options.newline()); QCOMPARE(test1Options.objectsSpacing(), test2Options.objectsSpacing()); QCOMPARE(test1Options.functionsSpacing(), test2Options.functionsSpacing()); QCOMPARE(test1Options.sortImports(), test2Options.sortImports()); QCOMPARE(test1Options.semicolonRule(), test2Options.semicolonRule()); } QTEST_MAIN(TestQmlformatCli) #include "tst_qmlformat_cli.moc"