<commit_before>/**
* CONFIDENTIAL
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
* This is unpublished proprietary source code of Red Hat.
**/
// Generated on 2014-03-05 using generator-angular 0.7.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    app: {
      // configurable paths
      src: 'src',
      dist: 'www',
      url: '',
      default_local_server_url: 'http://localhost:8001'
    },

    copy: {
      static: {
        files: [
          {expand: true, cwd: '<%= app.src %>/', src: ['**/*.html'], dest: '<%= app.dist %>', filter: 'isFile'},
          {expand: true, cwd: '<%= app.src %>/', src: ['**/*.json'], dest: '<%= app.dist %>', filter: 'isFile'},
        ],
      },
      css: {
        files: [
          {src: 'node_modules/angular-material/angular-material.css', dest: '<%= app.dist %>/css/', expand: true, flatten: true },
        ]
      }
    },

    sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                '<%= app.dist %>/css/app.css': '<%= app.src %>/sass/app.scss'
            }
        }
    },

    browserify: {
      options: {
        browserifyOptions: {
           debug: true
        }
      },
      all: {
        files: {
          "<%= app.dist %>/app/bundle.js": ["<%= app.src %>/app/app.js"]
        },
        options: {
          watch: true
        }
      }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      js: {
        files: ['<%= app.dist %>/app/bundle.js'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      html: {
        files: ['<%= app.src %>/sass/{,*/}*.html'],
        tasks: ['copy:static']
      },
      sass: {
        files: ['<%= app.src %>/sass/{,*/}*.scss'],
        tasks: ['sass']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= app.dist %>/**/*.html',
          '<%= app.dist %>/css/{,*/}*.css',
          '<%= app.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9002,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35730
      },
      livereload: {
        options: {
          open: {
            target: '<%= app.url %>'
          },
          base: [
            '.tmp',
            '<%= app.dist %>'
          ]
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: ['<%= app.dist %>'],
      server: '.tmp'
    }
  });

  grunt.registerTask('serve', function (target) {
    if (target === 'local') {
      var conn = 'http://' + grunt.config.get('connect.options.hostname') + ':' +
        grunt.config.get('connect.options.port');
      var url = grunt.option('url') || grunt.config.get('app.default_local_server_url');
      grunt.config.set('app.url', conn + '/?url=' + url);
    } else {
      // open with no url passed to fh-js-sdk
      grunt.config.set('connect.livereload.options.open', true);
    }

    grunt.task.run([
      'clean:dist',
      'sass',
      'copy',
      'clean:server',
      'connect:livereload',
      'browserify',
      'watch'
    ]);
  });

  grunt.registerTask('default', ['serve']);
};
<commit_msg>Fixed the html watch<commit_after>/**
* CONFIDENTIAL
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
* This is unpublished proprietary source code of Red Hat.
**/
// Generated on 2014-03-05 using generator-angular 0.7.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    app: {
      // configurable paths
      src: 'src',
      dist: 'www',
      url: '',
      default_local_server_url: 'http://localhost:8001'
    },

    copy: {
      static: {
        files: [
          {expand: true, cwd: '<%= app.src %>/', src: ['**/*.html'], dest: '<%= app.dist %>', filter: 'isFile'},
          {expand: true, cwd: '<%= app.src %>/', src: ['**/*.json'], dest: '<%= app.dist %>', filter: 'isFile'},
        ],
      },
      css: {
        files: [
          {src: 'node_modules/angular-material/angular-material.css', dest: '<%= app.dist %>/css/', expand: true, flatten: true },
        ]
      }
    },

    sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                '<%= app.dist %>/css/app.css': '<%= app.src %>/sass/app.scss'
            }
        }
    },

    browserify: {
      options: {
        browserifyOptions: {
           debug: true
        }
      },
      all: {
        files: {
          "<%= app.dist %>/app/bundle.js": ["<%= app.src %>/app/app.js"]
        },
        options: {
          watch: true
        }
      }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      js: {
        files: ['<%= app.dist %>/app/bundle.js'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      html: {
        files: ['<%= app.src %>/{,*/}*.html'],
        tasks: ['copy:static']
      },
      sass: {
        files: ['<%= app.src %>/sass/{,*/}*.scss'],
        tasks: ['sass']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= app.dist %>/**/*.html',
          '<%= app.dist %>/css/{,*/}*.css',
          '<%= app.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9002,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35730
      },
      livereload: {
        options: {
          open: {
            target: '<%= app.url %>'
          },
          base: [
            '.tmp',
            '<%= app.dist %>'
          ]
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: ['<%= app.dist %>'],
      server: '.tmp'
    }
  });

  grunt.registerTask('serve', function (target) {
    if (target === 'local') {
      var conn = 'http://' + grunt.config.get('connect.options.hostname') + ':' +
        grunt.config.get('connect.options.port');
      var url = grunt.option('url') || grunt.config.get('app.default_local_server_url');
      grunt.config.set('app.url', conn + '/?url=' + url);
    } else {
      // open with no url passed to fh-js-sdk
      grunt.config.set('connect.livereload.options.open', true);
    }

    grunt.task.run([
      'clean:dist',
      'sass',
      'copy',
      'clean:server',
      'connect:livereload',
      'browserify',
      'watch'
    ]);
  });

  grunt.registerTask('default', ['serve']);
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt) {

  grunt.initConfig({

    pkg: grunt.file.readJSON('bower.json'),

    clean: {
      dev: [
        'browser_extensions/chrome_dev/'
      ],
      dist: [
        'dist/',
        'browser_extensions/chrome_dist/'
      ]
    },

    copy: {
      dev: {
        files: [
          {
            expand: true,
            cwd: 'browser_extensions/chrome/',
            src: [
              '_locales/**/*',
              'images/icon_*',
              'js/**/*',
              'pages/**/*',
              'sounds/**/*',
              'stylesheets/**/*.css',
              'vendors/**/*',
              'manifest.json'
            ],
            dest: 'browser_extensions/chrome_dev/'
          },
          {
            src: 'src/pangu.js',
            dest: 'browser_extensions/chrome_dev/vendors/pangu.min.js'
          }
        ]
      },
      dist: {
        files: [
          {
            src: 'dist/pangu.min.js',
            dest: 'browser_extensions/chrome/vendors/pangu.min.js'
          },
          {
            expand: true,
            cwd: 'browser_extensions/chrome/',
            src: [
              '_locales/**/*',
              'images/icon_*',
              'js/**/*',
              'pages/**/*',
              'sounds/**/*',
              'stylesheets/**/*.css',
              'vendors/**/*',
              'manifest.json'
            ],
            dest: 'browser_extensions/chrome_dist/'
          },
          {
            src: '/Users/vinta/Dropbox/Developer/Projects/paranoid-auto-spacing/key.pem',
            dest: 'browser_extensions/chrome_dist/key.pem'
          }
        ]
      }
    },

    karma: {
      dist: {
        options: {
          // base path, that will be used to resolve files and exclude
          basePath: '',
          // start these browsers
          browsers: [
            'PhantomJS'
          ],
          // list of files / patterns to load in the browser
          files: [
            'dist/*.js',
            'tests/lib/jquery/jquery-1.10.2.min.js',
            'tests/lib/jasmine-jquery/jasmine-jquery.js',
            'tests/spec/**/*.js',
            {
              pattern: 'tests/fixtures/**/*.html',
              included: false,
              served: true
            }
          ],
          // list of files to exclude
          exclude: [],
          // frameworks to use
          frameworks: [
            'jasmine'
          ],
          // preprocessors allow you to do some work with your files before they get served to the browser.
          preprocessors: {
            '**/*.html': []
          },
          // test results reporter to use, possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
          reporters: [
            'progress'
          ],
          // continuous Integration mode, if true, it capture browsers, run tests and exit
          singleRun: true
        }
      }
    },

    // remove console.log()
    strip: {
      dist: {
        src: 'src/pangu.js',
        dest: 'dist/pangu.js'
      },
      dist_chrome: {
        src: 'browser_extensions/chrome_dist/js/*.js',
        options: {
          inline: true
        }
      }
    },

    uglify: {
      options: {
        banner: grunt.file.read('src/banner.js')
      },
      dist: {
        src: 'dist/pangu.js',
        dest: 'dist/pangu.min.js'
      }
    },

    watch: {
      dev: {
        files: [
          'Gruntfile.js',
          'bower.json',
          'src/**/*',
          'browser_extensions/chrome/**/*',
          '!browser_extensions/chrome/vendors/pangu.min.js'
        ],
        tasks: [
          'dev'
        ]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-strip');

  grunt.registerTask('dev', [
    'clean:dev',
    'copy:dev'
  ]);

  // 準備打包到 Chrome Web Store
  // browser_extensions/chrome_dev/ 是開發用的
  // browser_extensions/chrome_dist/ 是打包用的
  grunt.registerTask('dist', [
    'clean:dist',
    'strip:dist',
    'uglify',
    'copy:dist',
    'strip:dist_chrome'
  ]);

  grunt.registerTask('test', [
    'dist',
    'karma'
  ]);

  grunt.registerTask('default', [
    'test'
  ]);

};
<commit_msg>fix Gruntfile.js<commit_after>'use strict';

module.exports = function(grunt) {

  grunt.initConfig({

    pkg: grunt.file.readJSON('bower.json'),

    clean: {
      dev: [
        'browser_extensions/chrome_dev/'
      ],
      dist: [
        'dist/',
        'browser_extensions/chrome_dist/'
      ],
      all: [
        'dist/',
        'browser_extensions/chrome_dev/',
        'browser_extensions/chrome_dist/'
      ]
    },

    copy: {
      dev: {
        files: [
          {
            expand: true,
            cwd: 'browser_extensions/chrome/',
            src: [
              '_locales/**/*',
              'images/icon_*',
              'js/**/*',
              'pages/**/*',
              'sounds/**/*',
              'stylesheets/**/*.css',
              'vendors/**/*',
              'manifest.json'
            ],
            dest: 'browser_extensions/chrome_dev/'
          },
          {
            src: 'src/pangu.js',
            dest: 'browser_extensions/chrome_dev/vendors/pangu.min.js'
          }
        ]
      },
      dist: {
        files: [
          {
            src: 'dist/pangu.min.js',
            dest: 'browser_extensions/chrome/vendors/pangu.min.js'
          },
          {
            expand: true,
            cwd: 'browser_extensions/chrome/',
            src: [
              '_locales/**/*',
              'images/icon_*',
              'js/**/*',
              'pages/**/*',
              'sounds/**/*',
              'stylesheets/**/*.css',
              'vendors/**/*',
              'manifest.json'
            ],
            dest: 'browser_extensions/chrome_dist/'
          },
          {
            src: '/Users/vinta/Dropbox/Developer/Projects/paranoid-auto-spacing/key.pem',
            dest: 'browser_extensions/chrome_dist/key.pem'
          }
        ]
      }
    },

    karma: {
      dist: {
        options: {
          // base path, that will be used to resolve files and exclude
          basePath: '',
          // start these browsers
          browsers: [
            'PhantomJS'
          ],
          // list of files / patterns to load in the browser
          files: [
            'dist/*.js',
            'tests/lib/jquery/jquery-1.10.2.min.js',
            'tests/lib/jasmine-jquery/jasmine-jquery.js',
            'tests/spec/**/*.js',
            {
              pattern: 'tests/fixtures/**/*.html',
              included: false,
              served: true
            }
          ],
          // list of files to exclude
          exclude: [],
          // frameworks to use
          frameworks: [
            'jasmine'
          ],
          // preprocessors allow you to do some work with your files before they get served to the browser.
          preprocessors: {
            '**/*.html': []
          },
          // test results reporter to use, possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
          reporters: [
            'progress'
          ],
          // continuous Integration mode, if true, it capture browsers, run tests and exit
          singleRun: true
        }
      }
    },

    // remove console.log()
    strip: {
      dist: {
        src: 'src/pangu.js',
        dest: 'dist/pangu.js'
      },
      dist_chrome: {
        src: 'browser_extensions/chrome_dist/js/*.js',
        options: {
          inline: true
        }
      }
    },

    uglify: {
      options: {
        banner: grunt.file.read('src/banner.js')
      },
      dist: {
        src: 'dist/pangu.js',
        dest: 'dist/pangu.min.js'
      }
    },

    watch: {
      dev: {
        files: [
          'Gruntfile.js',
          'bower.json',
          'src/**/*',
          'browser_extensions/chrome/**/*',
          '!browser_extensions/chrome/vendors/pangu.min.js'
        ],
        tasks: [
          'dev'
        ]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-strip');

  grunt.registerTask('dev', [
    'clean:all',
    'copy:dev'
  ]);

  // 準備打包到 Chrome Web Store
  // browser_extensions/chrome_dev/ 是開發用的
  // browser_extensions/chrome_dist/ 是打包用的
  grunt.registerTask('dist', [
    'clean:all',
    'strip:dist',
    'uglify',
    'copy:dist',
    'strip:dist_chrome'
  ]);

  grunt.registerTask('test', [
    'dist',
    'karma'
  ]);

  grunt.registerTask('default', [
    'test'
  ]);

};
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *
 *
 * @providesModule SwipeableListView
 * @flow
 */
'use strict';

const ListView = require('ListView');
const React = require('React');
const SwipeableListViewDataSource = require('SwipeableListViewDataSource');
const SwipeableRow = require('SwipeableRow');

const {PropTypes} = React;

type Props = {
  bounceFirstRowOnMount: boolean,
  dataSource: SwipeableListViewDataSource,
  maxSwipeDistance: number | (rowData: any, sectionID: string, rowID: string) => number,
  onScroll: ?Function,
  renderRow: Function,
  renderQuickActions: Function,
};

type State = {
  dataSource: Object,
};

/**
 * A container component that renders multiple SwipeableRow's in a ListView
 * implementation. This is designed to be a drop-in replacement for the
 * standard React Native `ListView`, so use it as if it were a ListView, but
 * with extra props, i.e.
 *
 * let ds = SwipeableListView.getNewDataSource();
 * ds.cloneWithRowsAndSections(dataBlob, ?sectionIDs, ?rowIDs);
 * // ..
 * <SwipeableListView renderRow={..} renderQuickActions={..} {..ListView props} />
 *
 * SwipeableRow can be used independently of this component, but the main
 * benefit of using this component is
 *
 * - It ensures that at most 1 row is swiped open (auto closes others)
 * - It can bounce the 1st row of the list so users know it's swipeable
 * - More to come
 */
class SwipeableListView extends React.Component {
  props: Props;
  state: State;

  _listViewRef: ?React.Element<any> = null;
  _shouldBounceFirstRowOnMount: boolean = false;

  static getNewDataSource(): Object {
    return new SwipeableListViewDataSource({
      getRowData: (data, sectionID, rowID) => data[sectionID][rowID],
      getSectionHeaderData: (data, sectionID) => data[sectionID],
      rowHasChanged: (row1, row2) => row1 !== row2,
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
    });
  }

  static propTypes = {
    /**
     * To alert the user that swiping is possible, the first row can bounce
     * on component mount.
     */
    bounceFirstRowOnMount: PropTypes.bool.isRequired,
    /**
     * Use `SwipeableListView.getNewDataSource()` to get a data source to use,
     * then use it just like you would a normal ListView data source
     */
    dataSource: PropTypes.instanceOf(SwipeableListViewDataSource).isRequired,
    // Maximum distance to open to after a swipe
    maxSwipeDistance: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.func,
    ]).isRequired,
    // Callback method to render the swipeable view
    renderRow: PropTypes.func.isRequired,
    // Callback method to render the view that will be unveiled on swipe
    renderQuickActions: PropTypes.func.isRequired,
  };

  static defaultProps = {
    bounceFirstRowOnMount: false,
    renderQuickActions: () => null,
  };

  constructor(props: Props, context: any): void {
    super(props, context);

    this._shouldBounceFirstRowOnMount = this.props.bounceFirstRowOnMount;
    this.state = {
      dataSource: this.props.dataSource,
    };
  }

  componentWillReceiveProps(nextProps: Props): void {
    if (this.state.dataSource.getDataSource() !== nextProps.dataSource.getDataSource()) {
      this.setState({
        dataSource: nextProps.dataSource,
      });
    }
  }

  render(): React.Element<any> {
    return (
      <ListView
        {...this.props}
        ref={(ref) => {
          this._listViewRef = ref;
        }}
        dataSource={this.state.dataSource.getDataSource()}
        onScroll={this._onScroll}
        renderRow={this._renderRow}
      />
    );
  }

  _onScroll = (e): void => {
    // Close any opens rows on ListView scroll
    if (this.props.dataSource.getOpenRowID()) {
      this.setState({
        dataSource: this.state.dataSource.setOpenRowID(null),
      });
    }
    this.props.onScroll && this.props.onScroll(e);
  }

  /**
   * This is a work-around to lock vertical `ListView` scrolling on iOS and
   * mimic Android behaviour. Locking vertical scrolling when horizontal
   * scrolling is active allows us to significantly improve framerates
   * (from high 20s to almost consistently 60 fps)
   */
  _setListViewScrollable(value: boolean): void {
    if (this._listViewRef && typeof this._listViewRef.setNativeProps === 'function') {
      this._listViewRef.setNativeProps({
        scrollEnabled: value,
      });
    }
  }

  // Passing through ListView's getScrollResponder() function
  getScrollResponder(): ?Object {
    if (this._listViewRef && typeof this._listViewRef.getScrollResponder === 'function') {
      return this._listViewRef.getScrollResponder();
    }
  }

  // This enables rows having variable width slideoutView.
  _getMaxSwipeDistance = (rowData: Object, sectionID: string, rowID: string): number => {
    if (typeof this.props.maxSwipeDistance === 'function') {
      return this.props.maxSwipeDistance(rowData, sectionID, rowID);
    }

    return this.props.maxSwipeDistance;
  };

  _renderRow = (rowData: Object, sectionID: string, rowID: string): React.Element<any> => {
    const slideoutView = this.props.renderQuickActions(rowData, sectionID, rowID);

    // If renderRowSlideout is unspecified or returns falsey, don't allow swipe
    if (!slideoutView) {
      return this.props.renderRow(rowData, sectionID, rowID);
    }

    let shouldBounceOnMount = false;
    if (this._shouldBounceFirstRowOnMount) {
      this._shouldBounceFirstRowOnMount = false;
      shouldBounceOnMount = rowID === this.props.dataSource.getFirstRowID();
    }

    return (
      <SwipeableRow
        slideoutView={slideoutView}
        isOpen={rowData.id === this.props.dataSource.getOpenRowID()}
        maxSwipeDistance={this._getMaxSwipeDistance(rowData, sectionID, rowID)}
        key={rowID}
        onOpen={() => this._onOpen(rowData.id)}
        onSwipeEnd={() => this._setListViewScrollable(true)}
        onSwipeStart={() => this._setListViewScrollable(false)}
        shouldBounceOnMount={shouldBounceOnMount}>
        {this.props.renderRow(rowData, sectionID, rowID)}
      </SwipeableRow>
    );
  };

  _onOpen(rowID: string): void {
    this.setState({
      dataSource: this.state.dataSource.setOpenRowID(rowID),
    });
  }
}

module.exports = SwipeableListView;
<commit_msg>update comment to reflect change in function name to renderQuickActions<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *
 *
 * @providesModule SwipeableListView
 * @flow
 */
'use strict';

const ListView = require('ListView');
const React = require('React');
const SwipeableListViewDataSource = require('SwipeableListViewDataSource');
const SwipeableRow = require('SwipeableRow');

const {PropTypes} = React;

type Props = {
  bounceFirstRowOnMount: boolean,
  dataSource: SwipeableListViewDataSource,
  maxSwipeDistance: number | (rowData: any, sectionID: string, rowID: string) => number,
  onScroll: ?Function,
  renderRow: Function,
  renderQuickActions: Function,
};

type State = {
  dataSource: Object,
};

/**
 * A container component that renders multiple SwipeableRow's in a ListView
 * implementation. This is designed to be a drop-in replacement for the
 * standard React Native `ListView`, so use it as if it were a ListView, but
 * with extra props, i.e.
 *
 * let ds = SwipeableListView.getNewDataSource();
 * ds.cloneWithRowsAndSections(dataBlob, ?sectionIDs, ?rowIDs);
 * // ..
 * <SwipeableListView renderRow={..} renderQuickActions={..} {..ListView props} />
 *
 * SwipeableRow can be used independently of this component, but the main
 * benefit of using this component is
 *
 * - It ensures that at most 1 row is swiped open (auto closes others)
 * - It can bounce the 1st row of the list so users know it's swipeable
 * - More to come
 */
class SwipeableListView extends React.Component {
  props: Props;
  state: State;

  _listViewRef: ?React.Element<any> = null;
  _shouldBounceFirstRowOnMount: boolean = false;

  static getNewDataSource(): Object {
    return new SwipeableListViewDataSource({
      getRowData: (data, sectionID, rowID) => data[sectionID][rowID],
      getSectionHeaderData: (data, sectionID) => data[sectionID],
      rowHasChanged: (row1, row2) => row1 !== row2,
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
    });
  }

  static propTypes = {
    /**
     * To alert the user that swiping is possible, the first row can bounce
     * on component mount.
     */
    bounceFirstRowOnMount: PropTypes.bool.isRequired,
    /**
     * Use `SwipeableListView.getNewDataSource()` to get a data source to use,
     * then use it just like you would a normal ListView data source
     */
    dataSource: PropTypes.instanceOf(SwipeableListViewDataSource).isRequired,
    // Maximum distance to open to after a swipe
    maxSwipeDistance: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.func,
    ]).isRequired,
    // Callback method to render the swipeable view
    renderRow: PropTypes.func.isRequired,
    // Callback method to render the view that will be unveiled on swipe
    renderQuickActions: PropTypes.func.isRequired,
  };

  static defaultProps = {
    bounceFirstRowOnMount: false,
    renderQuickActions: () => null,
  };

  constructor(props: Props, context: any): void {
    super(props, context);

    this._shouldBounceFirstRowOnMount = this.props.bounceFirstRowOnMount;
    this.state = {
      dataSource: this.props.dataSource,
    };
  }

  componentWillReceiveProps(nextProps: Props): void {
    if (this.state.dataSource.getDataSource() !== nextProps.dataSource.getDataSource()) {
      this.setState({
        dataSource: nextProps.dataSource,
      });
    }
  }

  render(): React.Element<any> {
    return (
      <ListView
        {...this.props}
        ref={(ref) => {
          this._listViewRef = ref;
        }}
        dataSource={this.state.dataSource.getDataSource()}
        onScroll={this._onScroll}
        renderRow={this._renderRow}
      />
    );
  }

  _onScroll = (e): void => {
    // Close any opens rows on ListView scroll
    if (this.props.dataSource.getOpenRowID()) {
      this.setState({
        dataSource: this.state.dataSource.setOpenRowID(null),
      });
    }
    this.props.onScroll && this.props.onScroll(e);
  }

  /**
   * This is a work-around to lock vertical `ListView` scrolling on iOS and
   * mimic Android behaviour. Locking vertical scrolling when horizontal
   * scrolling is active allows us to significantly improve framerates
   * (from high 20s to almost consistently 60 fps)
   */
  _setListViewScrollable(value: boolean): void {
    if (this._listViewRef && typeof this._listViewRef.setNativeProps === 'function') {
      this._listViewRef.setNativeProps({
        scrollEnabled: value,
      });
    }
  }

  // Passing through ListView's getScrollResponder() function
  getScrollResponder(): ?Object {
    if (this._listViewRef && typeof this._listViewRef.getScrollResponder === 'function') {
      return this._listViewRef.getScrollResponder();
    }
  }

  // This enables rows having variable width slideoutView.
  _getMaxSwipeDistance = (rowData: Object, sectionID: string, rowID: string): number => {
    if (typeof this.props.maxSwipeDistance === 'function') {
      return this.props.maxSwipeDistance(rowData, sectionID, rowID);
    }

    return this.props.maxSwipeDistance;
  };

  _renderRow = (rowData: Object, sectionID: string, rowID: string): React.Element<any> => {
    const slideoutView = this.props.renderQuickActions(rowData, sectionID, rowID);

    // If renderQuickActions is unspecified or returns falsey, don't allow swipe
    if (!slideoutView) {
      return this.props.renderRow(rowData, sectionID, rowID);
    }

    let shouldBounceOnMount = false;
    if (this._shouldBounceFirstRowOnMount) {
      this._shouldBounceFirstRowOnMount = false;
      shouldBounceOnMount = rowID === this.props.dataSource.getFirstRowID();
    }

    return (
      <SwipeableRow
        slideoutView={slideoutView}
        isOpen={rowData.id === this.props.dataSource.getOpenRowID()}
        maxSwipeDistance={this._getMaxSwipeDistance(rowData, sectionID, rowID)}
        key={rowID}
        onOpen={() => this._onOpen(rowData.id)}
        onSwipeEnd={() => this._setListViewScrollable(true)}
        onSwipeStart={() => this._setListViewScrollable(false)}
        shouldBounceOnMount={shouldBounceOnMount}>
        {this.props.renderRow(rowData, sectionID, rowID)}
      </SwipeableRow>
    );
  };

  _onOpen(rowID: string): void {
    this.setState({
      dataSource: this.state.dataSource.setOpenRowID(rowID),
    });
  }
}

module.exports = SwipeableListView;
<|endoftext|>


<commit_before>
var Sidebar = new Class({

	Implements: [Options, Events],

	options: {
		file_selected_class: 'UI_File_Selected',
		file_normal_class: 'UI_File_Normal',
		file_listing_class: 'tree',
		editable: false
	},

	trees: {},

	initialize: function(options){
		this.setOptions(options);
		this.element = $('app-sidebar');
	},

	buildTree: function() {
		var that = this;
		var treeOptions = {
			checkDrag: function(el){
				return !el.hasClass('nodrag') && that.options.editable;
			},
			checkDrop: function(el, drop){
				var isFile = el.get('rel') == 'file',
					isSibling = this.current.getSiblings().contains(el);

				return (
						((drop.isSubnode || isSibling) && isFile)
						|| el.hasClass('top_branch')
						|| isSibling && !isFile && !drop.isSubnode
						|| !isFile && drop.isSubnode && this.current.getParent().getParent() == el
					) ? false : true;
			},
			onChange: function(){
				this.updatePath(this.current);
				that.renameFile(this.current.retrieve('file'), this.getFullPath(this.current));
			},
			onRenameComplete: function(){
				$$('div.rename_branch').removeClass('active');
			}
		};

		// Tree and Collapse initilizations
		var trees = this.trees = {
			'lib': new FileTree('LibTree', treeOptions),
			'data': new FileTree('DataTree', treeOptions),
			'plugins': new FileTree('PluginsTree', Object.merge({}, treeOptions, { actions: {
				edit: false,
				remove: true
			}}))
		};

		var topBranchOptions = {
			add: this.options.editable,
			edit: false,
			remove: false
		};

		trees.lib.collapse = new Collapse('LibTree');
		trees.lib.addBranch({
			'rel': 'directory',
			'title': 'Lib',
			'id': 'lib_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		trees.data.collapse = new Collapse('DataTree');
		trees.data.addBranch({
			'rel': 'directory',
			'title': 'Data',
			'id': 'data_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		trees.plugins.collapse = new Collapse('PluginsTree');
		var pluginsBranch = trees.plugins.addBranch({
			'rel': 'directory',
			'title': 'Plugins',
			'id': 'plugins_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		var sdkBranch = $('core_library_lib');
		if(sdkBranch) {
			pluginsBranch.getElement('ul').grab(sdkBranch);
		}

		this.attach();

		return this;
	},

	attach: function() {
		var that = this,
			sidebarEl = $(this);

		// highlight branch on click
		sidebarEl.addEvent('click:relay(.{file_listing_class} li:not(.top_branch) .label)'.substitute(this.options), function(e) {
			var li = $(e.target).getParent('li'),
				file = li.retrieve('file');
			that.setSelectedFile(li);
			file.onSelect();
		});

		//adding modules to Lib
		$(this.trees.lib).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptNewFile();
		});

		//adding attachments to Data
		$(this.trees.data).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptAttachment();
		});

		//adding User Libraries to Plugins
		$(this.trees.plugins).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptPlugin();
		});

		// delete
		sidebarEl.addEvent('click:relay(.{file_listing_class} li:not(.top_branch) .actions .delete)'.substitute(this.options), function(e) {
			var file = $(e.target).getParent('li').retrieve('file');
			if (!file.options.readonly) {
				that.promptRemoval(file);
			}
		});

		Object.each(this.trees, function(tree, name) {
			tree.addEvents({
				'renameComplete': function(li, fullpath) {
					that.renameFile(li.retrieve('file'), fullpath);
				},
				'deleteBranch': function(li) {

				}
			});
		});

		return this;
	},

	renameFile: function(file, fullpath) {
		var pack = fd.getItem();
		if (file instanceof Module) {
			pack.renameModule(file.options.filename, fullpath.replace('.'+file.options.type, ''));
		} else if (file instanceof Attachment) {
			pack.renameAttachment(file.options.uid, fullpath.replace('.'+file.options.type, ''));
		}
	},

	removeFileFromTree: function(treeName, file) {
		var tree = this.trees[treeName],
			that = this;

		$(tree).getElements('li[title="{filename}.{type}"]'.substitute(file.options)).some(function(el) {
			if(el.retrieve('file') == file) {
				el.dispose();
				return true;
			}
		});
	},

	addFileToTree: function(treeName, file) {
		var tree = this.trees[treeName],
			that = this;

		if (!tree) {
			this.buildTree();
			tree = this.trees[treeName];
		}

		var options = {
			target:	$(tree).getElement('.top_branch'),
			url: file.options.url
		};

		if (!this.options.editable) {
			options.edit = false;
			options.remove = false;
		}

		var element = tree.addPath(file, options);
		tree.collapse.prepare();
		file.addEvent('destroy', function() {
			that.removeFileFromTree(treeName, file);
		});

		if(file.options.active || file.options.main) {
			this.setSelectedFile(element);
		}
	}.protect(),

	addLib: function(lib) {
		this.addFileToTree('lib', lib);
	},

	addData: function(attachment) {
		this.addFileToTree('data', attachment);
	},

	addPlugin: function(plugin) {
		this.addFileToTree('plugins', plugin);
	},

	setSelectedFile: function(el) {
		var options = this.options;

		$(this).getElements('.{file_listing_class} li'.substitute(options))
			.removeClass(options.file_selected_class)
			.addClass(options.file_normal_class);

		el.removeClass(options.file_normal_class)
			.addClass(options.file_selected_class);

		return this;
	},

	promptRemoval: function(file) {
		var question = fd.showQuestion({
			title: 'Are you sure you want to remove {name}?'.substitute({ name: file.options.path }),
			message: 'You may always copy it from this revision',
			ok: 'Remove',
			id: 'remove_module_button',
			callback: function() {
				fd.getItem().removeModule(file);
				question.destroy();
			}
		});
	},

	promptNewFile: function() {
		var prompt = fd.showQuestion({
			title: 'Create a new file',
			message: '<input type="text" name="new_file" id="new_file" placeholder="File name..." />',
			ok: 'Create File',
			id: 'create_new_file',
			callback: function() {
				// get data
				var filename = $('new_file').value,
					pack = fd.getItem();
				if (!filename) {
					fd.error.alert('Filename can\'t be empty', 'Please provide the name of the module');
					return;
				}
				if (pack.options.modules.some(function(mod) { return mod.filename == filename; })) {
					fd.error.alert('Filename has to be unique', 'You already have the module with that name');
					return;
				}

				pack.addModule(filename);
				prompt.destroy();
			}
		});
	},

	promptAttachment: function() {
		var prompt = fd.showQuestion({
			title: 'Upload an Attachment',
			message: '<input type="file" name="new_attachment" id="new_attachment" placeholder="Browse for file to attach" />',
			ok: 'Create File',
			id: 'new_attachment_button',
			callback: function() {
				var fileInput = $('new_attachment');
				if(!(fileInput.files && fileInput.files.length)) {
					fd.error.alert('No file was selected.', 'Please select a file to upload.');
					return;
				}

				fd.getItem().sendMultipleFiles(fileInput.files);
				prompt.destroy();
			}
		});
	},

	promptPlugin: function() {
		var prompt = fd.showQuestion({
			title: 'Add a User Library',
			message: '<input type="text" name="new_library" id="new_library" placeholder="Search for libraries to include" />' +
					 '<input type="hidden" name="library_id_number" id="library_id_number" />',
			ok: 'Add Library',
			id: 'new_library_button',
			callback: function() {
				var lib_id = $('library_id_number').value;
				if(!lib_id) {
					fd.error.alert('No User Library selected', 'Please enter the name of an existing User Library');
					return;
				}

				fd.getItem().assignLibrary(lib_id)
				prompt.destroy();
			}
		});

		//setup Library autocomplete
		// autocomplete
		var autocomplete = new FlightDeck.Autocomplete({
			'url': settings.library_autocomplete_url
		});
	},

	toElement: function() {
		return this.element;
	}

});<commit_msg>only show selected status if file is editable, fixing library removal<commit_after>
var Sidebar = new Class({

	Implements: [Options, Events],

	options: {
		file_selected_class: 'UI_File_Selected',
		file_normal_class: 'UI_File_Normal',
		file_listing_class: 'tree',
		editable: false
	},

	trees: {},

	initialize: function(options){
		this.setOptions(options);
		this.element = $('app-sidebar');
	},

	buildTree: function() {
		var that = this;
		var treeOptions = {
			checkDrag: function(el){
				return !el.hasClass('nodrag') && that.options.editable;
			},
			checkDrop: function(el, drop){
				var isFile = el.get('rel') == 'file',
					isSibling = this.current.getSiblings().contains(el);

				return (
						((drop.isSubnode || isSibling) && isFile)
						|| el.hasClass('top_branch')
						|| isSibling && !isFile && !drop.isSubnode
						|| !isFile && drop.isSubnode && this.current.getParent().getParent() == el
					) ? false : true;
			},
			onChange: function(){
				this.updatePath(this.current);
				that.renameFile(this.current.retrieve('file'), this.getFullPath(this.current));
			},
			onRenameComplete: function(){
				$$('div.rename_branch').removeClass('active');
			}
		};

		// Tree and Collapse initilizations
		var trees = this.trees = {
			'lib': new FileTree('LibTree', treeOptions),
			'data': new FileTree('DataTree', treeOptions),
			'plugins': new FileTree('PluginsTree', Object.merge({}, treeOptions, { actions: {
				edit: false,
				remove: true
			}}))
		};

		var topBranchOptions = {
			add: this.options.editable,
			edit: false,
			remove: false
		};

		trees.lib.collapse = new Collapse('LibTree');
		trees.lib.addBranch({
			'rel': 'directory',
			'title': 'Lib',
			'id': 'lib_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		trees.data.collapse = new Collapse('DataTree');
		trees.data.addBranch({
			'rel': 'directory',
			'title': 'Data',
			'id': 'data_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		trees.plugins.collapse = new Collapse('PluginsTree');
		var pluginsBranch = trees.plugins.addBranch({
			'rel': 'directory',
			'title': 'Plugins',
			'id': 'plugins_branch',
			'class': 'top_branch nodrag'
		}, null, topBranchOptions);

		var sdkBranch = $('core_library_lib');
		if(sdkBranch) {
			pluginsBranch.getElement('ul').grab(sdkBranch);
		}

		this.attach();

		return this;
	},

	attach: function() {
		var that = this,
			sidebarEl = $(this);

		// highlight branch on click
		sidebarEl.addEvent('click:relay(.{file_listing_class} li:not(.top_branch) .label)'.substitute(this.options), function(e) {
			var li = $(e.target).getParent('li'),
				file = li.retrieve('file');
			if(file) {
				if(file.is_editable()) {
					that.setSelectedFile(li);
				}

				file.onSelect();
			}
		});

		//adding modules to Lib
		$(this.trees.lib).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptNewFile();
		});

		//adding attachments to Data
		$(this.trees.data).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptAttachment();
		});

		//adding User Libraries to Plugins
		$(this.trees.plugins).addEvent('click:relay(li.top_branch > .holder .add)', function(e) {
			that.promptPlugin();
		});

		// delete
		sidebarEl.addEvent('click:relay(.{file_listing_class} li:not(.top_branch) .actions .delete)'.substitute(this.options), function(e) {
			var file = $(e.target).getParent('li').retrieve('file');
			if (!file.options.readonly) {
				that.promptRemoval(file);
			}
		});

		Object.each(this.trees, function(tree, name) {
			tree.addEvents({
				'renameComplete': function(li, fullpath) {
					that.renameFile(li.retrieve('file'), fullpath);
				},
				'deleteBranch': function(li) {

				}
			});
		});

		return this;
	},

	renameFile: function(file, fullpath) {
		var pack = fd.getItem();
		if (file instanceof Module) {
			pack.renameModule(file.options.filename, fullpath.replace('.'+file.options.type, ''));
		} else if (file instanceof Attachment) {
			pack.renameAttachment(file.options.uid, fullpath.replace('.'+file.options.type, ''));
		}
	},

	removeFileFromTree: function(treeName, file) {
		var tree = this.trees[treeName],
			that = this,
			title;

		if(file instanceof Library) {
			title = file.options.full_name;
		} else {
			title = file.options.filename + '.' + file.options.type;
		}

		$(tree).getElements('li[title="{title}"]'.substitute({title:title})).some(function(el) {
			if(el.retrieve('file') == file) {
				el.dispose();
				return true;
			}
		});
	},

	addFileToTree: function(treeName, file) {
		var tree = this.trees[treeName],
			that = this;

		if (!tree) {
			this.buildTree();
			tree = this.trees[treeName];
		}

		var options = {
			target:	$(tree).getElement('.top_branch'),
			url: file.options.url
		};

		if (!this.options.editable) {
			options.edit = false;
			options.remove = false;
		}

		var element = tree.addPath(file, options);
		tree.collapse.prepare();
		file.addEvent('destroy', function() {
			that.removeFileFromTree(treeName, file);
		});

		if((file.options.active || file.options.main) && file.is_editable()) {
			this.setSelectedFile(element);
		}
	}.protect(),

	addLib: function(lib) {
		this.addFileToTree('lib', lib);
	},

	addData: function(attachment) {
		this.addFileToTree('data', attachment);
	},

	addPlugin: function(plugin) {
		this.addFileToTree('plugins', plugin);
	},

	setSelectedFile: function(el) {
		var options = this.options;

		$(this).getElements('.{file_listing_class} li'.substitute(options))
			.removeClass(options.file_selected_class)
			.addClass(options.file_normal_class);

		el.removeClass(options.file_normal_class)
			.addClass(options.file_selected_class);

		return this;
	},

	promptRemoval: function(file) {
		var question = fd.showQuestion({
			title: 'Are you sure you want to remove {name}?'.substitute({ name: file.options.path }),
			message: file instanceof Module ? 'You may always copy it from this revision' : '',
			ok: 'Remove',
			id: 'remove_file_button',
			callback: function() {
				if (file instanceof Module) {
					fd.getItem().removeModule(file);
				} else if (file instanceof Attachment) {
					fd.getItem().removeAttachment(file);
				} else if (file instanceof Library) {
					fd.getItem().removeLibrary(file);
				}

				question.destroy();
			}
		});
	},

	promptNewFile: function() {
		var prompt = fd.showQuestion({
			title: 'Create a new file',
			message: '<input type="text" name="new_file" id="new_file" placeholder="File name..." />',
			ok: 'Create File',
			id: 'create_new_file',
			callback: function() {
				// get data
				var filename = $('new_file').value,
					pack = fd.getItem();
				if (!filename) {
					fd.error.alert('Filename can\'t be empty', 'Please provide the name of the module');
					return;
				}
				if (pack.options.modules.some(function(mod) { return mod.filename == filename; })) {
					fd.error.alert('Filename has to be unique', 'You already have the module with that name');
					return;
				}

				pack.addModule(filename);
				prompt.destroy();
			}
		});
	},

	promptAttachment: function() {
		var prompt = fd.showQuestion({
			title: 'Upload an Attachment',
			message: '<input type="file" name="new_attachment" id="new_attachment" placeholder="Browse for file to attach" />',
			ok: 'Create File',
			id: 'new_attachment_button',
			callback: function() {
				var fileInput = $('new_attachment');
				if(!(fileInput.files && fileInput.files.length)) {
					fd.error.alert('No file was selected.', 'Please select a file to upload.');
					return;
				}

				fd.getItem().sendMultipleFiles(fileInput.files);
				prompt.destroy();
			}
		});
	},

	promptPlugin: function() {
		var prompt = fd.showQuestion({
			title: 'Add a User Library',
			message: '<input type="text" name="new_library" id="new_library" placeholder="Search for libraries to include" />' +
					 '<input type="hidden" name="library_id_number" id="library_id_number" />',
			ok: 'Add Library',
			id: 'new_library_button',
			callback: function() {
				var lib_id = $('library_id_number').value;
				if(!lib_id) {
					fd.error.alert('No User Library selected', 'Please enter the name of an existing User Library');
					return;
				}

				fd.getItem().assignLibrary(lib_id)
				prompt.destroy();
			}
		});

		//setup Library autocomplete
		// autocomplete
		var autocomplete = new FlightDeck.Autocomplete({
			'url': settings.library_autocomplete_url
		});
	},

	toElement: function() {
		return this.element;
	}

});<|endoftext|>


<commit_before>/**
 * Gruntfile for freedom.js
 *
 * Here are the common tasks used:
 * build
 *  - Lint and compile freedom.js
 *  - (default Grunt task)
 *  - This must be run before ANY karma task (because of connect:default)
 *  - Unit tests only run on PhantomJS
 * demo
 *  - Build freedom.js, and start a web server for seeing demos at
 *    http://localhost:8000/demo
 * test
 *  - Build freedom.js, and run all unit tests on
 *    Chrome, Firefox, and PhantomJS
 * debug
 *  - Same as test, except keeps the browsers open
 *    and reruns tests on watched file changes.
 *  - Used to debug unit tests
 * ci
 *  - Do everything that Travis CI should do
 *  - Lint, compile, and unit test freedom.js on phantom.js
 *  - Run all tests on saucelabs.com
 *  - Report coverage to coveralls.io
 **/

var FILES = {
  srcCore: [
    'src/*.js',
      'src/link/*.js',
      'src/proxy/*.js',
      'interface/*.js'
  ],
  srcPlatform: [
    'providers/core/*.js'
  ],
  specCoreUnit: [
    'spec/src/*.spec.js'
  ],
  specPlatformUnit: [
    'spec/providers/core/**/*.spec.js'
  ],
  srcProvider: [
    'providers/oauth/*.js',
    'providers/social/websocket-server/*.js',
    'providers/social/loopback/*.js',
    'providers/storage/**/*.js',
    'providers/transport/**/*.js'
  ],
  specProviderUnit: [
    'spec/providers/social/**/*.unit.spec.js',
    'spec/providers/storage/**/*.unit.spec.js',
    'spec/providers/transport/**/*.unit.spec.js'
  ],
  specProviderIntegration: [
    'spec/providers/*.integration.spec.js',
    'spec/providers/storage/*.integration.spec.js'
  ],
  specAll: ['spec/**/*.spec.js'],
  freedom: [
    'freedom.js'
  ]
};

var CUSTOM_LAUNCHER = {
  sauce_chrome_34: {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: '34',
    platform: 'OS X 10.9'
  },
  sauce_chrome_33: {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: '33',
    platform: 'Windows 7'
  },
  sauce_firefox: {
    base: 'SauceLabs',
    browserName: 'firefox',
    version: '29'
  }
};

module.exports = function (grunt) {
  /**
   * GRUNT CONFIG
   **/
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
        // NOTE: need to run 'connect:default' to serve files
        configFile: 'karma.conf.js',
      },
      single: { singleRun: true, autoWatch: false },
      watch: {
        singleRun: false,
        autoWatch: true,
        reporters: ['progress', 'story'],
        preprocessors: {},
        coverageReporter: {}
      },
      phantom: {
        browsers: ['PhantomJS'],
        singleRun: true,
        autoWatch: false
      },
      saucelabs: {
        browsers: ['sauce_chrome_34', 'sauce_chrome_33'],//, 'sauce_firefox'],
        singleRun: true,
        autoWatch: false,
        reporters: ['dots', 'saucelabs'],
        sauceLabs: {
          testName: 'freedom.js',
          username: 'freedomjs',
          accessKey: process.env.SAUCEKEY,
          build: process.env.TRAVIS_BUILD_NUMBER,
          tags: [
            '<%= gitinfo.local.branch.current.name %>',
            '<%= gitinfo.local.branch.current.shortSHA %>',
            '<%= gitinfo.local.branch.current.currentUser %>',
            '<%= gitinfo.local.branch.current.lastCommitAuthor %>',
            '<%= gitinfo.local.branch.current.lastCommitTime %>',
          ],
        },
        customLaunchers: CUSTOM_LAUNCHER
      }
    },
    jshint: {
      beforeconcat: {
        files: { src: FILES.srcCore.concat(FILES.srcPlatform) },
        options: {
          jshintrc: true
        }
      },
      providers: FILES.srcProvider,
      demo: ['demo/**/*.js', '!demo/**/third-party/**'],
      options: {
        '-W069': true
      }
    },
    browserify: {
      freedom: {
        files: {
          'freedom.js': ['src/util/workerEntry.js']
        },
        options: {
          transform: ['folderify'],
          postBundleCB: function(err, src, next) {
            next(err, require('fs').readFileSync('src/util/header.txt') + src);
          }
        }
      },
      frame: {
        files: {
          'spec/helper/frame.js': ['src/util/frameEntry.js']
        },
        options: {
          transform: ['folderify']
        }
      },
      jasmine_unit: {
        files: {
          'spec.js': FILES.specCoreUnit.concat(
            FILES.specPlatformUnit,
            FILES.specProviderUnit),
        },
        options: {
          transform: ['folderify', ['browserify-istanbul', {
            // Note: bundle must be ignored,
            ignore: ['**/spec/**', '**/providers/**', '**/src/bundle.js']
          }]]
        }
      },
      jasmine_full: {
        files: {
          'spec.js': FILES.specCoreUnit.concat(
            FILES.specPlatformUnit,
            FILES.specProviderUnit,
            FILES.specProviderIntegration),
          'spec/helper/frame.js': ['src/util/frameEntry.js']
        },
        options: {
          transform: ['folderify', ['browserify-istanbul', {
            ignore: ['**/spec/**', '**/providers/**', '**/src/bundle.js']
          }]]
        }
      },
      options: {
        ignore: ['ws']
      }
    },
    clean: ['freedom.js', 'freedom.js.map', 'freedom.min.js', 'freedom.min.js.map', 'spec.js', 'spec/helper/frame.js'],
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        options: {
          paths: 'src/',
          outdir: 'tools/doc/'
        }
      }
    },
    coveralls: {
      report: {
        src: 'tools/coverage/PhantomJS**/*lcov.info'
      }
    },
    connect: {
      default: {
        options: {
          port: 8000,
          keepalive: false
        }
      },
      keepalive: {
        options: {
          port: 8000,
          keepalive: true
        }
      },
      demo: {
        options: {
          port: 8000,
          keepalive: true,
          base: ["./","demo/"],
          open: "http://localhost:8000/demo/"
        }
      }
    },
    gitinfo: {},
    bump: {
      options: {
        files: ['package.json'],
        commit: true,
        commitMessage: 'Release v%VERSION%',
        commitFiles: ['package.json'],
        createTag: true,
        tagName: 'v%VERSION%',
        tagMessage: 'Version %VERSION%',
        push: true,
        pushTo: 'origin'
      }
    },
    'npm-publish': {
      options: {
        // list of tasks that are required before publishing
        requires: [],
        // if the workspace is dirty, abort publishing (to avoid publishing local changes)
        abortIfDirty: true,
      }
    }

  });

  // Load tasks.
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-coveralls');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-gitinfo');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-npm');

  // Default tasks.
  grunt.registerTask('build', [
    'jshint',
    'browserify:freedom',
    'gitinfo',
    'connect:default'
  ]);
  grunt.registerTask('unit', [
    'browserify:frame',
    'browserify:jasmine_unit',
    'connect:default',
    'karma:phantom'
  ]);
  grunt.registerTask('test', [
    'jshint',
    'browserify:frame',
    'browserify:jasmine_full',
    'connect:default',
    'karma:single'
  ]);
  grunt.registerTask('debug', [
    'build',
    'browserify:jasmine_full',
    'karma:watch'
  ]);
  grunt.registerTask('demo', [
    'browserify:freedom',
    'connect:demo',
  ]);

  if (process.env.TRAVIS_JOB_NUMBER) {
    var jobParts = process.env.TRAVIS_JOB_NUMBER.split('.');
    //When run from Travis from jobs *.1
    if (jobParts.length > 1 && jobParts[1] == '1') {
      grunt.registerTask('ci', [
        'build',
        'karma:phantom',
        'karma:saucelabs',
        'coveralls:report'
      ]);
    } else {  //When run from Travis from jobs *.2, *.3, etc.
      grunt.registerTask('ci', [
        'build',
        'karma:phantom'
      ]);
    }
  } else {  //When run from command-line
    grunt.registerTask('ci', [
      'build',
      'karma:phantom',
      'karma:saucelabs',
    ]);
  }

  grunt.registerTask('release', function(arg) {
    if (arguments.length === 0) {
      arg = 'patch';
    }
    grunt.task.run([
      'default',
      'bump:'+arg,
      'npm-publish'
    ]);
  });

  grunt.registerTask('default', ['build', 'unit']);
};

