diff --git a/testfiles/helpers.js b/testfiles/helpers.js new file mode 100644 index 0000000..999f659 --- /dev/null +++ b/testfiles/helpers.js @@ -0,0 +1,22 @@ +export function isString(value) { + return typeof(value) === "string" || value instanceof String; +} + +export function isTruthy(value) { + return value && value !== "false" && value !== "0"; +} + +export function logTagInfo(file, tag) { + // log tag type and supported fields + const fields = tag.fields; + utility.diag("debug", tag.type, "tag"); + utility.diag("debug", Object.keys(fields).sort().join(", "), "supported fields"); + + // log fields for debugging purposes + for (const [key, value] of Object.entries(fields)) { + const content = value.content; + if (content !== undefined && content != null && !(content instanceof ArrayBuffer)) { + utility.diag("debug", content, key + " (" + value.type + ")"); + } + } +} diff --git a/testfiles/script-processing-test.js b/testfiles/script-processing-test.js new file mode 100644 index 0000000..fe286d7 --- /dev/null +++ b/testfiles/script-processing-test.js @@ -0,0 +1,24 @@ +import * as helpers from "helpers.js" + +export function main(file) { + utility.diag("debug", Object.keys(settings).join(", "), "settings"); + for (const tag of file.tags) { + changeTagFields(file, tag); + } + file.applyChanges(); + return !helpers.isTruthy(settings.dryRun); +} + +function addTestFields(file, tag) { + const fields = tag.fields; + for (const [key, value] of Object.entries(settings)) { + if (key.startsWith("set:")) { + fields[key.substr(4)] = value; + } + } +} + +function changeTagFields(file, tag) { + helpers.logTagInfo(file, tag); + addTestFields(file, tag); +} diff --git a/testfiles/set-tags.js b/testfiles/set-tags.js index 410474a..25f87e0 100644 --- a/testfiles/set-tags.js +++ b/testfiles/set-tags.js @@ -1,3 +1,4 @@ +import * as helpers from "helpers.js" import * as metadatasearch from "metadatasearch.js" export function main(file) { @@ -10,45 +11,22 @@ export function main(file) { file.applyChanges(); // return a falsy value to skip the file after all - return !isTruthy(settings.dryRun); + return !helpers.isTruthy(settings.dryRun); } const mainTextFields = ["title", "artist", "album", "genre"]; const personalFields = ["comment", "rating"]; -function isString(value) { - return typeof(value) === "string" || value instanceof String; -} - -function isTruthy(value) { - return value && value !== "false" && value !== "0"; -} - -function logTagInfo(file, tag) { - // log tag type and supported fields - const fields = tag.fields; - utility.diag("debug", tag.type, "tag"); - utility.diag("debug", Object.keys(fields).join(", "), "supported fields"); - - // log fields for debugging purposes - for (const [key, value] of Object.entries(fields)) { - const content = value.content; - if (content !== undefined && content != null && !(content instanceof ArrayBuffer)) { - utility.diag("debug", content, key + " (" + value.type + ")"); - } - } -} - function applyFixesToMainFields(file, tag) { const fields = tag.fields; for (const key of mainTextFields) { for (const value of fields[key]) { - if (isString(value.content)) { + if (helpers.isString(value.content)) { value.content = value.content.trim(); - if (isTruthy(settings.fixUmlauts)) { + if (helpers.isTruthy(settings.fixUmlauts)) { value.content = utility.fixUmlauts(value.content); } - if (isTruthy(settings.formatNames)) { + if (helpers.isTruthy(settings.formatNames)) { value.content = utility.formatName(value.content); } } @@ -118,17 +96,17 @@ function addMiscFields(file, tag) { } function changeTagFields(file, tag) { - logTagInfo(file, tag); + helpers.logTagInfo(file, tag); // change/add various fields; these values can still be overridden by specifying fields normally as CLI args applyFixesToMainFields(file, tag); clearPersonalFields(file, tag); addTotalNumberOfTracks(file, tag); addMiscFields(file, tag); - if (isTruthy(settings.addLyrics)) { + if (helpers.isTruthy(settings.addLyrics)) { addLyrics(file, tag); } - if (isTruthy(settings.addCover)) { + if (helpers.isTruthy(settings.addCover)) { addCover(file, tag); } } diff --git a/tests/cli.cpp b/tests/cli.cpp index 7476141..c1a731b 100644 --- a/tests/cli.cpp +++ b/tests/cli.cpp @@ -77,6 +77,7 @@ class CliTests : public TestFixture { CPPUNIT_TEST(testReadingAndWritingDocumentTitle); CPPUNIT_TEST(testFileLayoutOptions); CPPUNIT_TEST(testJsonExport); + CPPUNIT_TEST(testScriptProcessing); #endif CPPUNIT_TEST_SUITE_END(); @@ -103,6 +104,7 @@ public: void testReadingAndWritingDocumentTitle(); void testFileLayoutOptions(); void testJsonExport(); + void testScriptProcessing(); #endif private: @@ -1176,4 +1178,51 @@ void CliTests::testJsonExport() #endif // TAGEDITOR_JSON_EXPORT } -#endif // PLATFORM_UNIX +/*! + * \brief Tests the --script parameter of the set operation. + */ +void CliTests::testScriptProcessing() +{ +#ifndef TAGEDITOR_USE_JSENGINE + std::cout << "\nSkipping script processing (feature not enabled)" << std::endl; +#else + std::cout << "\nScript processing" << endl; + auto stdout = std::string(), stderr = std::string(); + + const auto file = workingCopyPath("mtx-test-data/alac/othertest-itunes.m4a"); + const auto script = testFilePath("script-processing-test.js"); + const char *args[] = { "tageditor", "set", "--pedantic", "debug", "--script", script.data(), "--script-settings", "set:title=foo", "set:artist=bar", + "dryRun=false", "-f", file.data(), nullptr }; + TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, EXIT_PARSING_FAILURE); + CPPUNIT_ASSERT(testContainsSubstrings(stderr, { "executing JavaScript for othertest-itunes.m4a: entering main() function", + "settings: set:title, set:artist, dryRun", + "tag: MP4/iTunes tag", + "supported fields: album, albumArtist, arranger, ", "soundEngineer, title, track", + "MP4/iTunes tag: applying changes", + " - change title[0] from 'Sad Song' to 'foo'", + " - change artist[0] from 'Oasis' to 'bar'", + "executing JavaScript for othertest-itunes.m4a: done with return value: true", + "Changes are about to be applied" + })); + CPPUNIT_ASSERT(testContainsSubstrings(stdout, { "Loading JavaScript file", script.data(), + "Setting tag information for", file.data(), + "Changes have been applied." + })); + + args[9] = "dryRun=true"; + TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, EXIT_PARSING_FAILURE); + CPPUNIT_ASSERT(testContainsSubstrings(stderr, { "executing JavaScript for othertest-itunes.m4a: entering main() function", + "MP4/iTunes tag: applying changes", + " - set title[0] to 'foo' (no change)", + " - set artist[0] to 'bar' (no change)", + "executing JavaScript for othertest-itunes.m4a: done with return value: false" + })); + CPPUNIT_ASSERT_EQUAL(std::string::npos, stderr.find("Changes are about to be applied")); + CPPUNIT_ASSERT(testContainsSubstrings(stdout, { "Loading JavaScript file", script.data(), + "Setting tag information for", file.data(), + " - Skipping file because JavaScript returned a falsy value other than undefined." + })); +#endif +} + +#endif // defined(PLATFORM_UNIX) || defined(CPP_UTILITIES_HAS_EXEC_APP)