<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
;(function(w, $, TweenMax, TimelineLite, Power2, Quad) {
    'use strict';

    var $article_wrapper = $('#article-wrapper');
    var article_height = 820;
    var parallax_offset = 142;
    var phone_offset = 200; // distance from top of article to top of phone
    var phone_speed = 400; // ms phone movement speed between articles

    var $giantfox = $('#giantfox');
    var $giantfox_tail = $('#giantfox-foreground');
    var $phone = $('#phone-common');
    var $phone_android = $('#phone-android');
    var $overview = $('#overview');
    var $os = $('#os');
    var $marketplace = $('#marketplace');
    var $android = $('#android');

    // i heard document.ready isn't necessary anymore. just trying it out...
    //$(document).ready(function () {
        // set phone position (needs to be in style object for retrieval later)
        $phone.css('left', '50%');

        // set up foxtail sprite animation
        $('#foxtail').sprite({fps: 12, no_of_frames: 44, rewind: true});

        // Smooth scroll-to for left menu navigation
        $('#partner-menu a, #nav-main-menu a, a.nav').click(function(e) {
            e.preventDefault();

            var elementClicked = $(this).attr("href");
            var destination;

            // all <article>'s have set height and position
            switch (elementClicked) {
                case '#overview':
                    destination = 0;
                    break;
                case '#os':
                    destination = (article_height - parallax_offset);
                    break;
                case '#marketplace':
                    destination = ((article_height * 2) - (parallax_offset * 2));
                    break;
                case '#android':
                    destination = ((article_height * 3) - (parallax_offset * 3));
                    break;
            }

            // reset phone & giantfox
            $phone.animate({ 'left': '50%' }, phone_speed);
            $phone_android.animate({ 'left': '50%' }, phone_speed);
            $giantfox.css('left', '45%');

            // force all first sections to be current
            $('.partner-article').each(function(i, article) {
                $(article).attr('data-section', $(article).find('section:first').attr('id'));
                $(article).find('section').each(function(j, section) {
                    $(section).css('left', (j * 100) + '%').attr('data-current', ((j === 0) ? 1 : 0));
                });
            });

            $("body:not(:animated)").animate({ scrollTop: destination }, 1000);

            return false;
        });

        // fix for loading page with anchor in URL
        $(function() {
            setTimeout(function() {
                if (w.location.hash) {
                    $article_wrapper.animate({ scrollTop: 0 }, 100, function() {
                        $('#partner-nav a[href="' + window.location.hash + '"]').trigger('click');
                        w.location.hash = '';
                    });
                }
            }, 60); // may need to increase timeout
        });

        // move form out of overlay
        var $form = $('#form').detach();
        $article_wrapper.after($form);

        // activate form drawer
        $('#toggle-form').on('click', function() {
            var $menu = $('#overlay-menu');

            $menu.toggleClass('form-open');

            if (!$menu.hasClass('form-open')) {
                $.pageslide.close();
            }
        }).pageslide({
            direction: 'left',
            modal: true,
            speed: 300
        });

        // side scrolling sections
        $('.view-section').on('click', function(e) {
            e.preventDefault();

            // needed to calculate percentage offsets?
            var doc_width = $(w.document).width();

            var link = $(this);

            var article = link.parents('article:first');

            // which section is currently displayed?
            var orig = article.find('section[data-current="1"]:first');
            var orig_pos = Number(orig.data('pos'));

            // which section are we going to?
            var dest = $('#' + link.data('section'));
            var dest_pos = Number(dest.data('pos'));

            // what's the difference in position? multiply by 100 to get percentage
            var delta = (dest_pos - orig_pos) * 100;

            article.find('section').each(function(i, el) {
                var section = $(el);

                // percentage position of this section
                // (left will be in px and will be multiple of doc_width)
                var el_left = (section.position().left/doc_width) * 100;

                // make sure we round to the nearest 100
                var new_left = Math.round((el_left - delta)/100)*100;

                section.css('left', new_left + '%').attr('data-current', 0);
            });

            // update current section
            dest.attr('data-current', 1);

            // update parent article selector
            article.attr('data-section', dest.attr('id'));

            // which phone should we move?
            var $cur_phone = (article.attr('id') === 'android') ? $phone_android : $phone;

            // slide phone?
            if (dest_pos > 1) {
                $cur_phone.stop().animate({ 'left': '-50%' }, 500);
            } else {
                $cur_phone.stop().animate({ 'left': '50%' }, 500);
            }
        });

        $('a[data-section="os-operators"]').on('click', function() {
            $giantfox.css('left', '-45%');
        });

        $('a[data-section="os-overview"]').on('click', function() {
            $giantfox.css('left', '45%');
        });

        var _move_phone = function(factor, slide, new_z) {
            // chaining animations gets too crazy
            // make sure only one animation is running/queued at one time
            if ($phone.is(':animated')) {
                $phone.stop();

                // if phone is inbetween hiding/showing, force that to finish
                if (Number($phone.attr('data-hiding')) === 1) {
                    $phone.css('left', '-50%');
                    $phone.attr('data-hiding', 0);
                } else if (Number($phone.attr('data-showing')) === 1) {
                    $phone.css('left', '50%');
                    $phone.attr('data-showing', 0);
                }
            }

            $('body').attr('data-article', slide.attr('id'));

            $('#partner-menu li').removeClass('active');
            $('#partner-menu li[id="menu-' + slide.attr('id') + '"]').addClass('active');

            // when jumping more than one section with nav, phone may
            // not make it all the way to -50%
            var cur_left = $phone[0].style.left;
            var visible = (cur_left === '50%');

            var top_pos = ((article_height * factor) - (parallax_offset * factor)) + phone_offset;

            // scrolling to android slide should never affect standard phone's left or z-index
            if (slide.attr('id') === 'android') {
                $phone.animate({ 'top': top_pos + 'px' }, phone_speed);
            } else {
                // would like to abstract this more, but each scenario requires specific sequencing
                if (Number(slide.find('section:first').attr('data-current')) === 1) {
                    if (!visible) {
                        if (new_z) {
                            $phone.css('z-index', new_z);
                        }

                        $phone.animate({
                            top: top_pos
                        }, 100, function() {
                            $phone.attr('data-showing', 1);
                            $phone.animate({ 'left': '50%' }, phone_speed, function() {
                                $phone.attr('data-showing', 0);
                            });
                        });
                    } else {
                        $phone.animate({ 'top': top_pos + 'px' }, phone_speed, function() {
                            if (new_z) {
                                $phone.css('z-index', new_z);
                            }
                        });
                    }
                } else {
                    if (visible) {
                        $phone.attr('data-hiding', 1);
                        $phone.animate({
                            'left': '-50%'
                        }, phone_speed, function() {
                            $phone.attr('data-hiding', 0);
                            $phone.css('top', top_pos + 'px');

                            if (new_z) {
                                $phone.css('z-index', new_z);
                            }
                        });
                    } else {
                        if (new_z) {
                            $phone.css('z-index', new_z);
                        }

                        $phone.animate({ 'top': top_pos + 'px' }, phone_speed);
                    }
                }
            }
        };

        var controller = $.superscrollorama();

        var tweens = {};

        tweens.slide_up = {
            from: {
                css: { top: 120, opacity: 0 },
                immediateRender: true
            },
            to: { css: { top: 0, opacity: 1 } }
        };

        tweens.article_overview = {
            from: {
                css: { top: 0 },
                immediateRender: true
            },
            to: {
                css: { top: 0 },
                onComplete: function() {
                    //console.log('overview complete');
                },
                onReverseComplete: function() {
                    //console.log('overview rev complete');
                    _move_phone(0, $overview);
                }
            }
        };

        tweens.article_os = {
            from: {
                css: { top: 0, ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-1) },
                onStart: function() {
                    $phone.css('z-index', 110);
                },
                onComplete: function() {
                    //console.log('os complete');
                    _move_phone(1, $os);
                },
                onReverseComplete: function() {
                    //console.log('os rev complete');
                    _move_phone(0, $overview);
                }
            }
        };

        tweens.article_marketplace = {
            from: {
                css: { top: (parallax_offset*-1), ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-2) },
                onStart: function() {
                    $phone.css('z-index', 120);
                },
                onComplete: function() {
                    //console.log('marketplace complete');
                    _move_phone(2, $marketplace);
                },
                onReverseComplete: function() {
                    //console.log('marketplace rev complete');
                    _move_phone(1, $os, 110);
                }
            }
        };

        tweens.article_android = {
            from: {
                css: { top: (parallax_offset*-2), ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-3) },
                onComplete: function() {
                    //console.log('android complete');
                    _move_phone(3, $android);
                    $phone_android.addClass('android-phone-visible');
                },
                onReverseComplete: function() {
                    //console.log('android rev complete');
                    _move_phone(2, $marketplace);
                    $phone_android.removeClass('android-phone-visible');
                }
            }
        };

        var prev_article = '#overview';

        $('.partner-article').each(function(i, article) {
            var $article = $(article);

            var my_tweens = [], tween, $tweener;

            var dur = ($article.attr('id') === 'overview') ? 1.6 : 0.5;

            //if ($article.attr('id') !== 'overview') {
                tween = TweenMax.fromTo(
                    $article,
                    dur,
                    tweens['article_' + $article.attr('id')].from,
                    tweens['article_' + $article.attr('id')].to
                );

                my_tweens.push(tween);
            //}

            // build tween for each element in $article with class of tween
            $article.find('.tween').each(function(i, tweener) {
                $tweener = $(tweener);

                tween = TweenMax.fromTo(
                    $tweener,
                    0.6,
                    tweens.slide_up.from,
                    tweens.slide_up.to
                );

                my_tweens.push(tween);
            });

            if (my_tweens.length > 0) {
                controller.addTween(
                    prev_article,
                    (new TimelineLite()).append(my_tweens),
                    300, // scroll duration
                    600 // start offset
                );
            }

            if ($article.attr('id') !== 'overview') {
                prev_article = '#' + $article.attr('id');
            }
        });
    //});
})(window, window.jQuery, window.TweenMax, window.TimelineLite, window.Power2, window.Quad);

