简体   繁体   中英

array.sort behaving strangely with wallaby.js

I have a function that constructs an array like, [{index: 1}, {index: 4}, {index: 7}] . The array is ordered by the objects' index value. I have narrowed the scope of the function to just a sorting of an array and wallaby indicates the order of the array is incorrect, however mocha continues to indicate passing tests.

The spec is:

import expect from 'expect';
import sort from './sort';

describe("Given an array", ()=> {
    let array;
    beforeEach(() => {
        array = [
            { index: 7, owner: 1 },
            { index: 2, owner: 1 },
            { index: 3, owner: 1 },
            { index: 5, owner: 1 },
            { index: 1, owner: 1 }
        ];
    });

    describe("When sorting the array of elements by id", () => {

        let actual;
        beforeEach(() => {
            actual = sort(array);
        });

        it('should order the array of objects by ascending id',()=> {
            let expected = [
                { index: 1, owner: 1 },
                { index: 2, owner: 1 },
                { index: 3, owner: 1 },
                { index: 5, owner: 1 },
                { index: 7, owner: 1 }
            ];

            expect(actual).toEqual(expected);
        });
    });
});

The implementation of sort.js is:

export default function(array){
   return array.sort((x, y) => { return x.index > y.index});
}

My wallaby config looks like:

process.env.NODE_ENV = 'test';

var wallabyWebpack = require('wallaby-webpack');
var packageConfig = require('./package.json');

module.exports = function(wallaby) {

  var specFilePattern = 'src/shared/**/*.spec.js';
  var srcFilePattern = 'src/shared/**/*.js*';

  var babelProcessor = wallaby.compilers.babel(packageConfig['babel']);

  var webpackPostProcessor = wallabyWebpack({
    resolve: {
          extensions: ['', '.js', '.jsx']
      }
  });

  return {
    testFramework: 'mocha',
    debug: true,
    files: [
      { pattern: 'node_modules/babel-polyfill/dist/polyfill.js', instrument: false },
      { pattern: srcFilePattern, load: false },
      { pattern: specFilePattern, ignore: true }
    ],
    tests: [
      { pattern: specFilePattern, load: false }
    ],
    compilers: {
      '**/*.js*': babelProcessor
    },
    postprocessor: webpackPostProcessor,
    bootstrap: function(){
      window.__moduleBundler.loadTests();
    }
  };
};

Wallaby.js is using PhantomJs behind the scenes by default, which uses the same JavaScript engine that Safari does. And if you run this snippet in Safari Dev Tools :

屏幕截图 2016-03-22 at 12 42 21 pm

you'll notice that it also doesn't sort the array as expected. Chrome Dev Tools will show you a different result:

屏幕截图 2016-03-22 at 12 42 43 pm

So if you'd like your sort implementation to work on all platforms , you need to change it to be compliant with the spec and return 1 , -1 or 0 , as opposed to just true or false .

So if you rewrite your sort function this way:

export default function (array) {
  return array.sort((x, y) => {
    if (x.index > y.index) {
      return 1;
    }
    if (x.index < y.index) {
      return -1;
    }

    return 0;
  });

then it will work everywhere. If you'd prefer a shorter (but a bit less readable) way, you may use this one:

export default function(array) {
  return array.sort((x, y) => +(x.index > y.index) || +(x.index === y.index) - 1);
}

If for some reason you would only like to support platforms where your original code works and wouldn't like to change it, then I suggest switching the default PhantomJs runner to the Electron runner that wallaby also supports. It uses V8 and your original code works fine with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM