diff --git a/scripts/shop.cm b/scripts/shop.cm index 724bdbf1..745ff2c8 100644 --- a/scripts/shop.cm +++ b/scripts/shop.cm @@ -1379,5 +1379,20 @@ Shop.resolve_module = function(module_name, package_name, is_file_fn) { return null } + +Shop.resolve_alias = function(name, ctx) { + var deps = Shop.dependencies(ctx) + if (deps && deps[name]) return { alias: name, pkg: Shop.get_canonical_package(name, ctx) } + + for (var alias in deps) { + var pkg = deps[alias] + var parsed = Shop.parse_package(pkg) + if (parsed && (parsed.name == name || parsed.path == name)) { + return { alias: alias, pkg: parsed.path } + } + } + return null +} + Shop.get_canonical_package = get_canonical_package return Shop \ No newline at end of file diff --git a/scripts/test.ce b/scripts/test.ce new file mode 100644 index 00000000..5792a7a2 --- /dev/null +++ b/scripts/test.ce @@ -0,0 +1,136 @@ +var shop = use('shop') +var fd = use('fd') + +if (!args) args = [] + +var target_pkg = null // null = current, otherwise canonical path +var all_pkgs = false + +if (args.length > 0) { + if (args[0] == 'package') { + if (args.length < 2) { + log.console("Usage: cell test package ") + $_.stop() + return + } + var name = args[1] + var resolved = shop.resolve_alias(name, null) + if (resolved) { + target_pkg = resolved.pkg + log.console("Testing package: " + resolved.alias + " (" + resolved.pkg + ")") + } else { + log.console("Package not found: " + name) + $_.stop() + return + } + } else if (args[0] == 'all') { + all_pkgs = true + log.console("Testing all packages...") + } else { + log.console("Usage: cell test [package | all]") + $_.stop() + return + } +} + +function run_tests(pkg) { + var prefix = pkg ? ".cell/modules/" + pkg : "." + var tests_dir = prefix + "/tests" + + if (!fd.is_dir(tests_dir)) return { total: 0, passed: 0, failed: 0 } + + var files = shop.list_files(pkg) + var test_files = [] + for (var i = 0; i < files.length; i++) { + var f = files[i] + // Check if file is in tests/ folder and is a .cm module + if (f.startsWith("tests/") && f.endsWith(".cm")) { + test_files.push(f) + } + } + + var total = 0 + var passed = 0 + var failed = 0 + + if (test_files.length > 0) { + if (pkg) log.console("Running tests for " + pkg) + else log.console("Running tests for local package") + } + + for (var i = 0; i < test_files.length; i++) { + var f = test_files[i] + var mod_path = f.substring(0, f.length - 3) // remove .cm + + try { + var test_mod + if (pkg) { + test_mod = shop.use(mod_path, pkg) + } else { + test_mod = globalThis.use(mod_path) + } + + var tests = [] + if (typeof test_mod == 'function') { + tests.push({name: 'main', fn: test_mod}) + } else if (typeof test_mod == 'object') { + for (var k in test_mod) { + if (typeof test_mod[k] == 'function') { + tests.push({name: k, fn: test_mod[k]}) + } + } + } + + if (tests.length > 0) { + log.console(" " + f) + for (var j = 0; j < tests.length; j++) { + var t = tests[j] + try { + t.fn() + log.console(` PASS ${t.name}`) + passed++ + } catch (e) { + log.console(` FAIL ${t.name} ${e}`) + failed++ + } + total++ + } + } + + } catch (e) { + log.console(" Error loading " + f + ": " + e) + failed++ + total++ + } + } + return { total: total, passed: passed, failed: failed } +} + +var totals = { total: 0, passed: 0, failed: 0 } + +if (all_pkgs) { + // Run local first + var local_res = run_tests(null) + totals.total += local_res.total + totals.passed += local_res.passed + totals.failed += local_res.failed + + // Then all dependencies + var deps = shop.list_packages(null) + for (var i = 0; i < deps.length; i++) { + var res = run_tests(deps[i]) + totals.total += res.total + totals.passed += res.passed + totals.failed += res.failed + } +} else { + var res = run_tests(target_pkg) + totals.total += res.total + totals.passed += res.passed + totals.failed += res.failed +} + +log.console("----------------------------------------") +log.console("Tests: " + text(totals.passed) + " passed, " + text(totals.failed) + " failed, " + text(totals.total) + " total") + +$_.stop()