'use strict';

const hasObjectFreeze = (() => {
  const a = {};

  try{
    Object.freeze(a);
  } catch(e) {
    return false;
  }

  try {
    a.test = 1;
    return false;
  } catch(ignore) {}

  return true;
})();

const hasProxies = (() => {
  try {
    new Proxy({}, {});

    return true;
  } catch (ignore) {}

  return false;
})();

const buildUtils = (options) => Object.freeze({
  skipIfNoProxies: hasProxies ? it : it.skip,
  skipDescribeIfNoProxies: hasProxies ? describe : describe.skip,
  skipIfNoObjectFreeze: hasObjectFreeze ? it : it.skip,
  objToArr: obj => Object.keys(obj).map(k => [k, obj[k]])
});

import Modelico from './types/Modelico';
import ModelicoAsIs from './types/AsIs';
import ModelicoMap from './types/Map';
import ModelicoEnumMap from './types/EnumMap';
import ModelicoList from './types/List';
import ModelicoSet from './types/Set';

import setPath from './types/setPath';

import featuresSimple from './features/simple';
import featuresAdvanced from './features/advanced';
import featuresAdvancedES5 from './features/advanced.es5';
import featuresDeepNesting from './features/deepNesting';
import Immutable from './Immutable.js/index';
import ImmutableProxied from './Immutable.js/proxied';

import proxyMap from './proxies/proxyMap';
import proxyList from './proxies/proxyList';
import proxySet from './proxies/proxySet';
import proxyDate from './proxies/proxyDate';

import cases from './cases/index';

export default (options, should, M) => _ => {
  const U = buildUtils(options);
  const deps = [should, M];
  const utilsAndDeps = [U].concat(deps);

  describe('Base', Modelico.apply(_, deps));
  describe('AsIs', ModelicoAsIs.apply(_, utilsAndDeps));
  describe('Map', ModelicoMap.apply(_, deps));
  describe('EnumMap', ModelicoEnumMap.apply(_, deps));
  describe('ModelicoList', ModelicoList.apply(_, deps));
  describe('ModelicoSet', ModelicoSet.apply(_, deps));

  describe('setPath', setPath.apply(_, deps));

  describe('Readme simple features', featuresSimple.apply(_, deps));
  describe('Readme advanced features', featuresAdvanced.apply(_, deps));
  describe('Readme advanced features ES5', featuresAdvancedES5.apply(_, deps));
  describe('Deep nesting features', featuresDeepNesting.apply(_, deps));
  describe('Immutable.js examples', Immutable.apply(_, utilsAndDeps));

  U.skipDescribeIfNoProxies(
    'Immutable.js examples (proxied)',
    ImmutableProxied.apply(_, utilsAndDeps)
  );

  U.skipDescribeIfNoProxies('Proxies', () => {
    describe('Map', proxyMap.apply(_, deps));
    describe('List', proxyList.apply(_, deps));
    describe('Set', proxySet.apply(_, deps));
    describe('Date', proxyDate.apply(_, deps));
  });

  describe('Cases', cases.apply(_, deps));
};

@@ -1473,17 +1473,18 @@
 , M) =%3E 
-_
+()
  =%3E %7B%0A  
@@ -1611,26 +1611,20 @@
 Modelico
-.apply(_, 
+(...
 deps));%0A
@@ -1654,26 +1654,20 @@
 licoAsIs
-.apply(_, 
+(...
 utilsAnd
@@ -1703,26 +1703,20 @@
 elicoMap
-.apply(_, 
+(...
 deps));%0A
@@ -1752,26 +1752,20 @@
 oEnumMap
-.apply(_, 
+(...
 deps));%0A
@@ -1799,34 +1799,28 @@
 ModelicoList
-.apply(_, 
+(...
 deps));%0A  de
@@ -1852,26 +1852,20 @@
 elicoSet
-.apply(_, 
+(...
 deps));%0A
@@ -1894,26 +1894,20 @@
  setPath
-.apply(_, 
+(...
 deps));%0A
@@ -1958,26 +1958,20 @@
 esSimple
-.apply(_, 
+(...
 deps));%0A
@@ -2025,26 +2025,20 @@
 Advanced
-.apply(_, 
+(...
 deps));%0A
@@ -2099,26 +2099,20 @@
 ancedES5
-.apply(_, 
+(...
 deps));%0A
@@ -2166,26 +2166,20 @@
 pNesting
-.apply(_, 
+(...
 deps));%0A
@@ -2223,26 +2223,20 @@
 mmutable
-.apply(_, 
+(...
 utilsAnd
@@ -2332,26 +2332,20 @@
 eProxied
-.apply(_, 
+(...
 utilsAnd
@@ -2431,26 +2431,20 @@
 proxyMap
-.apply(_, 
+(...
 deps));%0A
@@ -2473,26 +2473,20 @@
 roxyList
-.apply(_, 
+(...
 deps));%0A
@@ -2513,26 +2513,20 @@
 proxySet
-.apply(_, 
+(...
 deps));%0A
@@ -2555,26 +2555,20 @@
 roxyDate
-.apply(_, 
+(...
 deps));%0A
@@ -2603,18 +2603,12 @@
 ases
-.apply(_, 
+(...
 deps

use spread operator instead of apply (#58)