<commit_before>angular.module('admin.troupe.services', ['ngResource', 'services.csrfResource']).
factory('TroupeRepository', ['$resource', 'csrfResource', function($resource, csrfResource) {
	return {
		url: '/admin/troupes',
		getTroupes: function() {
			return $resource(this.url, {}).query();
		},
		addTroupe: function(troupeToPost, csrfHeader, csrfToken) {
			return csrfResource.post(this.url, troupeToPost, csrfHeader, csrfToken);
		},
		deleteTroupe: function(id, csrfHeader, csrfToken) {
			return csrfResource.delete(this.url + '/' + id, csrfHeader, csrfToken);
		}
	};
}]);

angular.module('admin.troupe.controllers', ['admin.troupe.services']).
controller('deleteTroupe', ['$scope', '$rootScope', 'TroupeRepository', function($scope, $rootScope, TroupeRepository) {
	$scope.deleteTroupe = function(id, csrfHeader, csrfToken) {
		TroupeRepository.deleteTroupe(id, csrfHeader, csrfToken).
			success(function(data, status, headers, config) {$rootScope.$broadcast('troupesUpdated')}).
			error(function(data, status, headers, config) {console.log("deleteTroupe failed")});
	};
}]).
controller('addTroupe', ['$scope', '$rootScope', 'TroupeRepository', function($scope, $rootScope, TroupeRepository) {
	$scope.settings = [
	             	  {label: 'Camarilla', value: 0},
	             	  {label: 'Anarch', value: 1},
	             	  {label: 'Sabbat', value: 2}
	             	  ];
 	$scope.setting = $scope.settings[0];
	$scope.submit = function(csrfHeader, csrfToken) {
		TroupeRepository.addTroupe({'name': $scope.name, 'setting': $scope.setting.value}, csrfHeader, csrfToken).
			success(function(data, status, headers, config) {$rootScope.$broadcast('troupesUpdated')}).
			error(function(data, status, headers, config) {console.log("addTroupe failed")});
	};
}]);

angular.module('admin.troupe.directives', ['admin.troupe.services']).
directive('listTroupes', ['TroupeRepository', function(TroupeRepository) {
	return {
		restrict: 'E',
		scope: {
			csrf: '='
		},
		link: function(scope, iElement, iAttrs) {
			scope.troupes = TroupeRepository.getTroupes();
			scope.$on('troupesUpdated', function(event) {
				scope.troupes = TroupeRepository.getTroupes();
			});
		},
		templateUrl: '/js/admin/troupes/display.html'
	};
}]).
directive('addTroupe', [function() {
	return {
		restrict: 'E',
		scope: {
			csrf: '='
		},
		templateUrl: '/js/admin/troupes/add.html'
	};
}]);

angular.module('admin.troupe.filters', ['filters.setting']);

angular.module('admin.troupe', ['admin.troupe.filters', 'admin.troupe.controllers', 'admin.troupe.directives', 'admin.troupe.services']);<commit_msg>Changed the Troupe dropdown populator to use a setting source.  Realized I don't need the whole BiDirectionalMap thing, and should be able to just use a simple array for both purposes.<commit_after>angular.module('admin.troupe.services', ['ngResource', 'services.csrfResource']).
factory('TroupeRepository', ['$resource', 'csrfResource', function($resource, csrfResource) {
	return {
		url: '/admin/troupes',
		getTroupes: function() {
			return $resource(this.url, {}).query();
		},
		addTroupe: function(troupeToPost, csrfHeader, csrfToken) {
			return csrfResource.post(this.url, troupeToPost, csrfHeader, csrfToken);
		},
		deleteTroupe: function(id, csrfHeader, csrfToken) {
			return csrfResource.delete(this.url + '/' + id, csrfHeader, csrfToken);
		}
	};
}]);

angular.module('admin.troupe.controllers', ['admin.troupe.services', 'sources.settings']).
controller('deleteTroupe', ['$scope', '$rootScope', 'TroupeRepository', function($scope, $rootScope, TroupeRepository) {
	$scope.deleteTroupe = function(id, csrfHeader, csrfToken) {
		TroupeRepository.deleteTroupe(id, csrfHeader, csrfToken).
			success(function(data, status, headers, config) {$rootScope.$broadcast('troupesUpdated')}).
			error(function(data, status, headers, config) {console.log("deleteTroupe failed")});
	};
}]).
controller('addTroupe', ['$scope', '$rootScope', 'TroupeRepository', 'settingsSource', function($scope, $rootScope, TroupeRepository, settingsSource) {
	$scope.settings = [];
	for(var key in settingsSource.get().keysToValues) {
		$scope.settings[key] = {label: settingsSource.get().valueFor(key), value: key};
	}
 	$scope.setting = $scope.settings[0];
	$scope.submit = function(csrfHeader, csrfToken) {
		TroupeRepository.addTroupe({'name': $scope.name, 'setting': $scope.setting.value}, csrfHeader, csrfToken).
			success(function(data, status, headers, config) {$rootScope.$broadcast('troupesUpdated')}).
			error(function(data, status, headers, config) {console.log("addTroupe failed")});
	};
}]);

angular.module('admin.troupe.directives', ['admin.troupe.services']).
directive('listTroupes', ['TroupeRepository', function(TroupeRepository) {
	return {
		restrict: 'E',
		scope: {
			csrf: '='
		},
		link: function(scope, iElement, iAttrs) {
			scope.troupes = TroupeRepository.getTroupes();
			scope.$on('troupesUpdated', function(event) {
				scope.troupes = TroupeRepository.getTroupes();
			});
		},
		templateUrl: '/js/admin/troupes/display.html'
	};
}]).
directive('addTroupe', [function() {
	return {
		restrict: 'E',
		scope: {
			csrf: '='
		},
		templateUrl: '/js/admin/troupes/add.html'
	};
}]);

angular.module('admin.troupe.filters', ['filters.setting']);

angular.module('admin.troupe', ['admin.troupe.filters', 'admin.troupe.controllers', 'admin.troupe.directives', 'admin.troupe.services']);<|endoftext|>


<commit_before>// This is heavily based on https://github.com/sindresorhus/electron-context-menu
// ❤ @sindresorhus

import { clipboard, remote, ipcRenderer, shell } from 'electron';

import { isDevMode, isMac } from '../environment';

const debug = require('debug')('Franz:contextMenu');

const { Menu } = remote;

// const win = remote.getCurrentWindow();
const webContents = remote.getCurrentWebContents();

function delUnusedElements(menuTpl) {
  let notDeletedPrevEl;
  return menuTpl.filter(el => el.visible !== false).filter((el, i, array) => {
    const toDelete = el.type === 'separator' && (!notDeletedPrevEl || i === array.length - 1 || array[i + 1].type === 'separator');
    notDeletedPrevEl = toDelete ? notDeletedPrevEl : el;
    return !toDelete;
  });
}

const buildMenuTpl = (props, suggestions) => {
  const { editFlags } = props;
  const textSelection = props.selectionText.trim();
  const hasText = textSelection.length > 0;
  const can = type => editFlags[`can${type}`] && hasText;

  let menuTpl = [
    {
      type: 'separator',
    }, {
      id: 'lookup',
      label: `Look Up "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`,
      visible: isMac && props.mediaType === 'none' && hasText,
      click() {
        debug('Show definition for selection', textSelection);
        webContents.showDefinitionForSelection();
      },
    }, {
      type: 'separator',
    }, {
      id: 'cut',
      role: can('Cut') ? 'cut' : '',
      enabled: can('Cut'),
      visible: hasText && props.isEditable,
    }, {
      id: 'copy',
      label: 'Copy',
      role: can('Copy') ? 'copy' : '',
      enabled: can('Copy'),
      visible: props.isEditable || hasText,
    }, {
      id: 'paste',
      label: 'Paste',
      role: editFlags.canPaste ? 'paste' : '',
      enabled: editFlags.canPaste,
      visible: props.isEditable,
    }, {
      type: 'separator',
      visible: props.isEditable && hasText,
    }, {
      id: 'searchTextSelection',
      label: `Search Google for "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`,
      visible: hasText,
      click() {
        const url = `https://www.google.com/search?q=${textSelection}`;
        debug('Search on Google', url);
        shell.openExternal(url);
      },
    }, {
      type: 'separator',
    },
  ];

  if (props.linkURL && props.mediaType === 'none') {
    menuTpl = [{
      type: 'separator',
    }, {
      id: 'openLink',
      label: 'Open Link in Browser',
      click() {
        debug('Open link in Browser', props.linkURL);
        shell.openExternal(props.linkURL);
      },
    }, {
      id: 'copyLink',
      label: 'Copy Link',
      click() {
        clipboard.write({
          bookmark: props.linkText,
          text: props.linkURL,
        });
      },
    }, {
      type: 'separator',
    }];
  }

  if (props.mediaType === 'image') {
    menuTpl.push({
      type: 'separator',
    }, {
      id: 'openImage',
      label: 'Open Image in Browser',
      click() {
        debug('Open image in Browser', props.srcURL);
        shell.openExternal(props.srcURL);
      },
    }, {
      id: 'copyImageAddress',
      label: 'Copy Image Address',
      click() {
        clipboard.write({
          bookmark: props.srcURL,
          text: props.srcURL,
        });
      },
    }, {
      type: 'separator',
    });
  }

  if (props.mediaType === 'image') {
    menuTpl.push({
      id: 'saveImageAs',
      label: 'Save Image As…',
      async click() {
        if (props.srcURL.startsWith('blob:')) {
          const url = new window.URL(props.srcURL.substr(5));
          const fileName = url.pathname.substr(1);
          const resp = await window.fetch(props.srcURL);
          const blob = await resp.blob();
          const reader = new window.FileReader();
          reader.readAsDataURL(blob);
          reader.onloadend = () => {
            const base64data = reader.result;

            ipcRenderer.send('download-file', {
              content: base64data,
              fileOptions: {
                name: fileName,
                mime: blob.type,
              },
            });
          };
          debug('binary string', blob);
        } else {
          ipcRenderer.send('download-file', { url: props.srcURL });
        }
      },
    }, {
      type: 'separator',
    });
  }

  if (suggestions.length > 0) {
    suggestions.reverse().map(suggestion => menuTpl.unshift({
      id: `suggestion-${suggestion}`,
      label: suggestion,
      click() {
        webContents.replaceMisspelling(suggestion);
      },
    }));
  }

  if (isDevMode) {
    menuTpl.push({
      type: 'separator',
    }, {
      id: 'inspect',
      label: 'Inspect Element',
      click() {
        webContents.inspectElement(props.x, props.y);
      },
    }, {
      type: 'separator',
    });
  }

  return delUnusedElements(menuTpl);
};