module.exports.FILES = FILES;
module.exports.CUSTOM_LAUNCHER = CUSTOM_LAUNCHER;
<commit_msg>can't run connect twice in ci tests<commit_after>/**
 * Gruntfile for freedom.js
 *
 * Here are the common tasks used:
 * build
 *  - Lint and compile freedom.js
 *  - (default Grunt task)
 *  - This must be run before ANY karma task (because of connect:default)
 *  - Unit tests only run on PhantomJS
 * demo
 *  - Build freedom.js, and start a web server for seeing demos at
 *    http://localhost:8000/demo
 * test
 *  - Build freedom.js, and run all unit tests on
 *    Chrome, Firefox, and PhantomJS
 * debug
 *  - Same as test, except keeps the browsers open
 *    and reruns tests on watched file changes.
 *  - Used to debug unit tests
 * ci
 *  - Do everything that Travis CI should do
 *  - Lint, compile, and unit test freedom.js on phantom.js
 *  - Run all tests on saucelabs.com
 *  - Report coverage to coveralls.io
 **/

var FILES = {
  srcCore: [
    'src/*.js',
      'src/link/*.js',
      'src/proxy/*.js',
      'interface/*.js'
  ],
  srcPlatform: [
    'providers/core/*.js'
  ],
  specCoreUnit: [
    'spec/src/*.spec.js'
  ],
  specPlatformUnit: [
    'spec/providers/core/**/*.spec.js'
  ],
  srcProvider: [
    'providers/oauth/*.js',
    'providers/social/websocket-server/*.js',
    'providers/social/loopback/*.js',
    'providers/storage/**/*.js',
    'providers/transport/**/*.js'
  ],
  specProviderUnit: [
    'spec/providers/social/**/*.unit.spec.js',
    'spec/providers/storage/**/*.unit.spec.js',
    'spec/providers/transport/**/*.unit.spec.js'
  ],
  specProviderIntegration: [
    'spec/providers/*.integration.spec.js',
    'spec/providers/storage/*.integration.spec.js'
  ],
  specAll: ['spec/**/*.spec.js'],
  freedom: [
    'freedom.js'
  ]
};