<commit_msg>Fixed FF nav click bug<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
;(function(w, $, TweenMax, TimelineLite, Power2, Quad) {
    'use strict';

    var $article_wrapper = $('#article-wrapper');
    var article_height = 820;
    var parallax_offset = 142;
    var phone_offset = 200; // distance from top of article to top of phone
    var phone_speed = 400; // ms phone movement speed between articles

    var $giantfox = $('#giantfox');
    var $giantfox_tail = $('#giantfox-foreground');
    var $phone = $('#phone-common');
    var $phone_android = $('#phone-android');
    var $overview = $('#overview');
    var $os = $('#os');
    var $marketplace = $('#marketplace');
    var $android = $('#android');

    // i heard document.ready isn't necessary anymore. just trying it out...
    //$(document).ready(function () {
        // set phone position (needs to be in style object for retrieval later)
        $phone.css('left', '50%');

        // set up foxtail sprite animation
        $('#foxtail').sprite({fps: 12, no_of_frames: 44, rewind: true});

        // Smooth scroll-to for left menu navigation
        $('#partner-menu a, #nav-main-menu a, a.nav').click(function(e) {
            var elementClicked = $(this).attr("href");
            var destination;

            // all <article>'s have set height and position
            switch (elementClicked) {
                case '#overview':
                    destination = 0;
                    break;
                case '#os':
                    destination = (article_height - parallax_offset);
                    break;
                case '#marketplace':
                    destination = ((article_height * 2) - (parallax_offset * 2));
                    break;
                case '#android':
                    destination = ((article_height * 3) - (parallax_offset * 3));
                    break;
            }

            // reset phone & giantfox
            $phone.animate({ 'left': '50%' }, phone_speed);
            $phone_android.animate({ 'left': '50%' }, phone_speed);
            $giantfox.css('left', '45%');

            // force all first sections to be current
            $('.partner-article').each(function(i, article) {
                $(article).attr('data-section', $(article).find('section:first').attr('id'));
                $(article).find('section').each(function(j, section) {
                    $(section).css('left', (j * 100) + '%').attr('data-current', ((j === 0) ? 1 : 0));
                });
            });

            $("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination }, 1000);

            return false;
        });

        // fix for loading page with anchor in URL
        $(function() {
            setTimeout(function() {
                if (w.location.hash) {
                    $article_wrapper.animate({ scrollTop: 0 }, 100, function() {
                        $('#partner-nav a[href="' + window.location.hash + '"]').trigger('click');
                        w.location.hash = '';
                    });
                }
            }, 60); // may need to increase timeout
        });

        // move form out of overlay
        var $form = $('#form').detach();
        $article_wrapper.after($form);

        // activate form drawer
        $('#toggle-form').on('click', function() {
            var $menu = $('#overlay-menu');

            $menu.toggleClass('form-open');

            if (!$menu.hasClass('form-open')) {
                $.pageslide.close();
            }
        }).pageslide({
            direction: 'left',
            modal: true,
            speed: 300
        });

        // side scrolling sections
        $('.view-section').on('click', function(e) {
            e.preventDefault();

            // needed to calculate percentage offsets?
            var doc_width = $(w.document).width();

            var link = $(this);

            var article = link.parents('article:first');

            // which section is currently displayed?
            var orig = article.find('section[data-current="1"]:first');
            var orig_pos = Number(orig.data('pos'));

            // which section are we going to?
            var dest = $('#' + link.data('section'));
            var dest_pos = Number(dest.data('pos'));

            // what's the difference in position? multiply by 100 to get percentage
            var delta = (dest_pos - orig_pos) * 100;

            article.find('section').each(function(i, el) {
                var section = $(el);

                // percentage position of this section
                // (left will be in px and will be multiple of doc_width)
                var el_left = (section.position().left/doc_width) * 100;

                // make sure we round to the nearest 100
                var new_left = Math.round((el_left - delta)/100)*100;

                section.css('left', new_left + '%').attr('data-current', 0);
            });

            // update current section
            dest.attr('data-current', 1);

            // update parent article selector
            article.attr('data-section', dest.attr('id'));

            // which phone should we move?
            var $cur_phone = (article.attr('id') === 'android') ? $phone_android : $phone;

            // slide phone?
            if (dest_pos > 1) {
                $cur_phone.stop().animate({ 'left': '-50%' }, 500);
            } else {
                $cur_phone.stop().animate({ 'left': '50%' }, 500);
            }
        });

        $('a[data-section="os-operators"]').on('click', function() {
            $giantfox.css('left', '-45%');
        });

        $('a[data-section="os-overview"]').on('click', function() {
            $giantfox.css('left', '45%');
        });

        var _move_phone = function(factor, slide, new_z) {
            // chaining animations gets too crazy
            // make sure only one animation is running/queued at one time
            if ($phone.is(':animated')) {
                $phone.stop();

                // if phone is inbetween hiding/showing, force that to finish
                if (Number($phone.attr('data-hiding')) === 1) {
                    $phone.css('left', '-50%');
                    $phone.attr('data-hiding', 0);
                } else if (Number($phone.attr('data-showing')) === 1) {
                    $phone.css('left', '50%');
                    $phone.attr('data-showing', 0);
                }
            }

            $('body').attr('data-article', slide.attr('id'));

            $('#partner-menu li').removeClass('active');
            $('#partner-menu li[id="menu-' + slide.attr('id') + '"]').addClass('active');

            // when jumping more than one section with nav, phone may
            // not make it all the way to -50%
            var cur_left = $phone[0].style.left;
            var visible = (cur_left === '50%');

            var top_pos = ((article_height * factor) - (parallax_offset * factor)) + phone_offset;

            // scrolling to android slide should never affect standard phone's left or z-index
            if (slide.attr('id') === 'android') {
                $phone.animate({ 'top': top_pos + 'px' }, phone_speed);
            } else {
                // would like to abstract this more, but each scenario requires specific sequencing
                if (Number(slide.find('section:first').attr('data-current')) === 1) {
                    if (!visible) {
                        if (new_z) {
                            $phone.css('z-index', new_z);
                        }

                        $phone.animate({
                            top: top_pos
                        }, 100, function() {
                            $phone.attr('data-showing', 1);
                            $phone.animate({ 'left': '50%' }, phone_speed, function() {
                                $phone.attr('data-showing', 0);
                            });
                        });
                    } else {
                        $phone.animate({ 'top': top_pos + 'px' }, phone_speed, function() {
                            if (new_z) {
                                $phone.css('z-index', new_z);
                            }
                        });
                    }
                } else {
                    if (visible) {
                        $phone.attr('data-hiding', 1);
                        $phone.animate({
                            'left': '-50%'
                        }, phone_speed, function() {
                            $phone.attr('data-hiding', 0);
                            $phone.css('top', top_pos + 'px');

                            if (new_z) {
                                $phone.css('z-index', new_z);
                            }
                        });
                    } else {
                        if (new_z) {
                            $phone.css('z-index', new_z);
                        }

                        $phone.animate({ 'top': top_pos + 'px' }, phone_speed);
                    }
                }
            }
        };

        var controller = $.superscrollorama();

        var tweens = {};

        tweens.slide_up = {
            from: {
                css: { top: 120, opacity: 0 },
                immediateRender: true
            },
            to: { css: { top: 0, opacity: 1 } }
        };

        tweens.article_overview = {
            from: {
                css: { top: 0 },
                immediateRender: true
            },
            to: {
                css: { top: 0 },
                onComplete: function() {
                    //console.log('overview complete');
                },
                onReverseComplete: function() {
                    //console.log('overview rev complete');
                    _move_phone(0, $overview);
                }
            }
        };

        tweens.article_os = {
            from: {
                css: { top: 0, ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-1) },
                onStart: function() {
                    $phone.css('z-index', 110);
                },
                onComplete: function() {
                    //console.log('os complete');
                    _move_phone(1, $os);
                },
                onReverseComplete: function() {
                    //console.log('os rev complete');
                    _move_phone(0, $overview);
                }
            }
        };

        tweens.article_marketplace = {
            from: {
                css: { top: (parallax_offset*-1), ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-2) },
                onStart: function() {
                    $phone.css('z-index', 120);
                },
                onComplete: function() {
                    //console.log('marketplace complete');
                    _move_phone(2, $marketplace);
                },
                onReverseComplete: function() {
                    //console.log('marketplace rev complete');
                    _move_phone(1, $os, 110);
                }
            }
        };

        tweens.article_android = {
            from: {
                css: { top: (parallax_offset*-2), ease: Power2.easeOut },
                immediateRender: true
            },
            to: {
                css: { top: (parallax_offset*-3) },
                onComplete: function() {
                    //console.log('android complete');
                    _move_phone(3, $android);
                    $phone_android.addClass('android-phone-visible');
                },
                onReverseComplete: function() {
                    //console.log('android rev complete');
                    _move_phone(2, $marketplace);
                    $phone_android.removeClass('android-phone-visible');
                }
            }
        };

        var prev_article = '#overview';

        $('.partner-article').each(function(i, article) {
            var $article = $(article);

            var my_tweens = [], tween, $tweener;

            var dur = ($article.attr('id') === 'overview') ? 1.6 : 0.5;

            //if ($article.attr('id') !== 'overview') {
                tween = TweenMax.fromTo(
                    $article,
                    dur,
                    tweens['article_' + $article.attr('id')].from,
                    tweens['article_' + $article.attr('id')].to
                );

                my_tweens.push(tween);
            //}

            // build tween for each element in $article with class of tween
            $article.find('.tween').each(function(i, tweener) {
                $tweener = $(tweener);

                tween = TweenMax.fromTo(
                    $tweener,
                    0.6,
                    tweens.slide_up.from,
                    tweens.slide_up.to
                );

                my_tweens.push(tween);
            });

            if (my_tweens.length > 0) {
                controller.addTween(
                    prev_article,
                    (new TimelineLite()).append(my_tweens),
                    300, // scroll duration
                    600 // start offset
                );
            }

            if ($article.attr('id') !== 'overview') {
                prev_article = '#' + $article.attr('id');
            }
        });
    //});
})(window, window.jQuery, window.TweenMax, window.TimelineLite, window.Power2, window.Quad);