export default function contextMenu(spellcheckProvider) {
  webContents.on('context-menu', (e, props) => {
    e.preventDefault();

    let suggestions = [];
    if (spellcheckProvider && props.misspelledWord) {
      suggestions = spellcheckProvider.getSuggestion(props.misspelledWord);

      debug('Suggestions', suggestions);
    }

    const menu = Menu.buildFromTemplate(buildMenuTpl(props, suggestions.slice(0, 5)));

    menu.popup(remote.getCurrentWindow());
  });
}
<commit_msg>feat(Context Menu): Add "Go Back" and "Go Forward"<commit_after>// This is heavily based on https://github.com/sindresorhus/electron-context-menu
// ❤ @sindresorhus

import { clipboard, remote, ipcRenderer, shell } from 'electron';

import { isDevMode, isMac } from '../environment';

const debug = require('debug')('Franz:contextMenu');

const { Menu } = remote;

// const win = remote.getCurrentWindow();
const webContents = remote.getCurrentWebContents();

function delUnusedElements(menuTpl) {
  let notDeletedPrevEl;
  return menuTpl.filter(el => el.visible !== false).filter((el, i, array) => {
    const toDelete = el.type === 'separator' && (!notDeletedPrevEl || i === array.length - 1 || array[i + 1].type === 'separator');
    notDeletedPrevEl = toDelete ? notDeletedPrevEl : el;
    return !toDelete;
  });
}

const buildMenuTpl = (props, suggestions) => {
  const { editFlags } = props;
  const textSelection = props.selectionText.trim();
  const hasText = textSelection.length > 0;
  const can = type => editFlags[`can${type}`] && hasText;

  const canGoBack = webContents.canGoBack();
  const canGoForward = webContents.canGoForward();

  let menuTpl = [
    {
      type: 'separator',
    }, {
      id: 'lookup',
      label: `Look Up "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`,
      visible: isMac && props.mediaType === 'none' && hasText,
      click() {
        debug('Show definition for selection', textSelection);
        webContents.showDefinitionForSelection();
      },
    }, {
      type: 'separator',
    }, {
      id: 'cut',
      role: can('Cut') ? 'cut' : '',
      enabled: can('Cut'),
      visible: hasText && props.isEditable,
    }, {
      id: 'copy',
      label: 'Copy',
      role: can('Copy') ? 'copy' : '',
      enabled: can('Copy'),
      visible: props.isEditable || hasText,
    }, {
      id: 'paste',
      label: 'Paste',
      role: editFlags.canPaste ? 'paste' : '',
      enabled: editFlags.canPaste,
      visible: props.isEditable,
    }, {
      type: 'separator',
      visible: props.isEditable && hasText,
    }, {
      id: 'searchTextSelection',
      label: `Search Google for "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`,
      visible: hasText,
      click() {
        const url = `https://www.google.com/search?q=${textSelection}`;
        debug('Search on Google', url);
        shell.openExternal(url);
      },
    }, {
      type: 'separator',
    },
  ];

  if (props.linkURL && props.mediaType === 'none') {
    menuTpl = [{
      type: 'separator',
    }, {
      id: 'openLink',
      label: 'Open Link in Browser',
      click() {
        debug('Open link in Browser', props.linkURL);
        shell.openExternal(props.linkURL);
      },
    }, {
      id: 'copyLink',
      label: 'Copy Link',
      click() {
        clipboard.write({
          bookmark: props.linkText,
          text: props.linkURL,
        });
      },
    }, {
      type: 'separator',
    }];
  }

  if (props.mediaType === 'image') {
    menuTpl.push({
      type: 'separator',
    }, {
      id: 'openImage',
      label: 'Open Image in Browser',
      click() {
        debug('Open image in Browser', props.srcURL);
        shell.openExternal(props.srcURL);
      },
    }, {
      id: 'copyImageAddress',
      label: 'Copy Image Address',
      click() {
        clipboard.write({
          bookmark: props.srcURL,
          text: props.srcURL,
        });
      },
    }, {
      type: 'separator',
    });
  }

  if (props.mediaType === 'image') {
    menuTpl.push({
      id: 'saveImageAs',
      label: 'Save Image As…',
      async click() {
        if (props.srcURL.startsWith('blob:')) {
          const url = new window.URL(props.srcURL.substr(5));
          const fileName = url.pathname.substr(1);
          const resp = await window.fetch(props.srcURL);
          const blob = await resp.blob();
          const reader = new window.FileReader();
          reader.readAsDataURL(blob);
          reader.onloadend = () => {
            const base64data = reader.result;

            ipcRenderer.send('download-file', {
              content: base64data,
              fileOptions: {
                name: fileName,
                mime: blob.type,
              },
            });
          };
          debug('binary string', blob);
        } else {
          ipcRenderer.send('download-file', { url: props.srcURL });
        }
      },
    }, {
      type: 'separator',
    });
  }

  if (suggestions.length > 0) {
    suggestions.reverse().map(suggestion => menuTpl.unshift({
      id: `suggestion-${suggestion}`,
      label: suggestion,
      click() {
        webContents.replaceMisspelling(suggestion);
      },
    }));
  }

  if (canGoBack || canGoForward) {
    menuTpl.push({
      type: 'separator',
    }, {
      id: 'goBack',
      label: 'Go Back',
      enabled: canGoBack,
      click() {
        webContents.goBack();
      },
    }, {
      id: 'goForward',
      label: 'Go Forward',
      enabled: canGoForward,
      click() {
        webContents.goForward();
      },
    }, {
      type: 'separator',
    });
  }

  if (isDevMode) {
    menuTpl.push({
      type: 'separator',
    }, {
      id: 'inspect',
      label: 'Inspect Element',
      click() {
        webContents.inspectElement(props.x, props.y);
      },
    });
  }

  return delUnusedElements(menuTpl);
};