var CUSTOM_LAUNCHER = {
  sauce_chrome_34: {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: '34',
    platform: 'OS X 10.9'
  },
  sauce_chrome_33: {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: '33',
    platform: 'Windows 7'
  },
  sauce_firefox: {
    base: 'SauceLabs',
    browserName: 'firefox',
    version: '29'
  }
};

module.exports = function (grunt) {
  /**
   * GRUNT CONFIG
   **/
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
        // NOTE: need to run 'connect:default' to serve files
        configFile: 'karma.conf.js',
      },
      single: { singleRun: true, autoWatch: false },
      watch: {
        singleRun: false,
        autoWatch: true,
        reporters: ['progress', 'story'],
        preprocessors: {},
        coverageReporter: {}
      },
      phantom: {
        browsers: ['PhantomJS'],
        singleRun: true,
        autoWatch: false
      },
      saucelabs: {
        browsers: ['sauce_chrome_34', 'sauce_chrome_33'],//, 'sauce_firefox'],
        singleRun: true,
        autoWatch: false,
        reporters: ['dots', 'saucelabs'],
        sauceLabs: {
          testName: 'freedom.js',
          username: 'freedomjs',
          accessKey: process.env.SAUCEKEY,
          build: process.env.TRAVIS_BUILD_NUMBER,
          tags: [
            '<%= gitinfo.local.branch.current.name %>',
            '<%= gitinfo.local.branch.current.shortSHA %>',
            '<%= gitinfo.local.branch.current.currentUser %>',
            '<%= gitinfo.local.branch.current.lastCommitAuthor %>',
            '<%= gitinfo.local.branch.current.lastCommitTime %>',
          ],
        },
        customLaunchers: CUSTOM_LAUNCHER
      }
    },
    jshint: {
      beforeconcat: {
        files: { src: FILES.srcCore.concat(FILES.srcPlatform) },
        options: {
          jshintrc: true
        }
      },
      providers: FILES.srcProvider,
      demo: ['demo/**/*.js', '!demo/**/third-party/**'],
      options: {
        '-W069': true
      }
    },
    browserify: {
      freedom: {
        files: {
          'freedom.js': ['src/util/workerEntry.js']
        },
        options: {
          transform: ['folderify'],
          postBundleCB: function(err, src, next) {
            next(err, require('fs').readFileSync('src/util/header.txt') + src);
          }
        }
      },
      frame: {
        files: {
          'spec/helper/frame.js': ['src/util/frameEntry.js']
        },
        options: {
          transform: ['folderify']
        }
      },
      jasmine_unit: {
        files: {
          'spec.js': FILES.specCoreUnit.concat(
            FILES.specPlatformUnit,
            FILES.specProviderUnit),
        },
        options: {
          transform: ['folderify', ['browserify-istanbul', {
            // Note: bundle must be ignored,
            ignore: ['**/spec/**', '**/providers/**', '**/src/bundle.js']
          }]]
        }
      },
      jasmine_full: {
        files: {
          'spec.js': FILES.specCoreUnit.concat(
            FILES.specPlatformUnit,
            FILES.specProviderUnit,
            FILES.specProviderIntegration),
          'spec/helper/frame.js': ['src/util/frameEntry.js']
        },
        options: {
          transform: ['folderify', ['browserify-istanbul', {
            ignore: ['**/spec/**', '**/providers/**', '**/src/bundle.js']
          }]]
        }
      },
      options: {
        ignore: ['ws']
      }
    },
    clean: ['freedom.js', 'freedom.js.map', 'freedom.min.js', 'freedom.min.js.map', 'spec.js', 'spec/helper/frame.js'],
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        options: {
          paths: 'src/',
          outdir: 'tools/doc/'
        }
      }
    },
    coveralls: {
      report: {
        src: 'tools/coverage/PhantomJS**/*lcov.info'
      }
    },
    connect: {
      default: {
        options: {
          port: 8000,
          keepalive: false
        }
      },
      keepalive: {
        options: {
          port: 8000,
          keepalive: true
        }
      },
      demo: {
        options: {
          port: 8000,
          keepalive: true,
          base: ["./","demo/"],
          open: "http://localhost:8000/demo/"
        }
      }
    },
    gitinfo: {},
    bump: {
      options: {
        files: ['package.json'],
        commit: true,
        commitMessage: 'Release v%VERSION%',
        commitFiles: ['package.json'],
        createTag: true,
        tagName: 'v%VERSION%',
        tagMessage: 'Version %VERSION%',
        push: true,
        pushTo: 'origin'
      }
    },
    'npm-publish': {
      options: {
        // list of tasks that are required before publishing
        requires: [],
        // if the workspace is dirty, abort publishing (to avoid publishing local changes)
        abortIfDirty: true,
      }
    }

  });

  // Load tasks.
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-coveralls');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-gitinfo');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-npm');

  // Default tasks.
  grunt.registerTask('build', [
    'jshint',
    'browserify:freedom',
    'gitinfo',
  ]);
  grunt.registerTask('unit', [
    'browserify:frame',
    'browserify:jasmine_unit',
    'connect:default',
    'karma:phantom'
  ]);
  grunt.registerTask('test', [
    'jshint',
    'browserify:frame',
    'browserify:jasmine_full',
    'connect:default',
    'karma:single'
  ]);
  grunt.registerTask('debug', [
    'build',
    'connect:default',
    'browserify:jasmine_full',
    'karma:watch'
  ]);
  grunt.registerTask('demo', [
    'browserify:freedom',
    'connect:demo',
  ]);

  if (process.env.TRAVIS_JOB_NUMBER) {
    var jobParts = process.env.TRAVIS_JOB_NUMBER.split('.');
    //When run from Travis from jobs *.1
    if (jobParts.length > 1 && jobParts[1] == '1') {
      grunt.registerTask('ci', [
        'build',
        'connect:default',
        'karma:phantom',
        'karma:saucelabs',
        'coveralls:report'
      ]);
    } else {  //When run from Travis from jobs *.2, *.3, etc.
      grunt.registerTask('ci', [
        'build',
        'connect:default',
        'karma:phantom'
      ]);
    }
  } else {  //When run from command-line
    grunt.registerTask('ci', [
      'build',
      'connect:default',
      'karma:phantom',
      'karma:saucelabs',
    ]);
  }

  grunt.registerTask('release', function(arg) {
    if (arguments.length === 0) {
      arg = 'patch';
    }
    grunt.task.run([
      'default',
      'bump:'+arg,
      'npm-publish'
    ]);
  });

  grunt.registerTask('default', ['build', 'unit']);
};