<|endoftext|>


<commit_before>import React from 'react';
import { Launchers } from 'stockflux-core';
import Components from 'stockflux-components';

export default ({ symbol, name, small, disabled, intentsEnabled }) => {
  return (
    <Components.Buttons.Round
      className="shortcut watchlist"
      onClick={() => Launchers.launchWatchlist(symbol, name, intentsEnabled)}
      disabled={disabled}
      small={small}
    >
      <Components.Icons.Launcher.WatchlistIcon />
    </Components.Buttons.Round>
  );
};
<commit_msg>Deleted unused shortcut<commit_after><|endoftext|>


<commit_before>import Ember from 'ember';
var inject = Ember.inject;

import AuthenticateRoute from 'wholetale/routes/authenticate';
import RSVP from 'rsvp';

const Deferred = function() {
  let resolve = null;
  let reject = null;

  let promise = new RSVP.Promise((_resolve, _reject) => {
      resolve = _resolve;
      reject = _reject;
  });

  return {
      resolve: resolve,
      reject: reject,
      promise: promise
  };
};

export default AuthenticateRoute.extend({
  internalState: inject.service(),
  userAuth: inject.service(),
  folderNavs: inject.service(),

  model: function () {
    this._super();

    const self = this;

    var state = this.get('internalState');

    var thisUserID = this.get('userAuth').getCurrentUserID();

    console.log("The user id is = " + thisUserID);
    console.log(thisUserID);

    var folderID = state.getCurrentFolderID();

    console.log("loading the route for the index again");
    console.log("Folder ID: " + folderID);

    var folderContents = {};
    var itemContents = Deferred();

    if (!folderID || folderID === "null") {
      let nav = this.get('folderNavs').getFolderNavFor('home');
      folderContents = this.get('store').query('folder', {
        parentId: nav.parentId,
        parentType: nav.parentType,
        name: nav.name,
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).then(folders => {
        if (folders.length) {
          let folder_id = folders.content[0].id;

          state.setCurrentFolderID(folder_id);
          state.setCurrentParentId(nav.parentId);
          state.setCurrentParentType(nav.parentType);
          state.setCurrentFolderName(nav.name);

          itemContents.resolve(self.store.query('item', {
            folderId: folder_id,
            reload: true,
            adapterOptions: {
              queryParams: {
                limit: "0"
              }
            }
          }));

          return self.store.query('folder', {
            "parentId": folder_id,
            "parentType": "folder"
          });
        }
      });
    } else {
      console.log("Folder != null, so loading folder and items");
      folderContents = this.get('store').query('folder', {
        parentId: folderID,
        parentType: 'folder',
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      });
      itemContents.resolve(this.get('store').query('item', {
        folderId: folderID,
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }));
      console.log("Folder != null, leaving");
    }
    return RSVP.hash({
      folderContents: folderContents,
      itemContents: itemContents.promise,
      images: this.get('store').findAll('image', {
        reload: true,
        adapterOptions: {
          queryParams: {
            sort: "lowerName",
            sortdir: "1",
            limit: "50"
          }
        }
      })
    });
  },

  setupController: function (controller, model) {
    this._super(controller, model);
    controller.set('fileData', { folderContents: model.folderContents, itemContents: model.itemContents});
  }
});
<commit_msg>Catch when folders don't exist<commit_after>import Ember from 'ember';
var inject = Ember.inject;

import AuthenticateRoute from 'wholetale/routes/authenticate';
import RSVP from 'rsvp';

const Deferred = function() {
  let resolve = null;
  let reject = null;

  let promise = new RSVP.Promise((_resolve, _reject) => {
      resolve = _resolve;
      reject = _reject;
  });

  return {
      resolve: resolve,
      reject: reject,
      promise: promise
  };
};

export default AuthenticateRoute.extend({
  internalState: inject.service(),
  userAuth: inject.service(),
  folderNavs: inject.service(),

  model: function () {
    this._super();

    const self = this;

    var state = this.get('internalState');

    var thisUserID = this.get('userAuth').getCurrentUserID();

    console.log("The user id is = " + thisUserID);
    console.log(thisUserID);

    var folderID = state.getCurrentFolderID();

    console.log("loading the route for the index again");
    console.log("Folder ID: " + folderID);

    var folderContents = {};
    var itemContents = Deferred();
    if (!folderID || folderID === "null") {
      let nav = this.get('folderNavs').getFolderNavFor('home');
      folderContents = this.get('store').query('folder', {
        parentId: nav.parentId,
        parentType: nav.parentType,
        name: nav.name,
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).then(folders => {
        if (folders.length) {
          let folder_id = folders.content[0].id;

          state.setCurrentFolderID(folder_id);
          state.setCurrentParentId(nav.parentId);
          state.setCurrentParentType(nav.parentType);
          state.setCurrentFolderName(nav.name);

          itemContents.resolve(self.store.query('item', {
            folderId: folder_id,
            reload: true,
            adapterOptions: {
              queryParams: {
                limit: "0"
              }
            }
          }));

          return self.store.query('folder', {
            "parentId": folder_id,
            "parentType": "folder"
          });
        }
      });
    } else {
      folderContents = this.get('store').query('folder', {
        parentId: folderID,
        parentType: 'folder',
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).catch((err) => {
        console.log('Failed to get folder', err);
        return;
      });
      itemContents.resolve(this.get('store').query('item', {
        folderId: folderID,
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).catch((err) => {
        console.log('Failed to get items', err);
        return;
      }))
    }
    return RSVP.hash({
      folderContents: folderContents,
      itemContents: itemContents.promise,
      images: this.get('store').findAll('image', {
        reload: true,
        adapterOptions: {
          queryParams: {
            sort: "lowerName",
            sortdir: "1",
            limit: "50"
          }
        }
      })
    });
  },

  setupController: function (controller, model) {
    this._super(controller, model);
    controller.set('fileData', { folderContents: model.folderContents, itemContents: model.itemContents});
  }
});
<|endoftext|>


<commit_before>test( "hello test", function() {
    ok( 1 == "1", "Passed!" );
});

test("number constant test", function() {
    var result = evalPuma("1");
    ok( result.success && 1 === result.value, "Passed!" );
});

test("string constant test", function() {
    var result = evalPuma("\"Hello\"");
    ok( result.success && "Hello" === result.value, "Passed!" );
});

test("test division", function(){
    var result = evalPuma("2 / 2;");
    equal( result.value, 1, "Passed!");
});

test("arithmetic operations", function(){
    var result = evalPuma("1 + 1 * 2 << 2 >> 2 / 2;");
    equal( result.value, 1 + 1 * 2 << 2 >> 2 / 2, "Passed!");
});

test("basic function", function(){
    var result = evalPuma("function foo(){ return 1; } foo();");
    equal( result.value, 1, "Passed!");
});

test("basic function arguments", function(){
    var result = evalPuma("function foo(a, b){ return a + b; } foo(1, 2);");
    equal( result.value, 3, "Passed!");
});

test("basic function arguments with same name than local variables", function(){
    var result = evalPuma("var a = 2; var b = 3; function foo(a, b){ return a + b; } foo(1, 2);");
    equal( result.value, 3, "Passed!");
});

test("parent variable hidden by local variable", function(){
    var result = evalPuma("var a = 1; function foo(){ var a = 5; return a; } foo();");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("local variable function do not alias parent scope function", function(){
    var result = evalPuma("var a = 1; function foo(){ var a = 5; return a; } foo(); a;");
    result.makeValue();
    equal( result.value, 1, "Passed!");
});

test("parent variable accessed from local function", function(){
    var result = evalPuma("var a = 1; function foo(){ a = 5; return 2; } foo(); a;");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("parent variable accessed from local function", function(){
    var result = evalPuma("var a = 1; var b = 1; function foo(){ var a = 2; function foo2(){ a = 5; } foo2(); b = a; return 2; } foo(); b;");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("recursive function call", function(){
    var result = evalPuma("function recursive(a){ if(a>5) return a; else return recursive(a+1); } recursive(1);");
    equal(result.value, 6, "Passed!");
});

test("function that returns a function", function(){
    var result = evalPuma("function foo(){ function inner(){ return 2; } return inner; } foo()();");
    equal(result.value, 2, "Passed!");
});

test("return statement", function(){
    var result = evalPuma("function foo(){ return 1; return 2; } foo();");
    equal( result.value, 1, "Passed!");
});

test("for statement 1", function(){
    var result = evalPuma("for(var i=0;i<2;i=i+1) { j+=1; }");
    equal( result.value, 2, "Passed!");
});

/*
test("for statement 2", function(){
    var result = evalPuma("var b=true; for(var i=0;b;i=i+1) { if(i>5)b=false; j+=1; }");
    equal( result.value, 2, "Passed!");
});
*/<commit_msg>test for meta variable type count<commit_after>test( "hello test", function() {
    ok( 1 == "1", "Passed!" );
});

test("number constant test", function() {
    var result = evalPuma("1");
    ok( result.success && 1 === result.value, "Passed!" );
});

test("string constant test", function() {
    var result = evalPuma("\"Hello\"");
    ok( result.success && "Hello" === result.value, "Passed!" );
});

test("test division", function(){
    var result = evalPuma("2 / 2;");
    equal( result.value, 1, "Passed!");
});

test("arithmetic operations", function(){
    var result = evalPuma("1 + 1 * 2 << 2 >> 2 / 2;");
    equal( result.value, 1 + 1 * 2 << 2 >> 2 / 2, "Passed!");
});

test("basic function", function(){
    var result = evalPuma("function foo(){ return 1; } foo();");
    equal( result.value, 1, "Passed!");
});

test("basic function arguments", function(){
    var result = evalPuma("function foo(a, b){ return a + b; } foo(1, 2);");
    equal( result.value, 3, "Passed!");
});

test("basic function arguments with same name than local variables", function(){
    var result = evalPuma("var a = 2; var b = 3; function foo(a, b){ return a + b; } foo(1, 2);");
    equal( result.value, 3, "Passed!");
});

test("parent variable hidden by local variable", function(){
    var result = evalPuma("var a = 1; function foo(){ var a = 5; return a; } foo();");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("local variable function do not alias parent scope function", function(){
    var result = evalPuma("var a = 1; function foo(){ var a = 5; return a; } foo(); a;");
    result.makeValue();
    equal( result.value, 1, "Passed!");
});

test("parent variable accessed from local function", function(){
    var result = evalPuma("var a = 1; function foo(){ a = 5; return 2; } foo(); a;");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("parent variable accessed from local function", function(){
    var result = evalPuma("var a = 1; var b = 1; function foo(){ var a = 2; function foo2(){ a = 5; } foo2(); b = a; return 2; } foo(); b;");
    result.makeValue();
    equal( result.value, 5, "Passed!");
});

test("recursive function call", function(){
    var result = evalPuma("function recursive(a){ if(a>5) return a; else return recursive(a+1); } recursive(1);");
    equal(result.value, 6, "Passed!");
});

test("function that returns a function", function(){
    var result = evalPuma("function foo(){ function inner(){ return 2; } return inner; } foo()();");
    equal(result.value, 2, "Passed!");
});

test("return statement", function(){
    var result = evalPuma("function foo(){ return 1; return 2; } foo();");
    equal( result.value, 1, "Passed!");
});

test("for statement 1", function(){
    var result = evalPuma("for(var i=0;i<2;i=i+1) { j+=1; }");
    equal( result.value, 2, "Passed!");
});

/*
test("for statement 2", function(){
    var result = evalPuma("var b=true; for(var i=0;b;i=i+1) { if(i>5)b=false; j+=1; }");
    equal( result.value, 2, "Passed!");
});
*/

test("meta variables types counting", function(){
    var meta = evalPuma("var a; a = 1; a = \"hola\"; a = 2;").value.meta;
    equal( meta["number"], 2, "Passed!");
    equal( meta["string"], 1, "Passed!");
});
<|endoftext|>


<commit_before>"use strict";

const ActionBase = require('./action');

class TaskData {

  constructor(data) {
    if (typeof data !== "object") {
      throw new Error("Task initial data must be of type object.");
    }

    this.data = data;
  }

  get(selector) {
    let path = selector.split(".");
    let variable = this.data;

    for (let i = 0; i < path.length; i++) {
      if (!variable.hasOwnProperty(path[i])) {
        return null;
      }

      variable = variable[path[i]];
    }

    return variable;
  }

  set(selector, value) {
    let path = selector.split(".");
    let _data = this.data;

    for (let i = 0, l = path.length; i < l; i++) {
      let p = path[i];

      if (!_data.hasOwnProperty(p)) {
        if (i === l - 1) {
          _data[p] = value;
          break;
        } else {
          _data[p] = {};
        }
      } else if (i === l - 1) {
        _data[p] = value;
        break;
      }

      _data = _data[p];
    }
  }

}

module.exports = class Task {

  constructor(...actions) {
    this._references = {};
    this._actionStack = [];
    this._finalPromises = [];

    this._subTasks = [];

    if (!actions.length) {
      throw new Error("You must provide at-least one action for a task.");
    }

    this.then(...actions);
  }

  subTask() {
    let task = new Task("");
    task._references = this._references;
    task._actionStack = [];

    return task;
  }

  then(...actions) {
    this._actionStack.push({
      actions: actions,
    });

    return this;
  }

  after(reference, ...actions) {
    if (typeof reference === "string") {
      reference = [reference];
    }

    if (!Array.isArray(reference)) {
      throw new Error("After reference should be string or array of strings.");
    }

    let subTask = this.subTask();

    if (
      typeof actions[0] === "function" &&
      !(actions[0].prototype instanceof ActionBase)
    ) {
      actions[0](subTask);
    }
    else {
      subTask.then(...actions);
    }

    this._subTasks.push({
      references: reference,
      promises: [],
      task: subTask,
    });

    return this;
  }

  ifThen(condition, ...actions) {
    let subTask = this.subTask();

    if (typeof condition !== "function") {
      throw new Error("Task condition must be a function.");
    }

    if (
      typeof actions[0] === "function" &&
      !(actions[0].prototype instanceof ActionBase)
    ) {
      actions[0](subTask);
    }
    else {
      subTask.then(...actions);
    }

    this._lastIf = {
      condition: condition,
      actions: subTask,
    };

    this._actionStack.push(this._lastIf);

    return this;
  }

  otherwise(...actions) {
    if (!this._lastIf) {
      throw new Error("Otherwise can only be used after ifThen.");
    }

    this.ifThen(() => {}, ...actions);
    this._actionStack[this._actionStack.length - 1].condition = "otherwise";

    this._lastIf = null;

    return this;
  }

  start(initData) {
    this._data = initData instanceof TaskData ? initData : new TaskData(initData);

    let promise = Promise.all(
      this._processActions(this._actionStack.shift().actions)
    );

    let lastConditionStack;

    this._actionStack.forEach((stack) => {
      promise = promise.then(() => {
        if (stack.condition === "otherwise") {
          if (!lastConditionStack.passed) {
            return stack.actions.start(this._data);
          }

          lastConditionStack = null;
        }
        else if (stack.condition) {
          lastConditionStack = stack;
          lastConditionStack.passed = false;

          if (stack.condition(this._data)) {
            lastConditionStack.passed = true;
            return stack.actions.start(this._data);
          }
        }
        else {
          return Promise.all(this._processActions(stack.actions));
        }

        return Promise.resolve();
      });
    });

    return promise.then(() => {
      return Promise.all(this._finalPromises);
    }).then(() => this._data);
  }

  _addReferenceAction(reference, Action) {
    this._references[reference] = Action;

    this._subTasks.forEach((task) => {
      if (!task.references.length) {
        return;
      }

      let refIndex = task.references.indexOf(reference);
      if (refIndex === -1) {
        return;
      }

      task.promises.push(Action._promise);

      if (task.references.length === 1) {
        this._finalPromises.push(
          Promise.all(task.promises).then(() => {
            return task.task.start(this._data);
          })
        );
      }
      else {
        task.references.slice(refIndex, 1);
      }
    });

    return Action;
  }

  _processActions(actions) {
    let promises = [];

    actions.forEach((action) => {
      if (action.prototype instanceof ActionBase) {
        promises.push(new action(this._data)._promise);
        return;
      }

      switch (typeof action) {
        case "string":
          if (!this._references[action]) {
            throw new Error(`Referenced Action not found with key: ${action}`);
          }

          promises.push(this._references[action]._promise);
          break;
        case "object":
          for (let [reference, Action] of Object.entries(action)) {
            if (!(Action.prototype instanceof ActionBase)) {
              throw new Error(`Type of 'Action' expected, got '${typeof Action}': ${Action}`);
            }

            promises.push(
              this._addReferenceAction(reference, new Action(this._data))
            );
          }
          break;
        default:
          throw new Error(`Type of '${typeof action}' argument is unrecognized.`);
      }
    });

    return promises;
  }

};<commit_msg>Fixes reference bound actions not included in main promise.<commit_after>"use strict";

const ActionBase = require('./action');

class TaskData {

  constructor(data) {
    if (typeof data !== "object") {
      throw new Error("Task initial data must be of type object.");
    }

    this.data = data;
  }

  get(selector) {
    let path = selector.split(".");
    let variable = this.data;

    for (let i = 0; i < path.length; i++) {
      if (!variable.hasOwnProperty(path[i])) {
        return null;
      }

      variable = variable[path[i]];
    }

    return variable;
  }

  set(selector, value) {
    let path = selector.split(".");
    let _data = this.data;

    for (let i = 0, l = path.length; i < l; i++) {
      let p = path[i];

      if (!_data.hasOwnProperty(p)) {
        if (i === l - 1) {
          _data[p] = value;
          break;
        } else {
          _data[p] = {};
        }
      } else if (i === l - 1) {
        _data[p] = value;
        break;
      }

      _data = _data[p];
    }
  }

}

module.exports = class Task {

  constructor(...actions) {
    this._references = {};
    this._actionStack = [];
    this._finalPromises = [];

    this._subTasks = [];

    if (!actions.length) {
      throw new Error("You must provide at-least one action for a task.");
    }

    this.then(...actions);
  }

  subTask() {
    let task = new Task("");
    task._references = this._references;
    task._actionStack = [];

    return task;
  }

  then(...actions) {
    this._actionStack.push({
      actions: actions,
    });

    return this;
  }

  after(reference, ...actions) {
    if (typeof reference === "string") {
      reference = [reference];
    }

    if (!Array.isArray(reference)) {
      throw new Error("After reference should be string or array of strings.");
    }

    let subTask = this.subTask();

    if (
      typeof actions[0] === "function" &&
      !(actions[0].prototype instanceof ActionBase)
    ) {
      actions[0](subTask);
    }
    else {
      subTask.then(...actions);
    }

    this._subTasks.push({
      references: reference,
      promises: [],
      task: subTask,
    });

    return this;
  }

  ifThen(condition, ...actions) {
    let subTask = this.subTask();

    if (typeof condition !== "function") {
      throw new Error("Task condition must be a function.");
    }

    if (
      typeof actions[0] === "function" &&
      !(actions[0].prototype instanceof ActionBase)
    ) {
      actions[0](subTask);
    }
    else {
      subTask.then(...actions);
    }

    this._lastIf = {
      condition: condition,
      actions: subTask,
    };

    this._actionStack.push(this._lastIf);

    return this;
  }

  otherwise(...actions) {
    if (!this._lastIf) {
      throw new Error("Otherwise can only be used after ifThen.");
    }

    this.ifThen(() => {}, ...actions);
    this._actionStack[this._actionStack.length - 1].condition = "otherwise";

    this._lastIf = null;

    return this;
  }

  start(initData) {
    this._data = initData instanceof TaskData ? initData : new TaskData(initData);

    let promise = Promise.all(
      this._processActions(this._actionStack.shift().actions)
    );

    let lastConditionStack;

    this._actionStack.forEach((stack) => {
      promise = promise.then(() => {
        if (stack.condition === "otherwise") {
          if (!lastConditionStack.passed) {
            return stack.actions.start(this._data);
          }

          lastConditionStack = null;
        }
        else if (stack.condition) {
          lastConditionStack = stack;
          lastConditionStack.passed = false;

          if (stack.condition(this._data)) {
            lastConditionStack.passed = true;
            return stack.actions.start(this._data);
          }
        }
        else {
          return Promise.all(this._processActions(stack.actions));
        }

        return Promise.resolve();
      });
    });

    return promise.then(() => {
      return Promise.all(this._finalPromises);
    }).then(() => this._data);
  }

  _addReferenceAction(reference, Action) {
    this._references[reference] = Action;

    this._subTasks.forEach((task) => {
      if (!task.references.length) {
        return;
      }

      let refIndex = task.references.indexOf(reference);
      if (refIndex === -1) {
        return;
      }

      task.promises.push(Action._promise);
      task.references.splice(refIndex, 1);

      if (!task.references.length) {
        this._finalPromises.push(
          Promise.all(task.promises).then(() => {
            return task.task.start(this._data);
          })
        );
      }
    });

    return Action;
  }

  _processActions(actions) {
    let promises = [];

    actions.forEach((action) => {
      if (action.prototype instanceof ActionBase) {
        promises.push(new action(this._data)._promise);
        return;
      }

      switch (typeof action) {
        case "string":
          if (!this._references[action]) {
            throw new Error(`Referenced Action not found with key: ${action}`);
          }

          promises.push(this._references[action]._promise);
          break;
        case "object":
          for (let [reference, Action] of Object.entries(action)) {
            if (!(Action.prototype instanceof ActionBase)) {
              throw new Error(`Type of 'Action' expected, got '${typeof Action}': ${Action}`);
            }

            promises.push(
              this._addReferenceAction(reference, new Action(this._data))
            );
          }
          break;
        default:
          throw new Error(`Type of '${typeof action}' argument is unrecognized.`);
      }
    });

    return promises;
  }

};<|endoftext|>


<commit_before>/**
 * @fileOverview A test runner compliant to the
 * [CommonJS Unit Testing](http://wiki.commonjs.org/wiki/Unit_Testing/1.0)
 * specification. It manages the execution of unit tests and processes test results.
 * The runner reports the total number of failures as exit status code.
 *
 * The runner treats a module like a test case. A test case defines the fixture
 * to run multiple tests. Test cases can provide optional setUp() and
 * tearDown() functions to initialize and destroy the fixture. The
 * test runner will run these methods prior to / after each test.
 *
 * The following example test case testDatabase.js starts a
 * new test runner if executed with ringo testDatabase.js
 *
 * @example // testDatabase.js
 * exports.setUp = function() { ... open db connection ... }
 * exports.tearDown = function() { ... close db connection ... }
 *
 * exports.testCreateTable = function() { ... }
 * exports.testInsertData = function() { ... }
 * exports.testTransactions = function() { ... }
 * exports.testDeleteTable = function() { ... }
 *
 * if (require.main == module.id) {
 *   // Get a runner and run on the current module
 *   require("test").run(exports);
 * }
 *
 * @see The assert module is an
 * assertion library to write unit tests.
 */

var strings = require("ringo/utils/strings");
var term = require("ringo/term");
var fs = require("fs");

export(
    "run",
    "jsDump",
    "getStackTrace",
    "getType"
);

var {
    AssertionError,
    ArgumentsError
} = require("./assert");

/**
 * Converts the value passed as argument into a nicely formatted and
 * indented string
 * @param {Object} value The value to convert into a string
 * @param {Number} lvl Optional indentation level (defaults to zero)
 * @returns The string representation of the object passed as argument
 * @type String
 */
function jsDump(value, lvl) {
    if (!lvl) {
        lvl = 0;
    }

    switch (getType(value)) {
        case "string":
            return jsDump.quote(value);
        case "boolean":
        case "number":
        case "nan":
        case "date":
        case "regexp":
            return value.toString();
        case "undefined":
        case "null":
            return String(value);
        case "function":
            if (getType(value.name) === "string" && value.name.length > 0) {
                return value.name;
            }
            return value.toSource();
        case "array":
            var buf = value.map(function(val) {
                return jsDump.indent(lvl + 1) + jsDump(val, lvl + 1);
            });
            return ["[", buf.join(",\n"), jsDump.indent(lvl) + "]"].join("\n");
        case "object":
            var buf = [];
            for (var propName in value) {
                buf.push(jsDump.indent(lvl + 1) + '"' + propName + '": ' + jsDump(value[propName], lvl + 1));
            }
            return ["{", buf.join(",\n"), jsDump.indent(lvl) + "}"].join("\n");
        case "java":
            return '<java:' + value.class.name + '>';
    }
}
/**
 * @ignore
 */
jsDump.indent = function(lvl) {
    return strings.repeat("    ", lvl);
};

/**
 * @ignore
 */
jsDump.quote = function(str) {
    return JSON.stringify(str.toString());
};

/**
 * Returns the type of the object passed as argument.
 * @returns The type of the object passed as argument
 * @type String
 */
function getType(obj) {
    if (typeof(obj) === "string") {
        return "string";
    } else if (typeof(obj) === "boolean") {
        return "boolean";
    } else if (typeof (obj) === "number") {
        return (isNaN(obj) === true) ? "nan" : "number";
    } else if (typeof(obj) === "undefined") {
        return "undefined";
    } else if (obj === null) {
        return "null";
    } else if (obj instanceof Array) {
        return "array";
    } else if (obj instanceof Date) {
        return "date";
    } else if (obj instanceof RegExp) {
        return "regexp";
    } else if (obj instanceof Function) {
        return "function";
    } else if (obj instanceof java.lang.Object) {
        return "java";
    }
    return "object";
}

/**
 * Creates a stack trace and parses it for display.
 * @param {java.lang.StackTraceElement} trace The trace to parse. If not given
 * a stacktrace will be generated
 * @returns The parsed stack trace
 * @type String
 */
function getStackTrace(trace) {
    // create exception and fill in stack trace
    if (!trace) {
        var ex = new Packages.org.mozilla.javascript.EvaluatorException("");
        ex.fillInStackTrace();
        trace = ex.getScriptStack();
    }
    var stack = [];
    var el, fileName, lineNumber;
    for (var i = 0; i < trace.length; i += 1) {
        el = trace[i];
        if (el.fileName != null && el.lineNumber > -1) {
            // exclude all lines containing the unittest module itself
            // FIXME (ro): this is quite ugly, but it works ...
            if (el.fileName.indexOf(module.id) === 0 || el.fileName.indexOf("assert") === 0) {
                continue;
            }
            stack.push("at " + el.fileName + ":" + el.lineNumber);
        }
    }
    return stack;
};

/**
 * The main runner method. This method can be called with one, two or three
 * arguments: run(scope), run(scope, nameOfTest),
 * run(scope, writer) or run(scope, nameOfTest, writer)
 * @param {String|Object} scope Either the path to a module containing unit
 * tests to execute, or an object containing the exported test methods or nested scopes.
 * @param {String} name Optional name of a test method to execute
 * @param {Object} writer Optional writer to use for displaying the test results. Defaults
 * to TermWriter.
 */
function run(scope, name, writer) {
    if (arguments.length === 2) {
        if (typeof(arguments[1]) === "object") {
            writer = name;
            name = undefined;
        } else {
            writer = new TermWriter();
        }
    } else if (arguments.length === 1) {
        writer = new TermWriter();
    }
    if (typeof(scope) === "string") {
        scope = require(fs.resolve(fs.workingDirectory(), scope));
    }
    var summary = {
        "testsRun": 0,
        "passed": 0,
        "errors": 0,
        "failures": 0,
        "time": 0
    };
    writer.writeHeader();
    if (name != undefined) {
        executeTest(scope, name, summary, writer, []);
    } else {
        executeTestScope(scope, summary, writer, []);
    }
    scope = null;
    writer.writeSummary(summary);
    return summary.failures + summary.errors;
}

/**
 * Loops over all properties of a test scope and executes all methods whose
 * name starts with "test".
 * @param {Object} scope The scope object containing the test functions
 * @param {Object} summary An object containing summary information
 * @param {Object} writer A writer instance for displaying test results
 * @param {Array} path An array containing property path segments
 */
function executeTestScope(scope, summary, writer, path) {
    // loop over all exported properties and see if there are test methods to run
    for (var name in scope) {
        var value = scope[name];
        if (name === "test" || !strings.startsWith(name, "test")) {
            continue;
        }
        executeTest(scope, name, summary, writer, path);
    }
    return;
};

/**
 * Executes a single test, which can be either a single test method
 * or a test submodule.
 * @param {Object} scope The scope object containing the test
 * @param {String} name The name of the test to execute
 * @param {Object} summary An object containing summary information
 * @param {Object} writer A writer instance for displaying test results
 * @param {Array} path An array containing property path segments
 */
function executeTest(scope, name, summary, writer, path) {
    var value = scope[name];
    if (value instanceof Function) {
        writer.writeTestStart(name);
        var start = null;
        var time = 0;
        try {
            // execute setUp, if defined
            if (typeof(scope.setUp) === "function") {
                scope.setUp();
            }
            // execute test function
            start = new Date();
            value();
            time = (new Date()).getTime() - start.getTime();
            writer.writeTestPassed(time);
            summary.passed += 1;
        } catch (e) {
            if (!(e instanceof AssertionError) && !(e instanceof ArgumentsError)) {
                e = new EvaluationError(e);
            }
            writer.writeTestFailed(e);
            if (e instanceof AssertionError) {
                summary.failures += 1;
            } else {
                summary.errors += 1;
            }
        } finally {
            // execute tearDown, if defined
            if (typeof(scope.tearDown) === "function") {
                scope.tearDown();
            }
            summary.testsRun += 1;
            summary.time += time;
        }
    } else if (value.constructor === Object) {
        writer.enterScope(name);
        executeTestScope(value, summary, writer, path.concat([name]));
        writer.exitScope(name);
    }
    return;
}

/*******************************************
 *****  T E R M I N A L   W R I T E R  *****
 *******************************************/

/**
 * Constructs a new TermWriter instance
 * @class Instances of this class represent a writer for displaying test results
 * in the shell
 * @returns A newly created TermWriter instance
 * @constructor
 */
var TermWriter = function() {
    this.indent = "";
    return this;
};

/** @ignore */
TermWriter.prototype.toString = function() {
    return "[TermWriter]";
};

/**
 * Write a header at the beginning of a unit test(suite)
 */
TermWriter.prototype.writeHeader = function() {
    term.writeln("================================================================================");
    return;
};

/**
 * Notification that we're entering a new test scope.
 * @param name the name of the test scope
 */
TermWriter.prototype.enterScope = function(name) {
    term.writeln(this.indent, "+ Running", name, "...");
    this.indent += "  ";
};

/**
 * Notification that we're leaving a test scope.
 * @param name the name of the test scope
 */
TermWriter.prototype.exitScope = function(name) {
    this.indent = this.indent.substring(2);
};

/**
 * Display the beginning of a test function execution
 * @param {String} name The name of the test function about to be executed
 */
TermWriter.prototype.writeTestStart = function(name) {
    term.write(this.indent, "+ Running", name, "...");
    return;
};

/**
 * Display a passed test method execution
 * @param {Number} time The time the execution of the test method took
 */
TermWriter.prototype.writeTestPassed = function(time) {
    term.writeln(term.BOLD, " PASSED", term.RESET, "(" + time + " ms)");
    return;
};

/**
 * Display a failed test
 * @param {Object} exception The exception thrown during test method execution
 */
TermWriter.prototype.writeTestFailed = function(exception) {
    term.writeln(term.BOLD, term.WHITE, term.ONRED, " FAILED ");
    exception.message.split(/\n/).forEach(function(line) {
        term.writeln("  ", term.BOLD, term.RED, line);
    });
    if (exception.stackTrace != null) {
        exception.stackTrace.forEach(function(line) {
            term.writeln("  ", term.BOLD, line);
        });
    } else if (exception.fileName) {
        term.writeln("  at " + exception.fileName + ":" + exception.lineNumber);
    }
    term.writeln("");
    return;
};

/**
 * Display the summary of a unit test(suite) execution
 * @param {Object} summary The unit test summary
 */
TermWriter.prototype.writeSummary = function(summary) {
    if (summary.testsRun > 0) {
        term.writeln("--------------------------------------------------------------------------------");
        term.writeln("Executed", summary.testsRun, "tests in", summary.time, "ms ");
        term.writeln(term.BOLD, "Passed", summary.passed + ";", "Failed", summary.failures + ";", "Errors", summary.errors + ";");
    } else {
        term.writeln("No tests found");
    }
    return;
};
/**
 * Creates a new EvaluationError instance
 * @class Instances of this class represent an exception thrown when evaluating
 * a test file or a single test function
 * @param {Object} messageOrException Either a message string or the exception
 * thrown when evaluating
 * @returns A newly created EvaluationError instance
 * @constructor
 * @exteds TestException
 */
function EvaluationError(messageOrException) {
    var message = undefined;
    var exception = null;
    var stackTrace = null;
    var fileName = null;
    var lineNumber = -1;

    Object.defineProperty(this, "message", {
        get: function() {
            return message;
        }
    });

    Object.defineProperty(this, "stackTrace", {
        get: function() {
            return stackTrace;
        }
    });

    Object.defineProperty(this, "fileName", {
        get: function() {
            return fileName;
        }
    });

    Object.defineProperty(this, "lineNumber", {
        get: function() {
            return lineNumber;
        }
    });

    /**
     * Main constructor body
     */
    if (messageOrException instanceof Error) {
        exception = messageOrException;
    } else if (typeof(messageOrException.toString) === 'function') {
        message = messageOrException.toString();
    } else {
        message = messageOrException;
    }

    if (exception != null) {
        if (exception.rhinoException != null) {
            var e = exception.rhinoException;
            message += e.details();
            stackTrace = getStackTrace(e.getStackTrace());
        } else if (exception instanceof Error) {
            message = exception.message;
        }
        if (!stackTrace) {
            // got no stack trace, so add at least filename and line number
            fileName = exception.fileName || null;
            lineNumber = exception.lineNumber || null;
        }
    }
    return this;
};
EvaluationError.prototype = new Error();

/**
 * Executed when called from the command line
 */
if (require.main == module.id) {
    var system = require("system");
    if (system.args.length == 1) {
        term.writeln("Usage: bin/ringo test test/file1 test/file2");
    } else {
        var writer = new TermWriter();
        var failures = 0;
        for (var i=1; i<system.args.length; i+=1) {
            failures += this.run(system.args[i], writer);
        }
        system.exit(failures);
    }
}
<commit_msg>[doc] Test functions start with the prefix 'test'<commit_after>/**
 * @fileOverview A test runner compliant to the
 * [CommonJS Unit Testing](http://wiki.commonjs.org/wiki/Unit_Testing/1.0)
 * specification. It manages the execution of unit tests and processes test results.
 * The runner reports the total number of failures as exit status code.
 *
 * The runner treats a module like a test case. A test case defines the fixture
 * to run multiple tests. Test cases can provide optional setUp() and
 * tearDown() functions to initialize and destroy the fixture. The
 * test runner will run these methods prior to / after each test. Test functions
 * must start with a test prefix in their name, otherwise they
 * are skipped by the runner.
 *
 * The following example test case testDatabase.js starts a
 * new test runner if executed with ringo testDatabase.js
 *
 * @example // testDatabase.js
 * exports.setUp = function() { ... open db connection ... }
 * exports.tearDown = function() { ... close db connection ... }
 *
 * // Test functions start with the prefix 'test'
 * exports.testCreateTable = function() { ... }
 * exports.testInsertData = function() { ... }
 * exports.testTransactions = function() { ... }
 * exports.testDeleteTable = function() { ... }
 *
 * if (require.main == module.id) {
 *   // Get a runner and run on the current module
 *   require("test").run(exports);
 * }
 *
 * @see The assert module is an
 * assertion library to write unit tests.
 */

var strings = require("ringo/utils/strings");
var term = require("ringo/term");
var fs = require("fs");

export(
    "run",
    "jsDump",
    "getStackTrace",
    "getType"
);

var {
    AssertionError,
    ArgumentsError
} = require("./assert");

/**
 * Converts the value passed as argument into a nicely formatted and
 * indented string
 * @param {Object} value The value to convert into a string
 * @param {Number} lvl Optional indentation level (defaults to zero)
 * @returns The string representation of the object passed as argument
 * @type String
 */
function jsDump(value, lvl) {
    if (!lvl) {
        lvl = 0;
    }

    switch (getType(value)) {
        case "string":
            return jsDump.quote(value);
        case "boolean":
        case "number":
        case "nan":
        case "date":
        case "regexp":
            return value.toString();
        case "undefined":
        case "null":
            return String(value);
        case "function":
            if (getType(value.name) === "string" && value.name.length > 0) {
                return value.name;
            }
            return value.toSource();
        case "array":
            var buf = value.map(function(val) {
                return jsDump.indent(lvl + 1) + jsDump(val, lvl + 1);
            });
            return ["[", buf.join(",\n"), jsDump.indent(lvl) + "]"].join("\n");
        case "object":
            var buf = [];
            for (var propName in value) {
                buf.push(jsDump.indent(lvl + 1) + '"' + propName + '": ' + jsDump(value[propName], lvl + 1));
            }
            return ["{", buf.join(",\n"), jsDump.indent(lvl) + "}"].join("\n");
        case "java":
            return '<java:' + value.class.name + '>';
    }
}
/**
 * @ignore
 */
jsDump.indent = function(lvl) {
    return strings.repeat("    ", lvl);
};

/**
 * @ignore
 */
jsDump.quote = function(str) {
    return JSON.stringify(str.toString());
};

/**
 * Returns the type of the object passed as argument.
 * @returns The type of the object passed as argument
 * @type String
 */
function getType(obj) {
    if (typeof(obj) === "string") {
        return "string";
    } else if (typeof(obj) === "boolean") {
        return "boolean";
    } else if (typeof (obj) === "number") {
        return (isNaN(obj) === true) ? "nan" : "number";
    } else if (typeof(obj) === "undefined") {
        return "undefined";
    } else if (obj === null) {
        return "null";
    } else if (obj instanceof Array) {
        return "array";
    } else if (obj instanceof Date) {
        return "date";
    } else if (obj instanceof RegExp) {
        return "regexp";
    } else if (obj instanceof Function) {
        return "function";
    } else if (obj instanceof java.lang.Object) {
        return "java";
    }
    return "object";
}

/**
 * Creates a stack trace and parses it for display.
 * @param {java.lang.StackTraceElement} trace The trace to parse. If not given
 * a stacktrace will be generated
 * @returns The parsed stack trace
 * @type String
 */
function getStackTrace(trace) {
    // create exception and fill in stack trace
    if (!trace) {
        var ex = new Packages.org.mozilla.javascript.EvaluatorException("");
        ex.fillInStackTrace();
        trace = ex.getScriptStack();
    }
    var stack = [];
    var el, fileName, lineNumber;
    for (var i = 0; i < trace.length; i += 1) {
        el = trace[i];
        if (el.fileName != null && el.lineNumber > -1) {
            // exclude all lines containing the unittest module itself
            // FIXME (ro): this is quite ugly, but it works ...
            if (el.fileName.indexOf(module.id) === 0 || el.fileName.indexOf("assert") === 0) {
                continue;
            }
            stack.push("at " + el.fileName + ":" + el.lineNumber);
        }
    }
    return stack;
};

/**
 * The main runner method. This method can be called with one, two or three
 * arguments: run(scope), run(scope, nameOfTest),
 * run(scope, writer) or run(scope, nameOfTest, writer)
 * @param {String|Object} scope Either the path to a module containing unit
 * tests to execute, or an object containing the exported test methods or nested scopes.
 * @param {String} name Optional name of a test method to execute
 * @param {Object} writer Optional writer to use for displaying the test results. Defaults
 * to TermWriter.
 */
function run(scope, name, writer) {
    if (arguments.length === 2) {
        if (typeof(arguments[1]) === "object") {
            writer = name;
            name = undefined;
        } else {
            writer = new TermWriter();
        }
    } else if (arguments.length === 1) {
        writer = new TermWriter();
    }
    if (typeof(scope) === "string") {
        scope = require(fs.resolve(fs.workingDirectory(), scope));
    }
    var summary = {
        "testsRun": 0,
        "passed": 0,
        "errors": 0,
        "failures": 0,
        "time": 0
    };
    writer.writeHeader();
    if (name != undefined) {
        executeTest(scope, name, summary, writer, []);
    } else {
        executeTestScope(scope, summary, writer, []);
    }
    scope = null;
    writer.writeSummary(summary);
    return summary.failures + summary.errors;
}

/**
 * Loops over all properties of a test scope and executes all methods whose
 * name starts with "test".
 * @param {Object} scope The scope object containing the test functions
 * @param {Object} summary An object containing summary information
 * @param {Object} writer A writer instance for displaying test results
 * @param {Array} path An array containing property path segments
 */
function executeTestScope(scope, summary, writer, path) {
    // loop over all exported properties and see if there are test methods to run
    for (var name in scope) {
        var value = scope[name];
        if (name === "test" || !strings.startsWith(name, "test")) {
            continue;
        }
        executeTest(scope, name, summary, writer, path);
    }
    return;
};

/**
 * Executes a single test, which can be either a single test method
 * or a test submodule.
 * @param {Object} scope The scope object containing the test
 * @param {String} name The name of the test to execute
 * @param {Object} summary An object containing summary information
 * @param {Object} writer A writer instance for displaying test results
 * @param {Array} path An array containing property path segments
 */
function executeTest(scope, name, summary, writer, path) {
    var value = scope[name];
    if (value instanceof Function) {
        writer.writeTestStart(name);
        var start = null;
        var time = 0;
        try {
            // execute setUp, if defined
            if (typeof(scope.setUp) === "function") {
                scope.setUp();
            }
            // execute test function
            start = new Date();
            value();
            time = (new Date()).getTime() - start.getTime();
            writer.writeTestPassed(time);
            summary.passed += 1;
        } catch (e) {
            if (!(e instanceof AssertionError) && !(e instanceof ArgumentsError)) {
                e = new EvaluationError(e);
            }
            writer.writeTestFailed(e);
            if (e instanceof AssertionError) {
                summary.failures += 1;
            } else {
                summary.errors += 1;
            }
        } finally {
            // execute tearDown, if defined
            if (typeof(scope.tearDown) === "function") {
                scope.tearDown();
            }
            summary.testsRun += 1;
            summary.time += time;
        }
    } else if (value.constructor === Object) {
        writer.enterScope(name);
        executeTestScope(value, summary, writer, path.concat([name]));
        writer.exitScope(name);
    }
    return;
}

/*******************************************
 *****  T E R M I N A L   W R I T E R  *****
 *******************************************/

/**
 * Constructs a new TermWriter instance
 * @class Instances of this class represent a writer for displaying test results
 * in the shell
 * @returns A newly created TermWriter instance
 * @constructor
 */
var TermWriter = function() {
    this.indent = "";
    return this;
};

/** @ignore */
TermWriter.prototype.toString = function() {
    return "[TermWriter]";
};

/**
 * Write a header at the beginning of a unit test(suite)
 */
TermWriter.prototype.writeHeader = function() {
    term.writeln("================================================================================");
    return;
};

/**
 * Notification that we're entering a new test scope.
 * @param name the name of the test scope
 */
TermWriter.prototype.enterScope = function(name) {
    term.writeln(this.indent, "+ Running", name, "...");
    this.indent += "  ";
};

/**
 * Notification that we're leaving a test scope.
 * @param name the name of the test scope
 */
TermWriter.prototype.exitScope = function(name) {
    this.indent = this.indent.substring(2);
};

/**
 * Display the beginning of a test function execution
 * @param {String} name The name of the test function about to be executed
 */
TermWriter.prototype.writeTestStart = function(name) {
    term.write(this.indent, "+ Running", name, "...");
    return;
};

/**
 * Display a passed test method execution
 * @param {Number} time The time the execution of the test method took
 */
TermWriter.prototype.writeTestPassed = function(time) {
    term.writeln(term.BOLD, " PASSED", term.RESET, "(" + time + " ms)");
    return;
};

/**
 * Display a failed test
 * @param {Object} exception The exception thrown during test method execution
 */
TermWriter.prototype.writeTestFailed = function(exception) {
    term.writeln(term.BOLD, term.WHITE, term.ONRED, " FAILED ");
    exception.message.split(/\n/).forEach(function(line) {
        term.writeln("  ", term.BOLD, term.RED, line);
    });
    if (exception.stackTrace != null) {
        exception.stackTrace.forEach(function(line) {
            term.writeln("  ", term.BOLD, line);
        });
    } else if (exception.fileName) {
        term.writeln("  at " + exception.fileName + ":" + exception.lineNumber);
    }
    term.writeln("");
    return;
};

/**
 * Display the summary of a unit test(suite) execution
 * @param {Object} summary The unit test summary
 */
TermWriter.prototype.writeSummary = function(summary) {
    if (summary.testsRun > 0) {
        term.writeln("--------------------------------------------------------------------------------");
        term.writeln("Executed", summary.testsRun, "tests in", summary.time, "ms ");
        term.writeln(term.BOLD, "Passed", summary.passed + ";", "Failed", summary.failures + ";", "Errors", summary.errors + ";");
    } else {
        term.writeln("No tests found");
    }
    return;
};
/**
 * Creates a new EvaluationError instance
 * @class Instances of this class represent an exception thrown when evaluating
 * a test file or a single test function
 * @param {Object} messageOrException Either a message string or the exception
 * thrown when evaluating
 * @returns A newly created EvaluationError instance
 * @constructor
 * @exteds TestException
 */
function EvaluationError(messageOrException) {
    var message = undefined;
    var exception = null;
    var stackTrace = null;
    var fileName = null;
    var lineNumber = -1;

    Object.defineProperty(this, "message", {
        get: function() {
            return message;
        }
    });

    Object.defineProperty(this, "stackTrace", {
        get: function() {
            return stackTrace;
        }
    });

    Object.defineProperty(this, "fileName", {
        get: function() {
            return fileName;
        }
    });

    Object.defineProperty(this, "lineNumber", {
        get: function() {
            return lineNumber;
        }
    });

    /**
     * Main constructor body
     */
    if (messageOrException instanceof Error) {
        exception = messageOrException;
    } else if (typeof(messageOrException.toString) === 'function') {
        message = messageOrException.toString();
    } else {
        message = messageOrException;
    }

    if (exception != null) {
        if (exception.rhinoException != null) {
            var e = exception.rhinoException;
            message += e.details();
            stackTrace = getStackTrace(e.getStackTrace());
        } else if (exception instanceof Error) {
            message = exception.message;
        }
        if (!stackTrace) {
            // got no stack trace, so add at least filename and line number
            fileName = exception.fileName || null;
            lineNumber = exception.lineNumber || null;
        }
    }
    return this;
};
EvaluationError.prototype = new Error();

/**
 * Executed when called from the command line
 */
if (require.main == module.id) {
    var system = require("system");
    if (system.args.length == 1) {
        term.writeln("Usage: bin/ringo test test/file1 test/file2");
    } else {
        var writer = new TermWriter();
        var failures = 0;
        for (var i=1; i<system.args.length; i+=1) {
            failures += this.run(system.args[i], writer);
        }
        system.exit(failures);
    }
}
<|endoftext|>