export default function contextMenu(spellcheckProvider) {
  webContents.on('context-menu', (e, props) => {
    e.preventDefault();

    let suggestions = [];
    if (spellcheckProvider && props.misspelledWord) {
      suggestions = spellcheckProvider.getSuggestion(props.misspelledWord);

      debug('Suggestions', suggestions);
    }

    const menu = Menu.buildFromTemplate(buildMenuTpl(props, suggestions.slice(0, 5)));

    menu.popup(remote.getCurrentWindow());
  });
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from './template';

export default Ember.Component.extend({
    layout,
    fileManager: Ember.inject.service(),
    store: Ember.inject.service(),

    actions: {
        download() {
            let file = this.get('file');
            let url = file.get('links').download;
            window.open(url);
        },

        updateContents(evt) {
            let contents = evt.target.files[0];
            let file = this.get('file');
            let fm = this.get('fileManager');

            fm.updateContents(file, contents).then(() => {
                this.get('onChange')();
            });
        },

        addSubfolder(name) {
            let folder = this.get('file');
            if (name) {
                let p = this.get('fileManager').addSubfolder(folder, name);
                p.then(() => {
                    this.get('onChange')();
                });
            }
        },

        uploadFile(evt) {
            let newFile = evt.target.files[0];
            let folder = this.get('file');
            if (newFile) {
                let fm = this.get('fileManager');
                fm.uploadFile(folder, newFile.name, newFile).then(() => {
                    this.get('onChange')();
                });
            }
        },

        rename(newName) {
            let file = this.get('file');
            if (newName) {
                let p = this.get('fileManager').rename(file, newName);
                p.then(() => {
                    file.set('name', newName);
                    this.get('onChange')();
                });
            }
        },

        deleteFile() {
            let file = this.get('file');
            let p = this.get('fileManager').deleteFile(file);
            p.then(() => {
                this.get('onChange')();
            });
        },

        moveFile(folderId) {
            let file = this.get('file');
            let store = this.get('store');
            let folder = store.peekRecord('file', folderId);
            if (!folder) {
                folder = store.peekRecord('file-provider', folderId);
                if (!folder) {
                    // TODO errors
                    return;
                }
            }
            let options = {
                node: this.get('moveNode'),
                provider: folder.get('provider'),
                replace: this.get('moveReplace'),
                copy: this.get('moveCopy'),
                newName: this.get('moveName')
            };

            let p = this.get('fileManager').move(file, folder, options);
            p.then(() => this.get('onChange'));
        }
    }
});
<commit_msg>Do the right thing after moving a file in the dummy app<commit_after>import Ember from 'ember';
import layout from './template';

export default Ember.Component.extend({
    layout,
    fileManager: Ember.inject.service(),
    store: Ember.inject.service(),

    actions: {
        download() {
            let file = this.get('file');
            let url = file.get('links').download;
            window.open(url);
        },

        updateContents(evt) {
            let contents = evt.target.files[0];
            let file = this.get('file');
            let fm = this.get('fileManager');

            fm.updateContents(file, contents).then(() => {
                this.get('onChange')();
            });
        },

        addSubfolder(name) {
            let folder = this.get('file');
            if (name) {
                let p = this.get('fileManager').addSubfolder(folder, name);
                p.then(() => {
                    this.get('onChange')();
                });
            }
        },

        uploadFile(evt) {
            let newFile = evt.target.files[0];
            let folder = this.get('file');
            if (newFile) {
                let fm = this.get('fileManager');
                fm.uploadFile(folder, newFile.name, newFile).then(() => {
                    this.get('onChange')();
                });
            }
        },

        rename(newName) {
            let file = this.get('file');
            if (newName) {
                let p = this.get('fileManager').rename(file, newName);
                p.then(() => {
                    file.set('name', newName);
                    this.get('onChange')();
                });
            }
        },

        deleteFile() {
            let file = this.get('file');
            let p = this.get('fileManager').deleteFile(file);
            p.then(() => {
                this.get('onChange')();
            });
        },

        moveFile(folderId) {
            let file = this.get('file');
            let store = this.get('store');
            let folder = store.findRecord('file', folderId);
            if (!folder) {
                folder = store.findRecord('file-provider', folderId);
                if (!folder) {
                    return;
                }
            }
            let options = {
                node: this.get('moveNode'),
                provider: folder.get('provider'),
                replace: this.get('moveReplace'),
                copy: this.get('moveCopy'),
                newName: this.get('moveName')
            };

            let p = this.get('fileManager').move(file, folder, options);
            p.then(() => this.get('onChange')());
        }
    }
});
<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import {
  render,
  click,
  triggerEvent,
  find,
  waitFor,
  waitUntil,
} from '@ember/test-helpers';

module(
  'modifier',
  'Integration | Modifier | on-click-outside',
  function (hooks) {
    setupRenderingTest(hooks);

    test('smoke test', async function (assert) {
      assert.expect(2);

      this.set('didClickOutside', (e) => {
        assert.ok('`didClickOutside` fired only once');
        assert.equal(
          e.target.className,
          'outside',
          'the event object was passed and is correct'
        );
      });

      await render(hbs`

Somewhere, over the rainbow...

We're in

    `);

      await click('.inside');
      await click('.outside');
    });

    test('real-world scenario', async function (assert) {
      this.isOpened = false;

      this.open = () => {
        this.set('isOpened', true);
      };

      this.close = () => {
        assert.ok(true, 'The close handler was called');
        this.set('isOpened', false);
      };

      await render(hbs`
      <button data-test-open onclick={{action this.open}}>
        Toggle popover
      </button>

Outside

      {{#if this.isOpened}}

          Popover is opened.

      {{/if}}
    `);

      await click('[data-test-open]');
      await click('[data-test-outside]');
    });

    test(`it doesn't throw without a handler`, async function (assert) {
      assert.expect(0);

      await render(hbs`

Somewhere, over the rainbow...

We're in

    `);

      await click('.outside');
    });

    test('except selector', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      await render(hbs`

Somewhere, over the rainbow...

        Somewhere, under the rainbow...

    `);

      await click('.outside');
      await click('.except-outside');
    });

    test('handle removed DOM element outside', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      this.set('toggleFlag', () => {
        this.set('topSide', true);
      });

      await render(hbs`
      {{#if topSide}}
        Blue
      {{else}}

Yellow

      {{/if}}

    `);

      await click('.outside');
    });

    test('custom event', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      await render(hbs`

Somewhere, over the rainbow...

    `);

      await triggerEvent('.outside', 'mousedown');
    });

    // https://github.com/zeppelin/ember-click-outside/issues/98
    test('event order (#98)', async function (assert) {
      assert.expect(2);

      this.set('isOpened', false);
      this.set('toggleIsOpened', () => {
        this.set('isOpened', !this.isOpened);
      });

      await render(hbs`
      <button
        {{on "click" (fn this.toggleIsOpened)}}
        class="toggler"
        type="button"
      >
        Toggle isOpened
      </button>

      {{#if this.isOpened}}

Yay

      {{/if}}
    `);

      await click('.toggler');
      await waitFor('.popover');

      assert.ok(find('.popover'), 'The popover is visible');

      await click('.toggler');
      await waitUntil(() => !find('.popover'));

      assert.notOk(find('.popover'), 'The popover is hidden');
    });

    // https://github.com/zeppelin/ember-click-outside/issues/115
    test('multiple instances (#115)', async function (assert) {
      assert.expect(3);

      this.set('items', [1, 2, 3]);
      this.set('itemActionHandler', (which) => {
        assert.ok(true, 'The handler was called');
      });

      await render(hbs`

      {{#each this.items as |i|}}
        <Item @act={{fn this.itemActionHandler i}} />
      {{/each}}
    `);

      await click('.x');
    });
  }
);
<commit_msg>Tell qunit how many tests to expect<commit_after>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import {
  render,
  click,
  triggerEvent,
  find,
  waitFor,
  waitUntil,
} from '@ember/test-helpers';

module(
  'modifier',
  'Integration | Modifier | on-click-outside',
  function (hooks) {
    setupRenderingTest(hooks);

    test('smoke test', async function (assert) {
      assert.expect(2);

      this.set('didClickOutside', (e) => {
        assert.ok('`didClickOutside` fired only once');
        assert.equal(
          e.target.className,
          'outside',
          'the event object was passed and is correct'
        );
      });

      await render(hbs`

Somewhere, over the rainbow...

We're in

    `);

      await click('.inside');
      await click('.outside');
    });

    test('real-world scenario', async function (assert) {
      assert.expect(1);
      this.isOpened = false;

      this.open = () => {
        this.set('isOpened', true);
      };

      this.close = () => {
        assert.ok(true, 'The close handler was called');
        this.set('isOpened', false);
      };

      await render(hbs`
      <button data-test-open onclick={{action this.open}}>
        Toggle popover
      </button>

Outside

      {{#if this.isOpened}}

          Popover is opened.

      {{/if}}
    `);

      await click('[data-test-open]');
      await click('[data-test-outside]');
    });

    test(`it doesn't throw without a handler`, async function (assert) {
      assert.expect(0);

      await render(hbs`

Somewhere, over the rainbow...

We're in

    `);

      await click('.outside');
    });

    test('except selector', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      await render(hbs`

Somewhere, over the rainbow...

        Somewhere, under the rainbow...

    `);

      await click('.outside');
      await click('.except-outside');
    });

    test('handle removed DOM element outside', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      this.set('toggleFlag', () => {
        this.set('topSide', true);
      });

      await render(hbs`
      {{#if topSide}}
        Blue
      {{else}}

Yellow

      {{/if}}

    `);

      await click('.outside');
    });

    test('custom event', async function (assert) {
      assert.expect(1);

      this.set('didClickOutside', () => {
        assert.ok('`didClickOutside` fired only once');
      });

      await render(hbs`

Somewhere, over the rainbow...

    `);

      await triggerEvent('.outside', 'mousedown');
    });

    // https://github.com/zeppelin/ember-click-outside/issues/98
    test('event order (#98)', async function (assert) {
      assert.expect(2);

      this.set('isOpened', false);
      this.set('toggleIsOpened', () => {
        this.set('isOpened', !this.isOpened);
      });

      await render(hbs`
      <button
        {{on "click" (fn this.toggleIsOpened)}}
        class="toggler"
        type="button"
      >
        Toggle isOpened
      </button>

      {{#if this.isOpened}}

Yay

      {{/if}}
    `);

      await click('.toggler');
      await waitFor('.popover');

      assert.ok(find('.popover'), 'The popover is visible');

      await click('.toggler');
      await waitUntil(() => !find('.popover'));

      assert.notOk(find('.popover'), 'The popover is hidden');
    });

    // https://github.com/zeppelin/ember-click-outside/issues/115
    test('multiple instances (#115)', async function (assert) {
      assert.expect(3);

      this.set('items', [1, 2, 3]);
      this.set('itemActionHandler', (which) => {
        assert.ok(true, 'The handler was called');
      });

      await render(hbs`

      {{#each this.items as |i|}}
        <Item @act={{fn this.itemActionHandler i}} />
      {{/each}}
    `);

      await click('.x');
    });
  }
);
<|endoftext|>