module.exports.FILES = FILES;
module.exports.CUSTOM_LAUNCHER = CUSTOM_LAUNCHER;
<|endoftext|>


<commit_before>/*jshint strict: true */
/*global require, assertEqual, assertTrue, assertFalse, fail */

////////////////////////////////////////////////////////////////////////////////
/// @brief test attribute naming
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");

var arangodb = require("org/arangodb");

var db = arangodb.db;
var wait = require("internal").wait;

// -----------------------------------------------------------------------------
// --SECTION--                                                        attributes
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test attributes
////////////////////////////////////////////////////////////////////////////////

function AttributesSuite () {
  "use strict";
  var ERRORS = require("internal").errors;
  var cn = "UnitTestsCollectionAttributes";
  var c = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      db._drop(cn);
      c = db._create(cn);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      c.unload();
      c.drop();
      c = null;
      wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief no attributes
////////////////////////////////////////////////////////////////////////////////

    testNoAttributes : function () {
      var doc = { };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);
      delete d1.error;

      assertEqual(d1, d2);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief empty attribute name
////////////////////////////////////////////////////////////////////////////////

    testEmptyAttribute : function () {
      var doc = { "" : "foo" };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);
      delete d1.error;

      var i;
      for (i in d2) {
        if (d2.hasOwnProperty(i)) {
          assertTrue(i !== "");
        }
      }

      assertEqual(d1, d2);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief query empty attribute name
////////////////////////////////////////////////////////////////////////////////

    testQueryEmptyAttribute : function () {
      var doc = { "" : "foo" };
      c.save(doc);

      var docs = c.toArray();
      assertEqual(1, docs.length);
      var d = docs[0];

      var i;
      for (i in d) {
        if (d.hasOwnProperty(i)) {
          assertTrue(i !== "");
        }
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief "numeric" attribute names
////////////////////////////////////////////////////////////////////////////////

    testNumericAttributes : function () {
      var doc = { "12345" : 1, "6669" : "foo", "7734" : true };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(1, d2["12345"]);
      assertEqual("foo", d2["6669"]);
      assertEqual(true, d2["7734"]);

      assertEqual(undefined, d2["999"]);

      d2 = c.toArray()[0];
      assertEqual(1, d2["12345"]);
      assertEqual("foo", d2["6669"]);
      assertEqual(true, d2["7734"]);

      assertEqual(undefined, d2["999"]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief reserved attribute names
////////////////////////////////////////////////////////////////////////////////

    testReservedAttributes : function () {
      var doc = {
        "_id" : "foo",
        "_rev": "99",
        "_key" : "meow",
        "_from" : "33",
        "_to": "99",
        "_test" : false,
        "_boom" : "bang"
      };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual("meow", d1._key);
      assertEqual("meow", d2._key);
      assertEqual(cn + "/meow", d1._id);
      assertEqual(cn + "/meow", d2._id);
      assertEqual(d1._rev, d2._rev);
      assertFalse(d2._test);
      assertEqual("bang", d2._boom);
      assertFalse(d2.hasOwnProperty("_from"));
      assertFalse(d2.hasOwnProperty("_to"));

      // user specified _rev value must have been ignored
      assertTrue(d1._rev !== "99");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief reserved attribute names
////////////////////////////////////////////////////////////////////////////////

    testEmbeddedReservedAttributes : function () {
      var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false };

      c.save({ _key: "mydoc", _embedded: doc });
      var d = c.document("mydoc");

      assertEqual(cn + "/mydoc", d._id);
      assertEqual("mydoc", d._key);
      assertEqual("foo", d._embedded._id);
      assertEqual("99", d._embedded._rev);
      assertEqual("meow", d._embedded._key);
      assertEqual("33", d._embedded._from);
      assertEqual("99", d._embedded._to);
      assertFalse(d._embedded._test);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief attribute name with special chars
////////////////////////////////////////////////////////////////////////////////

    testSpecialAttributes : function () {
      var doc = { "-meow-" : 1, "mötör" : 2, " " : 3, "\t" : 4, "\r" : 5, "\n" : 6 };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(1, d2["-meow-"]);
      assertEqual(2, d2["mötör"]);
      assertEqual(3, d2[" "]);
      assertEqual(4, d2["\t"]);
      assertEqual(5, d2["\r"]);
      assertEqual(6, d2["\n"]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute list
////////////////////////////////////////////////////////////////////////////////

    testSharedAttributesList : function () {
      var sub = { name: 1 };
      var doc = { a: [ sub, sub ] };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(sub, d2.a[0]);
      assertEqual(sub, d2.a[1]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute object
////////////////////////////////////////////////////////////////////////////////

    testSharedAttributesObject : function () {
      var sub = { name: 1 };
      var doc = { a: sub, b: sub };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(sub, d2.a);
      assertEqual(sub, d2.a);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute list
////////////////////////////////////////////////////////////////////////////////

    testCyclicAttributesList : function () {
      var sub = {};
      var doc = { a: [ sub ] };

      sub.cycle = doc;

      try {
        c.save(doc);
        fail();
      }
      catch (err) {
        if (err && err.errorNum) {
          // we're on the server
          assertEqual(ERRORS.ERROR_ARANGO_SHAPER_FAILED.code, err.errorNum);
        }
        else {
          // we're on the client, and the JS engine just throws a generic type error
          assertTrue(true);
        }

      }
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////

jsunity.run(AttributesSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:
<commit_msg>added tests for attribute names and values containing specifically dollar signs<commit_after>/*jshint strict: true */
/*global require, assertEqual, assertTrue, assertFalse, fail */

////////////////////////////////////////////////////////////////////////////////
/// @brief test attribute naming
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");

var arangodb = require("org/arangodb");

var db = arangodb.db;
var wait = require("internal").wait;

// -----------------------------------------------------------------------------
// --SECTION--                                                        attributes
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test attributes
////////////////////////////////////////////////////////////////////////////////

function AttributesSuite () {
  "use strict";
  var ERRORS = require("internal").errors;
  var cn = "UnitTestsCollectionAttributes";
  var c = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      db._drop(cn);
      c = db._create(cn);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      c.unload();
      c.drop();
      c = null;
      wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief no attributes
////////////////////////////////////////////////////////////////////////////////

    testNoAttributes : function () {
      var doc = { };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);
      delete d1.error;

      assertEqual(d1, d2);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief empty attribute name
////////////////////////////////////////////////////////////////////////////////

    testEmptyAttribute : function () {
      var doc = { "" : "foo" };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);
      delete d1.error;

      var i;
      for (i in d2) {
        if (d2.hasOwnProperty(i)) {
          assertTrue(i !== "");
        }
      }

      assertEqual(d1, d2);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief query empty attribute name
////////////////////////////////////////////////////////////////////////////////

    testQueryEmptyAttribute : function () {
      var doc = { "" : "foo" };
      c.save(doc);

      var docs = c.toArray();
      assertEqual(1, docs.length);
      var d = docs[0];

      var i;
      for (i in d) {
        if (d.hasOwnProperty(i)) {
          assertTrue(i !== "");
        }
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief dollar signs
////////////////////////////////////////////////////////////////////////////////

    testDollarSignAttributes : function () {
      var doc = { "$foo" : "$bar", "$bar" : "$baz" };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual("$bar", d2.$foo);
      assertEqual("$baz", d2.$bar);
      assertEqual(undefined, d2.$boo);

      d2 = c.toArray()[0];
      assertEqual("$bar", d2.$foo);
      assertEqual("$baz", d2.$bar);

      c.update(d1, { "$baz" : "$barbaz$" });
      d2 = c.document(d1._id);
      assertEqual("$bar", d2.$foo);
      assertEqual("$baz", d2.$bar);
      assertEqual("$barbaz$", d2.$baz);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief "numeric" attribute names
////////////////////////////////////////////////////////////////////////////////

    testNumericAttributes : function () {
      var doc = { "12345" : 1, "6669" : "foo", "7734" : true };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(1, d2["12345"]);
      assertEqual("foo", d2["6669"]);
      assertEqual(true, d2["7734"]);

      assertEqual(undefined, d2["999"]);

      d2 = c.toArray()[0];
      assertEqual(1, d2["12345"]);
      assertEqual("foo", d2["6669"]);
      assertEqual(true, d2["7734"]);

      assertEqual(undefined, d2["999"]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief reserved attribute names
////////////////////////////////////////////////////////////////////////////////

    testReservedAttributes : function () {
      var doc = {
        "_id" : "foo",
        "_rev": "99",
        "_key" : "meow",
        "_from" : "33",
        "_to": "99",
        "_test" : false,
        "_boom" : "bang"
      };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual("meow", d1._key);
      assertEqual("meow", d2._key);
      assertEqual(cn + "/meow", d1._id);
      assertEqual(cn + "/meow", d2._id);
      assertEqual(d1._rev, d2._rev);
      assertFalse(d2._test);
      assertEqual("bang", d2._boom);
      assertFalse(d2.hasOwnProperty("_from"));
      assertFalse(d2.hasOwnProperty("_to"));

      // user specified _rev value must have been ignored
      assertTrue(d1._rev !== "99");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief reserved attribute names
////////////////////////////////////////////////////////////////////////////////

    testEmbeddedReservedAttributes : function () {
      var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false };

      c.save({ _key: "mydoc", _embedded: doc });
      var d = c.document("mydoc");

      assertEqual(cn + "/mydoc", d._id);
      assertEqual("mydoc", d._key);
      assertEqual("foo", d._embedded._id);
      assertEqual("99", d._embedded._rev);
      assertEqual("meow", d._embedded._key);
      assertEqual("33", d._embedded._from);
      assertEqual("99", d._embedded._to);
      assertFalse(d._embedded._test);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief attribute name with special chars
////////////////////////////////////////////////////////////////////////////////

    testSpecialAttributes : function () {
      var doc = { "-meow-" : 1, "mötör" : 2, " " : 3, "\t" : 4, "\r" : 5, "\n" : 6 };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(1, d2["-meow-"]);
      assertEqual(2, d2["mötör"]);
      assertEqual(3, d2[" "]);
      assertEqual(4, d2["\t"]);
      assertEqual(5, d2["\r"]);
      assertEqual(6, d2["\n"]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute list
////////////////////////////////////////////////////////////////////////////////

    testSharedAttributesList : function () {
      var sub = { name: 1 };
      var doc = { a: [ sub, sub ] };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(sub, d2.a[0]);
      assertEqual(sub, d2.a[1]);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute object
////////////////////////////////////////////////////////////////////////////////

    testSharedAttributesObject : function () {
      var sub = { name: 1 };
      var doc = { a: sub, b: sub };

      var d1 = c.save(doc);
      var d2 = c.document(d1._id);

      assertEqual(sub, d2.a);
      assertEqual(sub, d2.a);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief shared attribute list
////////////////////////////////////////////////////////////////////////////////

    testCyclicAttributesList : function () {
      var sub = {};
      var doc = { a: [ sub ] };

      sub.cycle = doc;

      try {
        c.save(doc);
        fail();
      }
      catch (err) {
        if (err && err.errorNum) {
          // we're on the server
          assertEqual(ERRORS.ERROR_ARANGO_SHAPER_FAILED.code, err.errorNum);
        }
        else {
          // we're on the client, and the JS engine just throws a generic type error
          assertTrue(true);
        }

      }
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////

jsunity.run(AttributesSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {
	// Project configuration.
	grunt.initConfig({
	    pkg: grunt.file.readJSON('package.json'),
		stylus: {
			compile: {
				options: {
					'paths': [
					    'node_modules/',    // nib
					    'styl/'             // Individual components
					]
				},
				files: {
					'build/css/io.css': 'styl/iOCSS.styl'
				}
			}
		},
		concat: {
			options: {
				banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
						'* <%= pkg.homepage %>/\n' +
						'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>; Licensed <%= pkg.license %> */\n'
			},
			iocss: {
				files: {
					'build/css/io.css': 'build/css/io.css'
				}
			}
		},
		copy: {
			examples: {
				expand: true,
				cwd: 'examples/',
				src: ['**'],
				dest: 'build/examples/'
			}
		},
		watch: {
			stylus: {
				files: ['styl/*', 'styl/themes/*'],
				tasks: 'stylus'
			}
		}
	});

	// Default task
	grunt.registerTask('default', ['stylus', 'concat', 'copy']);

    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-stylus');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
<commit_msg>Copy examples when they change<commit_after>/*global module:false*/
module.exports = function(grunt) {
	// Project configuration.
	grunt.initConfig({
	    pkg: grunt.file.readJSON('package.json'),
		stylus: {
			compile: {
				options: {
					'paths': [
					    'node_modules/',    // nib
					    'styl/'             // Individual components
					]
				},
				files: {
					'build/css/io.css': 'styl/iOCSS.styl'
				}
			}
		},
		concat: {
			options: {
				banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
						'* <%= pkg.homepage %>/\n' +
						'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>; Licensed <%= pkg.license %> */\n'
			},
			iocss: {
				files: {
					'build/css/io.css': 'build/css/io.css'
				}
			}
		},
		copy: {
			examples: {
				expand: true,
				cwd: 'examples/',
				src: ['**'],
				dest: 'build/examples/'
			}
		},
		watch: {
			stylus: {
				files: ['styl/*', 'styl/themes/*'],
				tasks: 'stylus'
			},
			examples: {
				files: [ 'examples/**' ],
				tasks: 'copy'
			}
		}
	});

	// Default task
	grunt.registerTask('default', ['stylus', 'concat', 'copy']);

    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-stylus');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
<|endoftext|>


<commit_before>import {promisify} from 'node-promise-es6';
import * as fse from 'fs-extra';

// export * from 'fs-extra';
/* eslint-disable */
export const copySync = fse.copySync;
export const createOutputStream = fse.createOutputStream;
export const emptyDirSync = fse.emptyDirSync;
export const ensureFileSync = fse.ensureFileSync;
export const ensureDirSync = fse.ensureDirSync;
export const ensureLinkSync = fse.ensureLinkSync;
export const ensureSymlinkSync = fse.ensureSymlinkSync;
export const mkdirsSync = fse.mkdirsSync;
export const outputFileSync = fse.outputFileSync;
export const outputJsonSync = fse.outputJsonSync;
export const readJsonSync = fse.readJsonSync;
export const removeSync = fse.removeSync;
export const writeJsonSync = fse.writeJsonSync;
/* eslint-enable */

export const copy = promisify(fse.copy);
export const emptyDir = promisify(fse.emptyDir);
export const ensureFile = promisify(fse.ensureFile);
export const ensureDir = promisify(fse.ensureDir);
export const ensureLink = promisify(fse.ensureLink);
export const ensureSymlink = promisify(fse.ensureSymlink);
export const mkdirs = promisify(fse.mkdirs);
export const move = promisify(fse.move);
export const outputFile = promisify(fse.outputFile);
export const outputJson = promisify(fse.outputJson);
export const readJson = promisify(fse.readJson);
export const remove = promisify(fse.remove);
export const writeJson = promisify(fse.writeJson);
<commit_msg>Also re-export fse.walk<commit_after>import {promisify} from 'node-promise-es6';
import * as fse from 'fs-extra';

// export * from 'fs-extra';
/* eslint-disable */
export const copySync = fse.copySync;
export const createOutputStream = fse.createOutputStream;
export const emptyDirSync = fse.emptyDirSync;
export const ensureFileSync = fse.ensureFileSync;
export const ensureDirSync = fse.ensureDirSync;
export const ensureLinkSync = fse.ensureLinkSync;
export const ensureSymlinkSync = fse.ensureSymlinkSync;
export const mkdirsSync = fse.mkdirsSync;
export const outputFileSync = fse.outputFileSync;
export const outputJsonSync = fse.outputJsonSync;
export const readJsonSync = fse.readJsonSync;
export const removeSync = fse.removeSync;
export const walk = fse.walk;
export const writeJsonSync = fse.writeJsonSync;
/* eslint-enable */

export const copy = promisify(fse.copy);
export const emptyDir = promisify(fse.emptyDir);
export const ensureFile = promisify(fse.ensureFile);
export const ensureDir = promisify(fse.ensureDir);
export const ensureLink = promisify(fse.ensureLink);
export const ensureSymlink = promisify(fse.ensureSymlink);
export const mkdirs = promisify(fse.mkdirs);
export const move = promisify(fse.move);
export const outputFile = promisify(fse.outputFile);
export const outputJson = promisify(fse.outputJson);
export const readJson = promisify(fse.readJson);
export const remove = promisify(fse.remove);
export const writeJson = promisify(fse.writeJson);
<|endoftext|>