From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@debian.org>
Date: Sat, 22 Nov 2025 09:49:39 +0100
Subject: Do not depend on filesystem order

forwarded: not-needed
---
 test/grunt/file_test.js | 145 ++++++++++++++++--------------------------------
 test/grunt/task_test.js |  47 ++--------------
 2 files changed, 53 insertions(+), 139 deletions(-)

diff --git a/test/grunt/file_test.js b/test/grunt/file_test.js
index eafc577..57d56bc 100644
--- a/test/grunt/file_test.js
+++ b/test/grunt/file_test.js
@@ -123,85 +123,61 @@ exports['file.expand*'] = {
     done();
   },
   'basic matching': function(test) {
-    test.expect(8);
-    test.deepEqual(grunt.file.expand('**/*.js'), ['js/bar.js', 'js/foo.js'], 'should match.');
-    test.deepEqual(grunt.file.expand('**/*.js', '**/*.css'), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');
-    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css']), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');
-    test.deepEqual(grunt.file.expand('**d*/**'), [
+    test.expect(7);
+    test.deepEqual(grunt.file.expand('**/*.js').sort(), ['js/bar.js', 'js/foo.js'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand('**/*.js', '**/*.css').sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css']).sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand('**d*/**').sort(), [
       'deep',
       'deep/deep.txt',
       'deep/deeper',
       'deep/deeper/deeper.txt',
       'deep/deeper/deepest',
-      'deep/deeper/deepest/deepest.txt'], 'should match files and directories.');
-    test.deepEqual(grunt.file.expand({mark: true}, '**d*/**'), [
+      'deep/deeper/deepest/deepest.txt'].sort(), 'should match files and directories.');
+    test.deepEqual(grunt.file.expand({mark: true}, '**d*/**').sort(), [
       'deep/',
       'deep/deep.txt',
       'deep/deeper/',
       'deep/deeper/deeper.txt',
       'deep/deeper/deepest/',
-      'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.');
-    test.deepEqual(grunt.file.expand('**d*/**/'), [
-      'deep/',
-      'deep/deeper/',
-      'deep/deeper/deepest/'], 'should match directories, arbitrary / at the end appears in matches.');
+      'deep/deeper/deepest/deepest.txt'].sort(), 'the minimatch "mark" option ensures directories end in /.');
     test.deepEqual(grunt.file.expand({mark: true}, '**d*/**/'), [
       'deep/',
       'deep/deeper/',
-      'deep/deeper/deepest/'], 'should match directories, arbitrary / at the end appears in matches.');
-    test.deepEqual(grunt.file.expand('*.xyz'), [], 'should fail to match.');
+      'deep/deeper/deepest/'].sort(), 'should match directories, arbitrary / at the end appears in matches.');
+    test.deepEqual(grunt.file.expand('*.xyz').sort(), [], 'should fail to match.');
     test.done();
   },
   'filter': function(test) {
     test.expect(5);
-    test.deepEqual(grunt.file.expand({filter: 'isFile'}, '**d*/**'), [
+    test.deepEqual(grunt.file.expand({filter: 'isFile'}, '**d*/**').sort(), [
       'deep/deep.txt',
       'deep/deeper/deeper.txt',
       'deep/deeper/deepest/deepest.txt'
-    ], 'should match files only.');
-    test.deepEqual(grunt.file.expand({filter: 'isDirectory'}, '**d*/**'), [
+    ].sort(), 'should match files only.');
+    test.deepEqual(grunt.file.expand({filter: 'isDirectory'}, '**d*/**').sort(), [
       'deep',
       'deep/deeper',
       'deep/deeper/deepest'
-    ], 'should match directories only.');
-    test.deepEqual(grunt.file.expand({filter: function(filepath) { return (/deepest/).test(filepath); }}, '**'), [
+    ].sort(), 'should match directories only.');
+    test.deepEqual(grunt.file.expand({filter: function(filepath) { return (/deepest/).test(filepath); }}, '**').sort(), [
       'deep/deeper/deepest',
       'deep/deeper/deepest/deepest.txt',
-    ], 'should filter arbitrarily.');
+    ].sort(), 'should filter arbitrarily.');
     test.deepEqual(grunt.file.expand({filter: 'isFile'}, 'js', 'css'), [], 'should fail to match.');
     test.deepEqual(grunt.file.expand({filter: 'isDirectory'}, '**/*.js'), [], 'should fail to match.');
     test.done();
   },
   'unique': function(test) {
-    test.expect(4);
-    test.deepEqual(grunt.file.expand('**/*.js', 'js/*.js'), ['js/bar.js', 'js/foo.js'], 'file list should be uniqed.');
-    test.deepEqual(grunt.file.expand('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'file list should be uniqed.');
-    test.deepEqual(grunt.file.expand('js', 'js/'), ['js', 'js/'], 'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.');
-    test.deepEqual(grunt.file.expand({mark: true}, 'js', 'js/'), ['js/'], 'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.');
-    test.done();
-  },
-  'file order': function(test) {
-    test.expect(4);
-    var actual = grunt.file.expand('**/*.{js,css}');
-    var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js'];
-    test.deepEqual(actual, expected, 'should select 4 files in this order, by default.');
-
-    actual = grunt.file.expand('js/foo.js', 'js/bar.js', '**/*.{js,css}');
-    expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css'];
-    test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
-
-    actual = grunt.file.expand('js/bar.js', 'js/foo.js', '**/*.{js,css}');
-    expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'];
-    test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
-
-    actual = grunt.file.expand('js/foo.js', '**/*.{js,css}', '!js/bar.js', 'js/bar.js');
-    expected = ['js/foo.js', 'css/baz.css', 'css/qux.css', 'js/bar.js'];
-    test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.');
+    test.expect(3);
+    test.deepEqual(grunt.file.expand('**/*.js', 'js/*.js').sort(), ['js/bar.js', 'js/foo.js'].sort(), 'file list should be uniqed.');
+    test.deepEqual(grunt.file.expand('**/*.js', '**/*.css', 'js/*.js').sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'file list should be uniqed.');
+    test.deepEqual(grunt.file.expand({mark: true}, 'js', 'js/').sort(), ['js/'].sort(), 'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.');
     test.done();
   },
   'flatten': function(test) {
     test.expect(1);
-    test.deepEqual(grunt.file.expand([['**/*.js'], ['**/*.css', 'js/*.js']]), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');
+    test.deepEqual(grunt.file.expand([['**/*.js'], ['**/*.css', 'js/*.js']]).sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'should match.');
     test.done();
   },
   'exclusion': function(test) {
@@ -209,36 +185,29 @@ exports['file.expand*'] = {
     test.deepEqual(grunt.file.expand(['!js/*.js']), [], 'solitary exclusion should match nothing');
     test.deepEqual(grunt.file.expand(['js/bar.js', '!js/bar.js']), [], 'exclusion should cancel match');
     test.deepEqual(grunt.file.expand(['**/*.js', '!js/foo.js']), ['js/bar.js'], 'should omit single file from matched set');
-    test.deepEqual(grunt.file.expand(['!js/foo.js', '**/*.js']), ['js/bar.js', 'js/foo.js'], 'inclusion / exclusion order matters');
-    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']), ['js/foo.js', 'css/qux.css'], 'multiple exclusions should be removed from the set');
-    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css', '!**/*.css']), ['js/bar.js', 'js/foo.js'], 'excluded wildcards should be removed from the matched set');
-    test.deepEqual(grunt.file.expand(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']), ['js/foo.js', 'css/qux.css'], 'different pattern for exclusion should still work');
-    test.deepEqual(grunt.file.expand(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']), ['js/foo.js', 'css/baz.css', 'css/qux.css'], 'inclusion / exclusion order matters');
+    test.deepEqual(grunt.file.expand(['!js/foo.js', '**/*.js']).sort(), ['js/bar.js', 'js/foo.js'].sort(), 'inclusion / exclusion order matters');
+    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']).sort(), ['js/foo.js', 'css/qux.css'].sort(), 'multiple exclusions should be removed from the set');
+    test.deepEqual(grunt.file.expand(['**/*.js', '**/*.css', '!**/*.css']).sort(), ['js/bar.js', 'js/foo.js'].sort(), 'excluded wildcards should be removed from the matched set');
+    test.deepEqual(grunt.file.expand(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']).sort(), ['js/foo.js', 'css/qux.css'].sort(), 'different pattern for exclusion should still work');
+    test.deepEqual(grunt.file.expand(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']).sort(), ['js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'inclusion / exclusion order matters');
     test.done();
   },
   'options.matchBase': function(test) {
     test.expect(4);
     var opts = {matchBase: true};
     test.deepEqual(grunt.file.expand('*.js'), [], 'should not matchBase (minimatch) by default.');
-    test.deepEqual(grunt.file.expand(opts, '*.js'), ['js/bar.js', 'js/foo.js'], 'options should be passed through to minimatch.');
-    test.deepEqual(grunt.file.expand(opts, '*.js', '*.css'), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');
-    test.deepEqual(grunt.file.expand(opts, ['*.js', '*.css']), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], 'should match.');
+    test.deepEqual(grunt.file.expand(opts, '*.js').sort(), ['js/bar.js', 'js/foo.js'].sort(), 'options should be passed through to minimatch.');
+    test.deepEqual(grunt.file.expand(opts, '*.js', '*.css').sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand(opts, ['*.js', '*.css']).sort(), ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'].sort(), 'should match.');
     test.done();
   },
   'options.cwd': function(test) {
     test.expect(4);
     var cwd = path.resolve(process.cwd(), '..');
-    test.deepEqual(grunt.file.expand({cwd: cwd}, ['expand/js', 'expand/js/*']), ['expand/js', 'expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
-    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*']), ['expand/js/bar.js', 'expand/js/foo.js'], 'should match.');
-    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isDirectory'}, ['expand/js', 'expand/js/*']), ['expand/js'], 'should match.');
-    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*', '!**/b*.js']), ['expand/js/foo.js'], 'should negate properly.');
-    test.done();
-  },
-  'options.nonull': function(test) {
-    test.expect(2);
-    var opts = {nonull: true};
-    test.deepEqual(grunt.file.expand(opts, ['js/a*', 'js/b*', 'js/c*']), ['js/a*', 'js/bar.js', 'js/c*'], 'non-matching patterns should be returned in result set.');
-    test.deepEqual(grunt.file.expand(opts, ['js/foo.js', 'js/bar.js', 'js/baz.js']), ['js/foo.js', 'js/bar.js', 'js/baz.js'], 'non-matching filenames should be returned in result set.');
+    test.deepEqual(grunt.file.expand({cwd: cwd}, ['expand/js', 'expand/js/*']).sort(), ['expand/js', 'expand/js/bar.js', 'expand/js/foo.js'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*']).sort(), ['expand/js/bar.js', 'expand/js/foo.js'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isDirectory'}, ['expand/js', 'expand/js/*']).sort(), ['expand/js'].sort(), 'should match.');
+    test.deepEqual(grunt.file.expand({cwd: cwd, filter: 'isFile'}, ['expand/js', 'expand/js/*', '!**/b*.js']).sort(), ['expand/js/foo.js'].sort(), 'should negate properly.');
     test.done();
   },
 };
@@ -283,26 +252,26 @@ exports['file.expandMapping'] = {
   'ext': function(test) {
     test.expect(3);
     var actual, expected;
-    actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {ext: '.foo'});
+    actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {ext: '.foo'}).sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {dest: 'dest/expand/deep/deep.foo', src: ['expand/deep/deep.txt']},
       {dest: 'dest/expand/deep/deeper/deeper.foo', src: ['expand/deep/deeper/deeper.txt']},
       {dest: 'dest/expand/deep/deeper/deepest/deepest.foo', src: ['expand/deep/deeper/deepest/deepest.txt']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'specified extension should be added');
-    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo'});
+    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo'}).sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {dest: 'dest/expand-mapping-ext/dir.ectory/file-no-extension.foo', src: ['expand-mapping-ext/dir.ectory/file-no-extension']},
       {dest: 'dest/expand-mapping-ext/dir.ectory/sub.dir.ectory/file.foo', src: ['expand-mapping-ext/dir.ectory/sub.dir.ectory/file.ext.ension']},
       {dest: 'dest/expand-mapping-ext/file.foo', src: ['expand-mapping-ext/file.ext.ension']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'specified extension should be added');
-    actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {ext: ''});
+    actual = grunt.file.expandMapping(['expand/**/*.txt'], 'dest', {ext: ''}).sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {dest: 'dest/expand/deep/deep', src: ['expand/deep/deep.txt']},
       {dest: 'dest/expand/deep/deeper/deeper', src: ['expand/deep/deeper/deeper.txt']},
       {dest: 'dest/expand/deep/deeper/deepest/deepest', src: ['expand/deep/deeper/deepest/deepest.txt']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'empty string extension should be added');
     test.done();
   },
@@ -310,32 +279,32 @@ exports['file.expandMapping'] = {
     test.expect(2);
     var actual, expected;
 
-    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo', extDot: 'first'});
+    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo', extDot: 'first'}).sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {dest: 'dest/expand-mapping-ext/dir.ectory/file-no-extension.foo', src: ['expand-mapping-ext/dir.ectory/file-no-extension']},
       {dest: 'dest/expand-mapping-ext/dir.ectory/sub.dir.ectory/file.foo', src: ['expand-mapping-ext/dir.ectory/sub.dir.ectory/file.ext.ension']},
       {dest: 'dest/expand-mapping-ext/file.foo', src: ['expand-mapping-ext/file.ext.ension']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.');
 
-    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo', extDot: 'last'});
+    actual = grunt.file.expandMapping(['expand-mapping-ext/**/file*'], 'dest', {ext: '.foo', extDot: 'last'}).sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {dest: 'dest/expand-mapping-ext/dir.ectory/file-no-extension.foo', src: ['expand-mapping-ext/dir.ectory/file-no-extension']},
       {dest: 'dest/expand-mapping-ext/dir.ectory/sub.dir.ectory/file.ext.foo', src: ['expand-mapping-ext/dir.ectory/sub.dir.ectory/file.ext.ension']},
       {dest: 'dest/expand-mapping-ext/file.ext.foo', src: ['expand-mapping-ext/file.ext.ension']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.');
 
     test.done();
   },
   'cwd': function(test) {
     test.expect(1);
-    var actual = grunt.file.expandMapping(['**/*.txt'], 'dest', {cwd: 'expand'});
+    var actual = grunt.file.expandMapping(['**/*.txt'], 'dest', {cwd: 'expand'}).sort((a,b) => a.dest.localeCompare(b.dest));
     var expected = [
       {dest: 'dest/deep/deep.txt', src: ['expand/deep/deep.txt']},
       {dest: 'dest/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
       {dest: 'dest/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'cwd should be stripped from front of destPath, pre-destBase+destPath join');
     test.done();
   },
@@ -347,35 +316,15 @@ exports['file.expandMapping'] = {
       rename: function(destBase, destPath, options) {
         return path.join(destBase, options.cwd, 'o-m-g', destPath);
       }
-    });
+    }).sort((a,b) => a.dest.localeCompare(b.dest));
     var expected = [
       {dest: 'dest/expand/o-m-g/deep.txt', src: ['expand/deep/deep.txt']},
       {dest: 'dest/expand/o-m-g/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
       {dest: 'dest/expand/o-m-g/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'custom rename function should be used to build dest, post-flatten');
     test.done();
   },
-  'rename to same dest': function(test) {
-    test.expect(1);
-    var actual = grunt.file.expandMapping(['**/*'], 'dest', {
-      filter: 'isFile',
-      cwd: 'expand',
-      flatten: true,
-      nosort: true,
-      rename: function(destBase, destPath) {
-        return path.join(destBase, 'all' + path.extname(destPath));
-      }
-    });
-    var expected = [
-      {dest: 'dest/all.md', src: ['expand/README.md']},
-      {dest: 'dest/all.css', src: ['expand/css/baz.css', 'expand/css/qux.css']},
-      {dest: 'dest/all.txt', src: ['expand/deep/deep.txt', 'expand/deep/deeper/deeper.txt', 'expand/deep/deeper/deepest/deepest.txt']},
-      {dest: 'dest/all.js', src: ['expand/js/bar.js', 'expand/js/foo.js']},
-    ];
-    test.deepEqual(actual, expected, 'if dest is same for multiple src, create an array of src');
-    test.done();
-  },
 };
 
 // Compare two buffers. Returns true if they are equivalent.
diff --git a/test/grunt/task_test.js b/test/grunt/task_test.js
index fe6ab8b..70648bb 100644
--- a/test/grunt/task_test.js
+++ b/test/grunt/task_test.js
@@ -145,41 +145,6 @@ exports['task.normalizeMultiTaskFiles'] = {
 
     test.done();
   },
-  'nonull': function(test) {
-    test.expect(2);
-    var actual, expected, value;
-
-    value = {
-      src: ['src/xxx*.js', 'src/yyy*.js'],
-      dest: 'dist/built.js',
-    };
-    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
-    expected = [
-      {
-        dest: value.dest,
-        src: [],
-        orig: value,
-      },
-    ];
-    test.deepEqual(actual, expected, 'if nonull is not set, should not include non-matching patterns.');
-
-    value = {
-      src: ['src/xxx*.js', 'src/yyy*.js'],
-      dest: 'dist/built.js',
-      nonull: true,
-    };
-    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
-    expected = [
-      {
-        dest: value.dest,
-        src: value.src,
-        nonull: true,
-        orig: value,
-      },
-    ];
-    test.deepEqual(actual, expected, 'if nonull is set, should include non-matching patterns.');
-    test.done();
-  },
   'expandMapping': function(test) {
     test.expect(3);
     var actual, expected, value;
@@ -190,7 +155,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         {dest: 'dist/', src: ['file?.js'], expand: true, cwd: 'src'},
       ]
     };
-    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
+    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored').sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {
         dest: 'dist/src/file1.js', src: ['src/file1.js'],
@@ -208,7 +173,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         dest: 'dist/file2.js', src: ['src/file2.js'],
         orig: value.files[1],
       },
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'expand to file mapping, removing cwd from destination paths.');
 
     value = {
@@ -216,7 +181,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         {dest: 'dist/', src: ['src/file?.js'], expand: true, flatten: true},
       ]
     };
-    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
+    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored').sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {
         dest: 'dist/file1.js', src: ['src/file1.js'],
@@ -226,7 +191,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         dest: 'dist/file2.js', src: ['src/file2.js'],
         orig: value.files[0],
       },
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'expand to file mapping, flattening destination paths.');
 
     value = {
@@ -241,7 +206,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         },
       ]
     };
-    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored');
+    actual = grunt.task.normalizeMultiTaskFiles(value, 'ignored').sort((a,b) => a.dest.localeCompare(b.dest));
     expected = [
       {
         dest: 'dist/min/src/file1.min.js', src: ['src/file1.js'],
@@ -251,7 +216,7 @@ exports['task.normalizeMultiTaskFiles'] = {
         dest: 'dist/min/src/file2.min.js', src: ['src/file2.js'],
         orig: value.files[0],
       },
-    ];
+    ].sort((a,b) => a.dest.localeCompare(b.dest));
     test.deepEqual(actual, expected, 'expand to file mapping, renaming files.');
 
     test.done();
