Commit 1f6838d for mammothjs

commit 1f6838d2c37acd15331f56b80bdd09ac0aae2405
Author: Michael Williamson <mike@zwobble.org>
Date:   Wed Sep 16 23:59:49 2026 +0100

    Add tests around forEachSeries and ensure it resolves to undefined

diff --git a/lib/promises.js b/lib/promises.js
index f448ca9..f008200 100644
--- a/lib/promises.js
+++ b/lib/promises.js
@@ -2,9 +2,14 @@ var _ = require("underscore");
 var bluebird = require("bluebird/js/release/promise")();

 exports.defer = defer;
+exports.Promise = bluebird.Promise;
 exports.resolve = bluebird.resolve;
 exports.reject = bluebird.reject;
-exports.forEachSeries = bluebird.mapSeries;
+
+exports.forEachSeries = function(array, func) {
+    return bluebird.mapSeries(array, func).then(function() {
+    });
+};

 var props = exports.props = function(obj) {
     // We rely on .keys() and .values() returning properties in the same order.
diff --git a/test/.eslintrc.json b/test/.eslintrc.json
index 4869f03..5bbc8fa 100644
--- a/test/.eslintrc.json
+++ b/test/.eslintrc.json
@@ -2,6 +2,7 @@
   "globals": {
     "__dirname": false,
     "describe": false,
-    "it": false
+    "it": false,
+    "setTimeout": false
   }
 }
diff --git a/test/promises.tests.js b/test/promises.tests.js
index a6e35ac..6497cd3 100644
--- a/test/promises.tests.js
+++ b/test/promises.tests.js
@@ -3,6 +3,100 @@ var assert = require("assert");
 var promises = require("../lib/promises");
 var test = require("./test")(module);

+test("forEachSeries", {
+    "empty array resolves immediately without calling function": function() {
+        return promises.forEachSeries([], function() {
+            throw new Error();
+        }).then(function(result) {
+            assert.deepStrictEqual(result, undefined);
+        });
+    },
+
+    "function is called on element after the previous element has been processed": function() {
+        var log = [];
+
+        return promises.forEachSeries([1, 2, 3], function(element) {
+            return new promises.Promise(function(resolve) {
+                log.push(["start", element]);
+                setTimeout(function() {
+                    log.push(["end", element]);
+                    resolve();
+                }, 0);
+            });
+        }).then(function(result) {
+            assert.deepStrictEqual(result, undefined);
+            assert.deepStrictEqual(log, [
+                ["start", 1],
+                ["end", 1],
+                ["start", 2],
+                ["end", 2],
+                ["start", 3],
+                ["end", 3]
+            ]);
+        });
+    },
+
+    "processing stops on sync error": function() {
+        var log = [];
+
+        return promises.forEachSeries([1, 2, 3], function(element) {
+            return new promises.Promise(function(resolve) {
+                log.push(["start", element]);
+                if (element === 2) {
+                    throw new Error("failure");
+                } else {
+                    setTimeout(function() {
+                        log.push(["end", element]);
+                        resolve();
+                    }, 0);
+                }
+            });
+        }).then(
+            function() {
+                assert.fail("Expected rejection");
+            },
+            function(error) {
+                assert.strictEqual(error.message, "failure");
+                assert.deepStrictEqual(log, [
+                    ["start", 1],
+                    ["end", 1],
+                    ["start", 2]
+                ]);
+            }
+        );
+    },
+
+    "processing stops on async error": function() {
+        var log = [];
+
+        return promises.forEachSeries([1, 2, 3], function(element) {
+            return new promises.Promise(function(resolve, reject) {
+                log.push(["start", element]);
+                setTimeout(function() {
+                    if (element === 2) {
+                        reject(new Error("failure"));
+                    } else {
+                        log.push(["end", element]);
+                        resolve();
+                    }
+                }, 0);
+            });
+        }).then(
+            function() {
+                assert.fail("Expected rejection");
+            },
+            function(error) {
+                assert.strictEqual(error.message, "failure");
+                assert.deepStrictEqual(log, [
+                    ["start", 1],
+                    ["end", 1],
+                    ["start", 2]
+                ]);
+            }
+        );
+    }
+});
+
 test("try", {
     "when function succeeds with non-promise then promise is resolved": function() {
         return promises.try(function() {