<commit_before>var helpersTests = [
  {
    name:     "replace",
    source:   "Hello {name}! You have {count} new messages.",
    context:  { name: "Mick", count: 30 },
    expected: "Hello Mick! You have 30 new messages.",
    message: "should test a basic replace"
  },
	{
    name:     "if helper without else",
    source:   '{@if cond="{x}<{y}"}
 X < Y
{/if}',
    context:  { x: 2, y: 3 },
    expected: "
 X < Y
",
    message: "should test if helper without else"
  },
  {
    name:     "if helper with else block",
    source:   '{@if cond=" \'{x}\'.length && \'{y}\'.length "}
 X and Y exists
{:else}
 X and Y does not exists
{/if}',
    context:  {},
    expected: "
 X and Y does not exists
",
    message: "should test if helper with else block"
  },
  {
    name:     "if helper with else using the or condition",
    source:   '{@if cond=" \'{x}\'.length || \'{y}\'.length "}
 X or Y exists
{:else}
 X or Y does not exists
{/if}',
    context:  { x: 1},
    expected: "
 X or Y exists
",
    message: "should test if helper with else using the or condition"
  },
  {
    name:     "if helper with else using the and conditon",
    source:   '{@if cond="( \'{x}\'.length ) && ({x}<3)"}
 X exists and is 1
{:else}
 x is not there
{/if}',
    context:  { x : 1},
    expected: "
 X exists and is 1
",
    message: "should test if helper with else usingt he and conditon"
  },
  {
    name:     "if helper using $idx",
    source:   '{#list}{@if cond="( {$idx} == 1 )"}
{y}
{/if}{/list}',
    context:  { x : 1, list: [ { y: 'foo' }, { y: 'bar'} ]},
    expected: "
bar
",
    message: "should test the if helper using $idx"
  },
  {
    name:     "math helper mod numbers",
    source:   '
{@math key="16" method="mod" operand="4"/}
',
    context:  {},
    expected: "
0
",
    message: "testing math/mod helper with two numbers"
  },
  {
    name:     "math helper mod using $idx",
    source:   '{#list}
{@math key="{$idx}" method="mod" operand="5"/}
{/list}',
    context:  { list: [ { y: 'foo' } ]},
    expected: "
0
",
    message: "should test the math/mod helper using $idx"
  },
  {
    name:     "math helper subtract numbers",
    source:   '
{@math key="16" method="subtract" operand="4"/}
',
    context:  {},
    expected: "
12
",
    message: "testing math/subtract helper with two numbers"
  },
  {
    name:     "math helper subtract number and string",
    source:   '
{@math key="16" method="subtract" operand="doh"/}
',
    context:  {},
    expected: "
NaN
",
    message: "testing math/subtract helper with a number and a string"
  },
  {
    name:     "math helper add numbers",
    source:   '
{@math key="5" method="add" operand="4"/}
',
    context:  {},
    expected: "
9
",
    message: "testing math/add helper with two numbers"
  },
  {
    name:     "math helper multiply numbers",
    source:   '
{@math key="5" method="multiply" operand="4"/}
',
    context:  {},
    expected: "
20
",
    message: "testing math/multiply helper with two numbers"
  },
  {
    name:     "math helper divide using variable",
    source:   '
{@math key="16" method="divide" operand="{y}"/}
',
    context:  { y : 4 },
    expected: "
4
",
    message: "testing math/divide helper with variable as operand"
  },
  {
    name:     "math helper floor numbers",
    source:   '
{@math key="16.5" method="floor"/}
',
    context:  {},
    expected: "
16
",
    message: "testing math/floor helper with two numbers"
  },
  {
    name:     "math helper ceil numbers",
    source:   '
{@math key="16.5" method="ceil"/}
',
    context:  {},
    expected: "
17
",
    message: "testing math/ceil helper with two numbers"
  },
  {
    name:     "math helper abs numbers",
    source:   '
{@math key="-16" method="abs"/}
',
    context:  {},
    expected: "
16
",
    message: "testing math/abs helper with two numbers"
  },
  {
    name:     "math helper eq  numbers",
    source:   '
{@math key="15" eq="16"/}
',
    context:  {},
    expected: "
false
",
    message: "testing math/eq helper with two numbers"
  },
  {
    name:     "select helper with a constant string and condition eq",
    source:   ["{@select key=\"foo\"}",
                 "{@eq value=\"foo\"}foo{/eq}",
               "{/select}"
              ].join("\n"),
    context:  {},
    expected: "foo",
    message: "should test select helper with a constant string and condition eq"
  },
  {
    name:     "select helper with a variable string and condition eq",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"foo\"}foo{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "foo",
    message: "should test select helper with a variable string and condition eq"
  },
  {
    name:     "select helper with variable and one condition eq",
    source:   ["{@select key=foo}",
                 "{@eq value=10}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition eq"
  },
  {
    name:     "select helper with string variable compared to a number and one condition eq",
    source:   ["{@select key=foo}",
                 "{@eq value=10}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with string variable compared to a number and one condition eq"
  },

  {
    name:     "select helper with variable and one condition lt",
    source:   ["{@select key=foo}",
                 "{@lt value=20}foobar{/lt}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition lt"
  },
  {
    name:     "select helper with one condition lte",
    source:   ["{@select key=foo}",
                 "{@lte value=10}foobar{/lte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with one condition lte"
  },
  {
    name:     "select helper with with variable and one condition lte",
    source:   ["{@select key=foo}",
                 "{@lte value=11}foobar{/lte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition lte"
  },
  {
    name:     "select helper with variable and one condition gt",
    source:   ["{@select key=foo}",
                 "{@gt value=5}foobar{/gt}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gt"
  },
  {
    name:     "select helper with variable and one condition gte",
    source:   ["{@select key=foo}",
                 "{@gte value=10}foobar{/gte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gte"
  },
  {
    name:     "select helper with variable and one condition gte",
    source:   ["{@select key=foo}",
                 "{@gte value=5}foobar{/gte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gte"
  },

  {
    name:     "select helper with variable of type string and eq condition",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "bar" },
    expected: "foobar",
    message: "should test select helper with variable of type string and eq condition"
  },
  {
    name:     "select helper with two conditions",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "baz" },
    expected: "foobaz",
    message: "should test select helper works with two conditions"
  },
  {
    name:     "select helper with three conditions and default case",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
                 "{@eq value=\"foobar\"}foofoobar{/eq}",
                 "{@default value=\"foo\"}foofoo{/default}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "foofoo",
    message: "should test select helper with three conditions and default case"
  },
  {
    name:     "select helper with no matching conditions",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "",
    message: "should test select helper with no matching conditions"
  },
  {
    name:     "select helper with variable and type string with 2 conditions",
    source:   ['{@select key=test}',
                '{@eq value="{y}"}
FOO
{/eq}',
                '{@eq value="{x}"}
BAR
{/eq}',
              '{/select}'].join("\n"),
    context:  { "test":"foo", "y": "foo", "x": "bar" },
    expected: "
FOO
",
    message: "should test select helper with variable and type string with 2 conditions"
  },
  {
    name:     "select helper with variable and type string in a nested object",
    source:   "{@select key=x.key}{@eq value=10}foobar{/eq}{/select}",
    context:  {"x": {"key" : 10}},
    expected: "foobar",
    message: "should test select helper with variable and type string in a nested object"
  },
  {
    name:     "select helper with variable and type string in a nested objects",
    source:   "{@select key=\"{x.b.foo}\"}{@eq value=\"a\"}foobar{/eq}{/select}",
    context:  { x : {b : { "foo" : "a"}}},
    expected: "foobar",
    message: "should test select helper with variable and type string in a nested objects"
  },

  {
    name:     "select helper with missing key in the context and hence no output",
    source:   ["{#b}{@select key=y}",
               " {@eq value=\"{z}\"}
FOO
{/eq}",
               " {@eq value=\"{x}\"}
BAR
{/eq}",
               " {@default}foofoo{/default}",
               "{/select}{/b}"].join("\n"),
    context:  { b : { z: "foo", x: "bar" } },
    expected: "",
    message: "should test select helper with missing key in the context and hence no output"
  },
  {
    name:     "select helper wih key matching the else condition",
    source:   ["{#b}{@select key=\"{x}\"}",
               " {@eq value=\"{y}\"}
BAR
{/eq}",
               " {@eq value=\"{z}\"}
BAZ
{/eq}",
               " {@default value=\"foo\"}foofoo{/default}",
               "{/select}{/b}"].join("\n"),
    context:  { b : { "x": "foo", "y": "bar", "z": "baz" } },
    expected: "foofoo",
    message: "should test select helper with key matching the else condition"
  },
  {
    name:     "select helper inside a array with .",
    source:   ["{#skills}{@select key=.}",
               "{@eq value=\"java\"}JAVA,{/eq}",
               "{@eq value=\"js\"}JS,{/eq}",
               "{@default value=\"foo\"}UNKNOWN{/default}",
               "{/select}{/skills}"].join("\n"),
    context:  { "skills" : [ "java", "js" , "unknown"] },
    expected: "JAVA,JS,UNKNOWN",
    message: "should test a select helper inside a array with ."
  },
  {
    name:     "select helper inside a array with {.}",
    source:   ["{#skills}{@select key=\"{.}\"}",
               "{@eq value=\"java\"}JAVA,{/eq}",
               "{@eq value=\"js\"}JS,{/eq}",
               "{@default value=\"foo\"}UNKNOWN{/default}",
               "{/select}{/skills}"].join("\n"),
    context:  { "skills" : [ "java", "js" , "unknown"] },
    expected: "JAVA,JS,UNKNOWN",
    message: "should test select helper inside a array with {.}"
  },
  {
  	name:     "partial within a array",
    source:   '{#n}{>replace name=. count="30"/}{@sep} {/sep}{/n}',
    context:  { n: ["Mick", "Tom", "Bob"] },
    expected: "Hello Mick! You have 30 new messages. Hello Tom! You have 30 new messages. Hello Bob! You have 30 new messages.",
    message: "should test partial within an array"
  },
  {
    name:     "async_iterator",
    source:   "{#numbers}{#delay}{.}{/delay}{@sep}, {/sep}{/numbers}",
    context:  {
                numbers: [3, 2, 1],
                delay: function(chunk, context, bodies) {
                  return chunk.map(function(chunk) {
                    setTimeout(function() {
                      chunk.render(bodies.block, context).end();
                    }, Math.ceil(Math.random()*10));
                  });
                }
              },
    expected: "3, 2, 1",
    message: "should test async iterator"
  },
];

if (typeof module !== "undefined" && typeof require !== "undefined") {
    module.exports = helpersTests; // We're on node.js
} else {
    window.helpersTests = helpersTests; // We're on the browser
}
<commit_msg>trying again with last commit<commit_after>var helpersTests = [
  {
    name:     "replace",
    source:   "Hello {name}! You have {count} new messages.",
    context:  { name: "Mick", count: 30 },
    expected: "Hello Mick! You have 30 new messages.",
    message: "should test a basic replace"
  },
  {
    name:     "if helper without else",
    source:   '{@if cond="{x}<{y}"}
 X < Y
{/if}',
    context:  { x: 2, y: 3 },
    expected: "
 X < Y
",
    message: "should test if helper without else"
  },
  {
    name:     "if helper with else block",
    source:   '{@if cond=" \'{x}\'.length && \'{y}\'.length "}
 X and Y exists
{:else}
 X and Y does not exists
{/if}',
    context:  {},
    expected: "
 X and Y does not exists
",
    message: "should test if helper with else block"
  },
  {
    name:     "if helper with else using the or condition",
    source:   '{@if cond=" \'{x}\'.length || \'{y}\'.length "}
 X or Y exists
{:else}
 X or Y does not exists
{/if}',
    context:  { x: 1},
    expected: "
 X or Y exists
",
    message: "should test if helper with else using the or condition"
  },
  {
    name:     "if helper with else using the and conditon",
    source:   '{@if cond="( \'{x}\'.length ) && ({x}<3)"}
 X exists and is 1
{:else}
 x is not there
{/if}',
    context:  { x : 1},
    expected: "
 X exists and is 1
",
    message: "should test if helper with else usingt he and conditon"
  },
  {
    name:     "if helper using $idx",
    source:   '{#list}{@if cond="( {$idx} == 1 )"}
{y}
{/if}{/list}',
    context:  { x : 1, list: [ { y: 'foo' }, { y: 'bar'} ]},
    expected: "
bar
",
    message: "should test the if helper using $idx"
  },
  {
    name:     "math helper mod numbers",
    source:   '
{@math key="16" method="mod" operand="4"/}
',
    context:  {},
    expected: "
0
",
    message: "testing math/mod helper with two numbers"
  },
  {
    name:     "math helper mod using $idx",
    source:   '{#list}
{@math key="{$idx}" method="mod" operand="5"/}
{/list}',
    context:  { list: [ { y: 'foo' } ]},
    expected: "
0
",
    message: "should test the math/mod helper using $idx"
  },
  {
    name:     "math helper subtract numbers",
    source:   '
{@math key="16" method="subtract" operand="4"/}
',
    context:  {},
    expected: "
12
",
    message: "testing math/subtract helper with two numbers"
  },
  {
    name:     "math helper subtract number and string",
    source:   '
{@math key="16" method="subtract" operand="doh"/}
',
    context:  {},
    expected: "
NaN
",
    message: "testing math/subtract helper with a number and a string"
  },
  {
    name:     "math helper add numbers",
    source:   '
{@math key="5" method="add" operand="4"/}
',
    context:  {},
    expected: "
9
",
    message: "testing math/add helper with two numbers"
  },
  {
    name:     "math helper multiply numbers",
    source:   '
{@math key="5" method="multiply" operand="4"/}
',
    context:  {},
    expected: "
20
",
    message: "testing math/multiply helper with two numbers"
  },
  {
    name:     "math helper divide using variable",
    source:   '
{@math key="16" method="divide" operand="{y}"/}
',
    context:  { y : 4 },
    expected: "
4
",
    message: "testing math/divide helper with variable as operand"
  },
  {
    name:     "math helper floor numbers",
    source:   '
{@math key="16.5" method="floor"/}
',
    context:  {},
    expected: "
16
",
    message: "testing math/floor helper with two numbers"
  },
  {
    name:     "math helper ceil numbers",
    source:   '
{@math key="16.5" method="ceil"/}
',
    context:  {},
    expected: "
17
",
    message: "testing math/ceil helper with two numbers"
  },
  {
    name:     "math helper abs numbers",
    source:   '
{@math key="-16" method="abs"/}
',
    context:  {},
    expected: "
16
",
    message: "testing math/abs helper with two numbers"
  },
  {
    name:     "math helper eq  numbers",
    source:   '
{@math key="15" eq="16"/}
',
    context:  {},
    expected: "
false
",
    message: "testing math/eq helper with two numbers"
  },
  {
    name:     "select helper with a constant string and condition eq",
    source:   ["{@select key=\"foo\"}",
                 "{@eq value=\"foo\"}foo{/eq}",
               "{/select}"
              ].join("\n"),
    context:  {},
    expected: "foo",
    message: "should test select helper with a constant string and condition eq"
  },
  {
    name:     "select helper with a variable string and condition eq",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"foo\"}foo{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "foo",
    message: "should test select helper with a variable string and condition eq"
  },
  {
    name:     "select helper with variable and one condition eq",
    source:   ["{@select key=foo}",
                 "{@eq value=10}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition eq"
  },
  {
    name:     "select helper with string variable compared to a number and one condition eq",
    source:   ["{@select key=foo}",
                 "{@eq value=10}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with string variable compared to a number and one condition eq"
  },

  {
    name:     "select helper with variable and one condition lt",
    source:   ["{@select key=foo}",
                 "{@lt value=20}foobar{/lt}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition lt"
  },
  {
    name:     "select helper with one condition lte",
    source:   ["{@select key=foo}",
                 "{@lte value=10}foobar{/lte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with one condition lte"
  },
  {
    name:     "select helper with with variable and one condition lte",
    source:   ["{@select key=foo}",
                 "{@lte value=11}foobar{/lte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition lte"
  },
  {
    name:     "select helper with variable and one condition gt",
    source:   ["{@select key=foo}",
                 "{@gt value=5}foobar{/gt}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gt"
  },
  {
    name:     "select helper with variable and one condition gte",
    source:   ["{@select key=foo}",
                 "{@gte value=10}foobar{/gte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gte"
  },
  {
    name:     "select helper with variable and one condition gte",
    source:   ["{@select key=foo}",
                 "{@gte value=5}foobar{/gte}",
               "{/select}"
              ].join("\n"),
    context:  { foo: 10 },
    expected: "foobar",
    message: "should test select helper with variable and one condition gte"
  },

  {
    name:     "select helper with variable of type string and eq condition",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "bar" },
    expected: "foobar",
    message: "should test select helper with variable of type string and eq condition"
  },
  {
    name:     "select helper with two conditions",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "baz" },
    expected: "foobaz",
    message: "should test select helper works with two conditions"
  },
  {
    name:     "select helper with three conditions and default case",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
                 "{@eq value=\"foobar\"}foofoobar{/eq}",
                 "{@default value=\"foo\"}foofoo{/default}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "foofoo",
    message: "should test select helper with three conditions and default case"
  },
  {
    name:     "select helper with no matching conditions",
    source:   ["{@select key=\"{foo}\"}",
                 "{@eq value=\"bar\"}foobar{/eq}",
                 "{@eq value=\"baz\"}foobaz{/eq}",
               "{/select}"
              ].join("\n"),
    context:  { "foo": "foo" },
    expected: "",
    message: "should test select helper with no matching conditions"
  },
  {
    name:     "select helper with variable and type string with 2 conditions",
    source:   ['{@select key=test}',
                '{@eq value="{y}"}
FOO
{/eq}',
                '{@eq value="{x}"}
BAR
{/eq}',
              '{/select}'].join("\n"),
    context:  { "test":"foo", "y": "foo", "x": "bar" },
    expected: "
FOO
",
    message: "should test select helper with variable and type string with 2 conditions"
  },
  {
    name:     "select helper with variable and type string in a nested object",
    source:   "{@select key=x.key}{@eq value=10}foobar{/eq}{/select}",
    context:  {"x": {"key" : 10}},
    expected: "foobar",
    message: "should test select helper with variable and type string in a nested object"
  },
  {
    name:     "select helper with variable and type string in a nested objects",
    source:   "{@select key=\"{x.b.foo}\"}{@eq value=\"a\"}foobar{/eq}{/select}",
    context:  { x : {b : { "foo" : "a"}}},
    expected: "foobar",
    message: "should test select helper with variable and type string in a nested objects"
  },

  {
    name:     "select helper with missing key in the context and hence no output",
    source:   ["{#b}{@select key=y}",
               " {@eq value=\"{z}\"}
FOO
{/eq}",
               " {@eq value=\"{x}\"}
BAR
{/eq}",
               " {@default}foofoo{/default}",
               "{/select}{/b}"].join("\n"),
    context:  { b : { z: "foo", x: "bar" } },
    expected: "",
    message: "should test select helper with missing key in the context and hence no output"
  },
  {
    name:     "select helper wih key matching the else condition",
    source:   ["{#b}{@select key=\"{x}\"}",
               " {@eq value=\"{y}\"}
BAR
{/eq}",
               " {@eq value=\"{z}\"}
BAZ
{/eq}",
               " {@default value=\"foo\"}foofoo{/default}",
               "{/select}{/b}"].join("\n"),
    context:  { b : { "x": "foo", "y": "bar", "z": "baz" } },
    expected: "foofoo",
    message: "should test select helper with key matching the else condition"
  },
  {
    name:     "select helper inside a array with .",
    source:   ["{#skills}{@select key=.}",
               "{@eq value=\"java\"}JAVA,{/eq}",
               "{@eq value=\"js\"}JS,{/eq}",
               "{@default value=\"foo\"}UNKNOWN{/default}",
               "{/select}{/skills}"].join("\n"),
    context:  { "skills" : [ "java", "js" , "unknown"] },
    expected: "JAVA,JS,UNKNOWN",
    message: "should test a select helper inside a array with ."
  },
  {
    name:     "select helper inside a array with {.}",
    source:   ["{#skills}{@select key=\"{.}\"}",
               "{@eq value=\"java\"}JAVA,{/eq}",
               "{@eq value=\"js\"}JS,{/eq}",
               "{@default value=\"foo\"}UNKNOWN{/default}",
               "{/select}{/skills}"].join("\n"),
    context:  { "skills" : [ "java", "js" , "unknown"] },
    expected: "JAVA,JS,UNKNOWN",
    message: "should test select helper inside a array with {.}"
  },
  {
    name:     "partial within a array",
    source:   '{#n}{>replace name=. count="30"/}{@sep} {/sep}{/n}',
    context:  { n: ["Mick", "Tom", "Bob"] },
    expected: "Hello Mick! You have 30 new messages. Hello Tom! You have 30 new messages. Hello Bob! You have 30 new messages.",
    message: "should test partial within an array"
  },
  {
    name:     "async_iterator",
    source:   "{#numbers}{#delay}{.}{/delay}{@sep}, {/sep}{/numbers}",
    context:  {
                numbers: [3, 2, 1],
                delay: function(chunk, context, bodies) {
                  return chunk.map(function(chunk) {
                    setTimeout(function() {
                      chunk.render(bodies.block, context).end();
                    }, Math.ceil(Math.random()*10));
                  });
                }
              },
    expected: "3, 2, 1",
    message: "should test async iterator"
  },
];

if (typeof module !== "undefined" && typeof require !== "undefined") {
    module.exports = helpersTests; // We're on node.js
} else {
    window.helpersTests = helpersTests; // We're on the browser
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2013  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// WidgetModel, WidgetView, and WidgetManager
//============================================================================
/**
 * Base Widget classes
 * @module IPython
 * @namespace IPython
 * @submodule widget
 */

(function () {
    "use strict";

    // Use require.js 'define' method so that require.js is intelligent enough to
    // syncronously load everything within this file when it is being 'required'
    // elsewhere.
    define(["underscore",
             "backbone",
            ], function (underscore, backbone) {

        //--------------------------------------------------------------------
        // WidgetManager class
        //--------------------------------------------------------------------
        var WidgetManager = function () {
            this.comm_manager = null;
            this.widget_model_types = {};
            this.widget_view_types = {};
            this._model_instances = {};

            Backbone.sync = function (method, model, options, error) {
                var result = model._handle_sync(method, options);
                if (options.success) {
                  options.success(result);
                }
            };
        };

        WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
            this.comm_manager = comm_manager;

            // Register already-registered widget model types with the comm manager.
            for (var widget_model_name in this.widget_model_types) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
        };

        WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
            // Register the widget with the comm manager.  Make sure to pass this object's context
            // in so `this` works in the call back.
            if (this.comm_manager !== null) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
            this.widget_model_types[widget_model_name] = widget_model_type;
        };

        WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
            this.widget_view_types[widget_view_name] = widget_view_type;
        };

        WidgetManager.prototype.handle_msg = function(msg, model) {
            var method = msg.content.data.method;
            switch (method) {
                case 'display':
                    var cell = this.get_msg_cell(msg.parent_header.msg_id);
                    if (cell === null) {
                        console.log("Could not determine where the display" +
                            " message was from.  Widget will not be displayed");
                    } else {
                        var view = this.create_view(model, msg.content.data.view_name);
                        if (view !== undefined
                            && cell.widget_subarea !== undefined
                            && cell.widget_subarea !== null) {

                            view.cell = cell;
                            cell.widget_area.show();
                            cell.widget_subarea.append(view.$el);
                        }
                    }
                    break;
            }
        }

<<<<<<< HEAD
<<<<<<< HEAD
        WidgetManager.prototype.create_view = function(model, view_name, cell) {
=======
        WidgetManager.prototype.create_view = function(model, view_name, options) {
>>>>>>> Completely remove cell from model and view.
            view_name = view_name || model.get('default_view_name');
=======
    WidgetManager.prototype.create_view = function(model, view_name, cell, options) {
        view_name = view_name || model.get('default_view_name');
>>>>>>> Add widget view options in creating child views
            var ViewType = this.widget_view_types[view_name];
            if (ViewType !== undefined && ViewType !== null) {
                var view = new ViewType({model: model, widget_manager: this, options: options});
                view.render();
                model.views.push(view);
                model.on('destroy', view.remove, view);
<<<<<<< HEAD
                /*
                    // TODO: handle view deletion.  Don't forget to delete child views
                    var that = this;
                    view.$el.on("remove", function () {
                        var index = that.views.indexOf(view);
                        if (index > -1) {
                            that.views.splice(index, 1);
=======
        /*
                // TODO: handle view deletion.  Don't forget to delete child views
                var that = this;
                view.$el.on("remove", function () {
                    var index = that.views.indexOf(view);
                    if (index > -1) {
                        that.views.splice(index, 1);
                    }
                    view.remove(); // Clean-up view

                    // Close the comm if there are no views left.
                    if (that.views.length() === 0) {
            //trigger comm close event?
                        }

                        if (that.comm !== undefined) {
                            that.comm.close();
                            delete that.comm.model; // Delete ref so GC will collect widget model.
                            delete that.comm;
>>>>>>> Add widget view options in creating child views
                        }
                        view.remove(); // Clean-up view

                        // Close the comm if there are no views left.
                        if (that.views.length() === 0) {
                //trigger comm close event?
                            }

                            if (that.comm !== undefined) {
                                that.comm.close();
                                delete that.comm.model; // Delete ref so GC will collect widget model.
                                delete that.comm;
                            }
                            delete that.model_id; // Delete id from model so widget manager cleans up.
                        });
                */
                return view;
            }
        },

        WidgetManager.prototype.get_msg_cell = function (msg_id) {
            var cell = null;
            // First, check to see if the msg was triggered by cell execution.
            if (IPython.notebook !== undefined && IPython.notebook !== null) {
                cell = IPython.notebook.get_msg_cell(msg_id);
            }
            if (cell !== null) {
                return cell
            }
            // Second, check to see if a get_cell callback was defined
            // for the message.  get_cell callbacks are registered for
            // widget messages, so this block is actually checking to see if the
            // message was triggered by a widget.
            var kernel = this.get_kernel();
            if (kernel !== undefined && kernel !== null) {
                var callbacks = kernel.get_callbacks_for_msg(msg_id);
                if (callbacks !== undefined &&
                    callbacks.iopub !== undefined &&
                    callbacks.iopub.get_cell !== undefined) {

                    return callbacks.iopub.get_cell();
                }
            }

            // Not triggered by a cell or widget (no get_cell callback
            // exists).
            return null;
        };

        WidgetManager.prototype.callbacks = function (view) {
            // callback handlers specific a view
            var callbacks = {};
            var cell = view.cell;
            if (cell !== null) {
                // Try to get output handlers
                var handle_output = null;
                var handle_clear_output = null;
                if (cell.output_area !== undefined && cell.output_area !== null) {
                    handle_output = $.proxy(cell.output_area.handle_output, cell.output_area);
                    handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
                }

                // Create callback dict using what is known
                var that = this;
                callbacks = {
                    iopub : {
                        output : handle_output,
                        clear_output : handle_clear_output,

                        status : function (msg) {
                            view.model._handle_status(msg, that.callbacks());
                        },

                        // Special function only registered by widget messages.
                        // Allows us to get the cell for a message so we know
                        // where to add widgets if the code requires it.
                        get_cell : function () {
                            return cell;
                        },
                    },
                };
            }
            return callbacks;
        };

        WidgetManager.prototype.get_model = function (model_id) {
            var model = this._model_instances[model_id];
            if (model !== undefined && model.id == model_id) {
                return model;
            }
            return null;
        };

        WidgetManager.prototype.get_kernel = function () {
            if (this.comm_manager === null) {
                return null;
            } else {
                return this.comm_manager.kernel;
            }
        };

        WidgetManager.prototype.on_create_widget = function (callback) {
            this._create_widget_callback = callback;
        };

        WidgetManager.prototype._handle_create_widget = function (widget_model) {
            if (this._create_widget_callback) {
                try {
                    this._create_widget_callback(widget_model);
                } catch (e) {
                    console.log("Exception in WidgetManager callback", e, widget_model);
                }
            }
        };

        WidgetManager.prototype._handle_comm_open = function (comm, msg) {
            var widget_type_name = msg.content.target_name;
            var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
            this._model_instances[comm.comm_id] = widget_model; // comm_id == model_id
            this._handle_create_widget(widget_model);
        };

        //--------------------------------------------------------------------
        // Init code
        //--------------------------------------------------------------------
        IPython.WidgetManager = WidgetManager;
        if (IPython.widget_manager === undefined || IPython.widget_manager === null) {
            IPython.widget_manager = new WidgetManager();
        }

        return IPython.widget_manager;
    });
}());
<commit_msg>Missing view argument when recursively calling widgetmanager.callbacks(view)<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2013  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// WidgetModel, WidgetView, and WidgetManager
//============================================================================
/**
 * Base Widget classes
 * @module IPython
 * @namespace IPython
 * @submodule widget
 */

(function () {
    "use strict";

    // Use require.js 'define' method so that require.js is intelligent enough to
    // syncronously load everything within this file when it is being 'required'
    // elsewhere.
    define(["underscore",
             "backbone",
            ], function (underscore, backbone) {

        //--------------------------------------------------------------------
        // WidgetManager class
        //--------------------------------------------------------------------
        var WidgetManager = function () {
            this.comm_manager = null;
            this.widget_model_types = {};
            this.widget_view_types = {};
            this._model_instances = {};

            Backbone.sync = function (method, model, options, error) {
                var result = model._handle_sync(method, options);
                if (options.success) {
                  options.success(result);
                }
            };
        };

        WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
            this.comm_manager = comm_manager;

            // Register already-registered widget model types with the comm manager.
            for (var widget_model_name in this.widget_model_types) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
        };

        WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
            // Register the widget with the comm manager.  Make sure to pass this object's context
            // in so `this` works in the call back.
            if (this.comm_manager !== null) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
            this.widget_model_types[widget_model_name] = widget_model_type;
        };

        WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
            this.widget_view_types[widget_view_name] = widget_view_type;
        };

        WidgetManager.prototype.handle_msg = function(msg, model) {
            var method = msg.content.data.method;
            switch (method) {
                case 'display':
                    var cell = this.get_msg_cell(msg.parent_header.msg_id);
                    if (cell === null) {
                        console.log("Could not determine where the display" +
                            " message was from.  Widget will not be displayed");
                    } else {
                        var view = this.create_view(model, msg.content.data.view_name);
                        if (view !== undefined
                            && cell.widget_subarea !== undefined
                            && cell.widget_subarea !== null) {

                            view.cell = cell;
                            cell.widget_area.show();
                            cell.widget_subarea.append(view.$el);
                        }
                    }
                    break;
            }
        }

<<<<<<< HEAD
<<<<<<< HEAD
        WidgetManager.prototype.create_view = function(model, view_name, cell) {
=======
        WidgetManager.prototype.create_view = function(model, view_name, options) {
>>>>>>> Completely remove cell from model and view.
            view_name = view_name || model.get('default_view_name');
=======
    WidgetManager.prototype.create_view = function(model, view_name, cell, options) {
        view_name = view_name || model.get('default_view_name');
>>>>>>> Add widget view options in creating child views
            var ViewType = this.widget_view_types[view_name];
            if (ViewType !== undefined && ViewType !== null) {
                var view = new ViewType({model: model, widget_manager: this, options: options});
                view.render();
                model.views.push(view);
                model.on('destroy', view.remove, view);
<<<<<<< HEAD
                /*
                    // TODO: handle view deletion.  Don't forget to delete child views
                    var that = this;
                    view.$el.on("remove", function () {
                        var index = that.views.indexOf(view);
                        if (index > -1) {
                            that.views.splice(index, 1);
=======
        /*
                // TODO: handle view deletion.  Don't forget to delete child views
                var that = this;
                view.$el.on("remove", function () {
                    var index = that.views.indexOf(view);
                    if (index > -1) {
                        that.views.splice(index, 1);
                    }
                    view.remove(); // Clean-up view

                    // Close the comm if there are no views left.
                    if (that.views.length() === 0) {
            //trigger comm close event?
                        }

                        if (that.comm !== undefined) {
                            that.comm.close();
                            delete that.comm.model; // Delete ref so GC will collect widget model.
                            delete that.comm;
>>>>>>> Add widget view options in creating child views
                        }
                        view.remove(); // Clean-up view

                        // Close the comm if there are no views left.
                        if (that.views.length() === 0) {
                //trigger comm close event?
                            }

                            if (that.comm !== undefined) {
                                that.comm.close();
                                delete that.comm.model; // Delete ref so GC will collect widget model.
                                delete that.comm;
                            }
                            delete that.model_id; // Delete id from model so widget manager cleans up.
                        });
                */
                return view;
            }
        },

        WidgetManager.prototype.get_msg_cell = function (msg_id) {
            var cell = null;
            // First, check to see if the msg was triggered by cell execution.
            if (IPython.notebook !== undefined && IPython.notebook !== null) {
                cell = IPython.notebook.get_msg_cell(msg_id);
            }
            if (cell !== null) {
                return cell
            }
            // Second, check to see if a get_cell callback was defined
            // for the message.  get_cell callbacks are registered for
            // widget messages, so this block is actually checking to see if the
            // message was triggered by a widget.
            var kernel = this.get_kernel();
            if (kernel !== undefined && kernel !== null) {
                var callbacks = kernel.get_callbacks_for_msg(msg_id);
                if (callbacks !== undefined &&
                    callbacks.iopub !== undefined &&
                    callbacks.iopub.get_cell !== undefined) {

                    return callbacks.iopub.get_cell();
                }
            }

            // Not triggered by a cell or widget (no get_cell callback
            // exists).
            return null;
        };

        WidgetManager.prototype.callbacks = function (view) {
            // callback handlers specific a view
            var callbacks = {};
            var cell = view.cell;
            if (cell !== null) {
                // Try to get output handlers
                var handle_output = null;
                var handle_clear_output = null;
                if (cell.output_area !== undefined && cell.output_area !== null) {
                    handle_output = $.proxy(cell.output_area.handle_output, cell.output_area);
                    handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
                }

                // Create callback dict using what is known
                var that = this;
                callbacks = {
                    iopub : {
                        output : handle_output,
                        clear_output : handle_clear_output,

                        status : function (msg) {
                            view.model._handle_status(msg, that.callbacks(view));
                        },

                        // Special function only registered by widget messages.
                        // Allows us to get the cell for a message so we know
                        // where to add widgets if the code requires it.
                        get_cell : function () {
                            return cell;
                        },
                    },
                };
            }
            return callbacks;
        };

        WidgetManager.prototype.get_model = function (model_id) {
            var model = this._model_instances[model_id];
            if (model !== undefined && model.id == model_id) {
                return model;
            }
            return null;
        };

        WidgetManager.prototype.get_kernel = function () {
            if (this.comm_manager === null) {
                return null;
            } else {
                return this.comm_manager.kernel;
            }
        };

        WidgetManager.prototype.on_create_widget = function (callback) {
            this._create_widget_callback = callback;
        };

        WidgetManager.prototype._handle_create_widget = function (widget_model) {
            if (this._create_widget_callback) {
                try {
                    this._create_widget_callback(widget_model);
                } catch (e) {
                    console.log("Exception in WidgetManager callback", e, widget_model);
                }
            }
        };

        WidgetManager.prototype._handle_comm_open = function (comm, msg) {
            var widget_type_name = msg.content.target_name;
            var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
            this._model_instances[comm.comm_id] = widget_model; // comm_id == model_id
            this._handle_create_widget(widget_model);
        };

        //--------------------------------------------------------------------
        // Init code
        //--------------------------------------------------------------------
        IPython.WidgetManager = WidgetManager;
        if (IPython.widget_manager === undefined || IPython.widget_manager === null) {
            IPython.widget_manager = new WidgetManager();
        }

        return IPython.widget_manager;
    });
}());
<|endoftext|>


<commit_before>/*
 * grunt-bitbundler
 * https://github.com/MiguelCastillo/bit-bundler
 *
 * Copyright (c) 2015 Miguel Castillo
 * Licensed under the MIT license.
 */

"use strict";

var utils = require("belty");
var bitbundler = require("bit-bundler");
var path = require("path");

module.exports = function(grunt) {
  grunt.task.registerMultiTask("bitbundler", "bit bundler grunt plugin", function() {
    var settings = this.data.options || {};
    var done = this.async();

    var allFiles = this.files.reduce(function(container, files) {
      var outputFile = files.dest;
      var inputFiles = files.src.map(function(src) {
        return path.resolve(src);
      });

      bitbundler(utils.merge({files: inputFiles}, settings))
        .bundle(function(result) {
            grunt.file.write(outputFile, result);
            done();
          },
          function(err) {
            err = err && err.stack ? err.stack : err;
            grunt.log.error(err);
            done(err);
          });

      container.push({
        input: inputFiles,
        output: outputFile
      });

      return container;
    }, []);

    if (settings.stats === true) {
      grunt.log.writeln("Files processed:");
      grunt.log.writeln(JSON.stringify(allFiles));
    }
  });
};
<commit_msg>Added support for vendor bundle splitting<commit_after>/*
 * grunt-bitbundler
 * https://github.com/MiguelCastillo/bit-bundler
 *
 * Copyright (c) 2015 Miguel Castillo
 * Licensed under the MIT license.
 */

"use strict";

var utils = require("belty");
var bitbundler = require("bit-bundler");
var path = require("path");

module.exports = function(grunt) {
  grunt.task.registerMultiTask("bitbundler", "bit bundler grunt plugin", function() {
    var settings = this.data.options || {};
    var done = this.async();

    resolveFiles(this.files)
      .then(bundleFiles(settings))
      .then(bundleVendor(settings))
      .then(function() { done(); }, function(err) { logError(err); done(err); });

    function resolveFiles(files) {
      return Promise.all(files.map(resolveFile));
    }

    function resolveFile(file) {
      var src = file.src.map(function(src) {
        return path.resolve(src);
      });

      return {
        src: src,
        dest: file.dest
      };
    }

    function bundleFiles(settings) {
      return function(files) {
        return Promise.all(
          files
            .map(createBundler(settings))
            .map(runBundler)
        );
      };
    }

    function bundleVendor(settings) {
      return function(allBundles) {
        var vendorSettings = { splitVendor: false, browserPack: { hasExports: true } };
        return bundleFiles(vendorSettings)([getVendorFiles(allBundles, settings.splitVendor)]);
      };
    }

    function getVendorFiles(allBundles, dest) {
      var vendorFiles = allBundles
        .reduce(function(container, bundles) {
          return container.concat(bundles);
        }, [])
        .reduce(function(container, bundles) {
          return container.concat(bundles.vendor);
        }, [])
        .reduce(function(container, vendor) {
          container.push(vendor.name);
          return container;
        }, []);

      return {
        src: vendorFiles,
        dest: dest
      };
    }

    function createBundler(settings) {
      return function(file) {
        return {
          file: file,
          bundler: bitbundler(utils.merge({files: file.src}, settings))
        };
      };
    }

    function runBundler(settings) {
      function writeBundle(allBundles) {
        var concatOutput = allBundles.reduce(function(output, bundles) {
          return output + ";" + bundles.result;
        }, "");

        grunt.file.write(settings.file.dest, concatOutput);
        return allBundles;
      }

      return settings.bundler.bundle().then(writeBundle);
    }

    function logError(err) {
      var errStr = err && err.stack || err;
      grunt.log.error(errStr);
      return err;
    }

  });
};
<|endoftext|>


<commit_before>/*******************************
             Set-up
*******************************/

var
  // npm dependencies
  extend          = require('extend'),
  fs              = require('fs'),
  path            = require('path'),
  requireDotFile  = require('require-dot-file'),

  // semantic.json defaults
  defaults        = require('./defaults'),
  config          = require('./project/config'),

  // final config object
  userConfig
;

/*******************************
          User Config
*******************************/

try {
  // looks for config file across all parent directories
  userConfig = requireDotFile('semantic.json');
}
catch(error) {
  if(error.code === 'MODULE_NOT_FOUND') {
    console.error('No semantic.json config found');
  }
}

if(!userConfig) {
  // No semantic.json file use tasks/config/defaults.js
  console.error('Using default values for gulp');
  userConfig = defaults;
}
else {
  // extend defaults using shallow copy
  userConfig = extend(false, {}, defaults, userConfig);
}

/*******************************
       Add Derived Values
*******************************/

// adds additional derived values to config
userConfig = config.addDerivedValues(userConfig);

/*******************************
             Export
*******************************/

module.exports = userConfig;<commit_msg>more debug<commit_after>/*******************************
             Set-up
*******************************/

var
  // npm dependencies
  extend          = require('extend'),
  fs              = require('fs'),
  path            = require('path'),
  requireDotFile  = require('require-dot-file'),

  // semantic.json defaults
  defaults        = require('./defaults'),
  config          = require('./project/config'),

  // final config object
  userConfig
;

console.log(defaults);

/*******************************
          User Config
*******************************/

try {
  // looks for config file across all parent directories
  userConfig = requireDotFile('semantic.json');
}
catch(error) {
  if(error.code === 'MODULE_NOT_FOUND') {
    console.error('No semantic.json config found');
  }
}

if(!userConfig) {
  // No semantic.json file use tasks/config/defaults.js
  console.error('Using default values for gulp');
  userConfig = defaults;
}
else {
  // extend defaults using shallow copy
  userConfig = extend(false, {}, defaults, userConfig);
}

/*******************************
       Add Derived Values
*******************************/

// adds additional derived values to config
userConfig = config.addDerivedValues(userConfig);

/*******************************
             Export
*******************************/

module.exports = userConfig;

console.log(defaults);
<|endoftext|>


<commit_before>/*jshint node:true */
var FruitLoops = require('fruit-loops'),
    Mocha = require('mocha'),
    Sinon = require('sinon'),
    expect = require('expect.js'),
    path = require('path');

module.exports = function(grunt) {
  grunt.registerTask('fruit-loops:test', function() {
    var done = this.async();

    var page = FruitLoops.page({
      index: __dirname + '/../build/dev/fruit-loops/test.html',
      evil: true,

      resolver: function(href, window) {
        if (!/-server/.test(href)) {
          href = href.replace(/\.js$/, '-server.js');
        }
        return path.resolve(__dirname + '/../build/dev/fruit-loops/', href);
      },
      beforeExec: function(page, next) {
        page.window.Mocha = Mocha;
        page.window.mocha = createMocha(page.window);
        page.window.sinon = Sinon;
        page.window.expect = expect;

        var grep = grunt.option('grep');
        if (grep) {
          page.window.mocha.grep(grep);
        }

        next();
      },
      callback: function(err, data) {
        if (err) {
          throw err;
        } else if (!page.window.mochaResults) {
          throw new Error('Fruit Loops tests terminated early');
        } else if (page.window.mochaResults.reports.length) {
          throw new Error(page.window.mochaResults.reports.length + ' failed tests');
        } else {
          done();
        }
      }
    });
  });
};

function createMocha(global) {
  var mocha = new Mocha({reporter: 'dot'});

  /**
   * Override ui to ensure that the ui functions are initialized.
   * Normally this would happen in Mocha.prototype.loadFiles.
   */

  mocha.ui = function(ui){
    Mocha.prototype.ui.call(this, ui);
    this.suite.emit('pre-require', global, null, this);
    return this;
  };

  /**
   * Setup mocha with the given setting options.
   */

  mocha.setup = function(opts){
    if ('string' == typeof opts) {
      opts = { ui: opts };
    }
    for (var opt in opts) {
      this[opt](opts[opt]);
    }
    return this;
  };

  /**
   * Run mocha, returning the Runner.
   */

  mocha.run = function(fn){
    return Mocha.prototype.run.call(mocha, function() {
      // Have to manually emit as mocha will use the process async methods rather than the
      // window's so events emit will cause early termination.
      global.emit();

      fn && fn();
    });
  };
  return mocha;
}
<commit_msg>Fix fruit loops error handling<commit_after>/*jshint node:true */
var FruitLoops = require('fruit-loops'),
    Mocha = require('mocha'),
    Sinon = require('sinon'),
    expect = require('expect.js'),
    path = require('path');

module.exports = function(grunt) {
  grunt.registerTask('fruit-loops:test', function() {
    var done = this.async();

    var _error = console.error;
    console.error = console.log;

    var page = FruitLoops.page({
      index: __dirname + '/../build/dev/fruit-loops/test.html',
      evil: true,

      resolver: function(href, window) {
        if (!/-server/.test(href)) {
          href = href.replace(/\.js$/, '-server.js');
        }
        return path.resolve(__dirname + '/../build/dev/fruit-loops/', href);
      },
      beforeExec: function(page, next) {
        page.window.Mocha = Mocha;
        page.window.mocha = createMocha(page.window);
        page.window.sinon = Sinon;
        page.window.expect = expect;

        // NOP emit so tests of that functionality don't cause early termination
        page.window.emit = function() {};

        var grep = grunt.option('grep');
        if (grep) {
          page.window.mocha.grep(grep);
        }

        next();
      },
      callback: function(err, data) {
        console.error = _error;

        if (err) {
          done(err);
        } else if (!page.window.mochaResults) {
          done(new Error('Fruit Loops tests terminated early'));
        } else if (page.window.mochaResults.reports.length) {
          done(new Error(page.window.mochaResults.reports.length + ' failed tests'));
        } else {
          done();
        }
      }
    });
  });
};

function createMocha(global) {
  var mocha = new Mocha({reporter: 'dot'}),
      emit = global.emit;

  /**
   * Override ui to ensure that the ui functions are initialized.
   * Normally this would happen in Mocha.prototype.loadFiles.
   */

  mocha.ui = function(ui){
    Mocha.prototype.ui.call(this, ui);
    this.suite.emit('pre-require', global, null, this);
    return this;
  };

  /**
   * Setup mocha with the given setting options.
   */

  mocha.setup = function(opts){
    if ('string' == typeof opts) {
      opts = { ui: opts };
    }
    for (var opt in opts) {
      this[opt](opts[opt]);
    }
    return this;
  };

  /**
   * Run mocha, returning the Runner.
   */

  mocha.run = function(fn){
    return Mocha.prototype.run.call(mocha, function() {
      // Have to manually emit as mocha will use the process async methods rather than the
      // window's so events emit will cause early termination.
      emit.call(global);

      fn && fn();
    });
  };
  return mocha;
}
<|endoftext|>