var angularGlobal = { 'typeOf':function(obj){ if (obj === _null) return $null; var type = typeof obj; if (type == $object) { if (obj instanceof Array) return $array; if (isDate(obj)) return $date; if (obj.nodeType == 1) return $element; } return type; } }; /** * @workInProgress * @ngdoc overview * @name angular.Object * @function * * @description * Utility functions for manipulation with JavaScript objects. * * These functions are exposed in two ways: * * - **in angular expressions**: the functions are bound to all objects and augment the Object * type. The names of these methods are prefixed with `$` character to minimize naming collisions. * To call a method, invoke the function without the first argument, e.g, `myObject.$foo(param2)`. * * - **in JavaScript code**: the functions don't augment the Object type and must be invoked as * functions of `angular.Object` as `angular.Object.foo(myObject, param2)`. * */ var angularCollection = { 'copy': copy, 'size': size, 'equals': equals }; var angularObject = { 'extend': extend }; /** * @workInProgress * @ngdoc overview * @name angular.Array * * @description * Utility functions for manipulation with JavaScript Array objects. * * These functions are exposed in two ways: * * - **in angular expressions**: the functions are bound to the Array objects and augment the Array * type as array methods. The names of these methods are prefixed with `$` character to minimize * naming collisions. To call a method, invoke `myArrayObject.$foo(params)`. * * - **in JavaScript code**: the functions don't augment the Array type and must be invoked as * functions of `angular.Array` as `angular.Array.foo(myArrayObject, params)`. * */ var angularArray = { /** * @workInProgress * @ngdoc function * @name angular.Array.indexOf * @function * * @description * Determines the index of `value` in `array`. * * Note: this function is used to augment the Array type in angular expressions. See * {@link angular.Array} for more info. * * @param {Array} array Array to search. * @param {*} value Value to search for. * @returns {number} The position of the element in `array`. The position is 0-based. `-1` is returned if the value can't be found. * * @example

Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. @scenario it('should correctly calculate the initial index', function() { expect(binding('books.$indexOf(bookName)')).toBe('2'); }); it('should recalculate', function() { input('bookName').enter('foo'); expect(binding('books.$indexOf(bookName)')).toBe('-1'); input('bookName').enter('Moby Dick'); expect(binding('books.$indexOf(bookName)')).toBe('0'); }); */ 'indexOf': indexOf, /** * @workInProgress * @ngdoc function * @name angular.Array.sum * @function * * @description * This function calculates the sum of all numbers in `array`. If the `expressions` is supplied, * it is evaluated once for each element in `array` and then the sum of these values is returned. * * Note: this function is used to augment the Array type in angular expressions. See * {@link angular.Array} for more info. * * @param {Array} array The source array. * @param {(string|function())=} expression Angular expression or a function to be evaluated for each * element in `array`. The array element becomes the `this` during the evaluation. * @returns {number} Sum of items in the array. * * @example
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}} [X]
add item Total: {{invoice.items.$sum('qty*cost') | currency}}
@scenario //TODO: these specs are lame because I had to work around issues #164 and #167 it('should initialize and calculate the totals', function() { expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3); expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)). toEqual(['$99.50']); expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); }); it('should add an entry and recalculate', function() { element('.doc-example a:contains("add item")').click(); using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)). toEqual(['$2,000.00']); expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); }); */ 'sum':function(array, expression) { var fn = angular['Function']['compile'](expression); var sum = 0; for (var i = 0; i < array.length; i++) { var value = 1 * fn(array[i]); if (!isNaN(value)){ sum += value; } } return sum; }, /** * @workInProgress * @ngdoc function * @name angular.Array.remove * @function * * @description * Modifies `array` by rem
#!/usr/bin/env python
"""
Useful tool to run the test suite for rest_framework and generate a coverage report.
"""

# http://ericholscher.com/blog/2009/jun/29/enable-setuppy-test-your-django-apps/
# http://www.travisswicegood.com/2010/01/17/django-virtualenv-pip-and-fabric/
# http://code.djangoproject.com/svn/django/trunk/tests/runtests.py
import os
import sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'rest_framework.runtests.settings'

from coverage import coverage


def main():
    """Run the tests for rest_framework and generate a coverage report."""

    cov = coverage()
    cov.erase()
    cov.start()

    from django.conf import settings
    from django.test.utils import get_runner
    TestRunner = get_runner(settings)

    if hasattr(TestRunner, 'func_name'):
        # Pre 1.2 test runners were just functions,
        # and did not support the 'failfast' option.
        import warnings
        warnings.warn(
            'Function-based test runners are deprecated. Test runners should be classes with a run_tests() method.',
            DeprecationWarning
        )
        failures = TestRunner(['rest_framework'])
    else:
        test_runner = TestRunner()
        failures = test_runner.run_tests(['rest_framework'])
    cov.stop()

    # Discover the list of all modules that we should test coverage for
    import rest_framework

    project_dir = os.path.dirname(rest_framework.__file__)
    cov_files = []

    for (path, dirs, files) in os.walk(project_dir):
        # Drop tests and runtests directories from the test coverage report
        if os.path.basename(path) == 'tests' or os.path.basename(path) == 'runtests':
            continue

        # Drop the compat module from coverage, since we're not interested in the coverage
        # of a module which is specifically for resolving environment dependant imports.
        # (Because we'll end up getting different coverage reports for it for each environment)
        if 'compat.py' in files:
            files.remove('compat.py')

        cov_files.extend([os.path.join(path, file) for file in files if file.endswith('.py')])

    cov.report(cov_files)
    if '--html' in sys.argv:
        cov.html_report(cov_files, directory='coverage')
    sys.exit(failures)

if __name__ == '__main__':
    main()
[add 'John'] [add 'Mary']
people = {{people}}
@scenario beforeEach(function() { expect(binding('people')).toBe('people = []'); }); it('should create an empty record when "add empty" is clicked', function() { element('.doc-example a:contains("add empty")').click(); expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]'); }); it('should create a "John" record when "add \'John\'" is clicked', function() { element('.doc-example a:contains("add \'John\'")').click(); expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); }); it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { element('.doc-example a:contains("add \'Mary\'")').click(); expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); }); it('should delete a record when "X" is clicked', function() { element('.doc-example a:contains("add empty")').click(); element('.doc-example li a:contains("X"):first').click(); expect(binding('people')).toBe('people = []'); }); */ 'add':function(array, value) { array.push(isUndefined(value)? {} : value); return array; }, /** * @workInProgress * @ngdoc function * @name angular.Array.count * @function * * @description * Determines the number of elements in an array. Optionally it will count only those elements * for which the `condition` evaluets to `true`. * * Note: this function is used to augment the Array type in angular expressions. See * {@link angular.Array} for more info. * * @param {Array} array The array to count elements in. * @param {(Function()|string)=} condition A function to be evaluated or angular expression to be * compiled and evaluated. The element that is currently being iterated over, is exposed to * the `condition` as `this`. * @returns {number} Number of elements in the array (for which the condition evaluates to true). * * @example

     
     

Number of items which have one point: {{ items.$count('points==1') }}

Number of items which have more than one point: {{items.$count('points>1')}}

@scenario it('should calculate counts', function() { expect(binding('items.$count(\'points==1\')')).toEqual(2); expect(binding('items.$count(\'points>1\')')).toEqual(1); }); it('should recalculate when updated', function() { using('.doc-example li:first-child').input('item.points').enter('23'); expect(binding('items.$count(\'points==1\')')).toEqual(1); expect(binding('items.$count(\'points>1\')')).toEqual(2); }); */ 'count':function(array, condition) { if (!condition) return array.length; var fn = angular['Function']['compile'](condition), count = 0; foreach(array, function(value){ if (fn(value)) { count ++; } }); return count; }, /** * @workInProgress * @ngdoc function * @name angular.Array.orderBy * @function * * @description * Orders `array` by the `expression` predicate. * * Note: this function is used to augment the Array type in angular expressions. See * {@link angular.Array} for more info. * * @param {Array} array The array to sort. * @param {function()|string|Array.<(function()|string)>} expression A predicate to be used by the * comparator to determine the order of elements. * * Can be one of: * * - `function`: JavaScript's Array#sort comparator function * - `string`: angular expression which evaluates to an object to order by, such as 'name' to * sort by a property called 'name'. Optionally prefixed with `+` or `-` to control ascending * or descending sort order (e.g. +name or -name). * - `Array`: array of function or string predicates, such that a first predicate in the array * is used for sorting, but when the items are equivalent next predicate is used. * * @param {boolean=} descend TODO * @returns {Array} Sorted copy of the source array. * * @example
Sorting predicate = {{predicate}}

Name (^) Phone (^) Age (^)
{{friend.name}} {{friend.phone}} {{friend.age}}
@scenario it('should be reverse ordered by aged', function() { expect(binding('predicate')).toBe('Sorting predicate = -age'); expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). toEqual(['35', '29', '21', '19', '10']); expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); }); it('should reorder the table when user selects different predicate', function() { element('.doc-example a:contains("Name")').click(); expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). toEqual(['35', '10', '29', '19', '21']); element('.doc-example a:contains("Phone")+a:contains("^")').click(); expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')). toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); }); */ //TODO: WTH is descend param for and how/when it should be used, how is it affected by +/- in // predicate? the code below is impossible to read and specs are not very good. 'orderBy':function(array, expression, descend) { expression = isArray(expression) ? expression: [expression]; expression = map(expression, function($){ var descending = false, get = $ || identity; if (isString($)) { if (($.charAt(0) == '+' || $.charAt(0) == '-')) { descending = $.charAt(0) == '-'; $ = $.substring(1); } get = expressionCompile($).fnSelf; } return reverse(function(a,b){ return compare(get(a),get(b)); }, descending); }); var arrayCopy = []; for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } return arrayCopy.sort(reverse(comparator, descend)); function comparator(o1, o2){ for ( var i = 0; i < expression.length; i++) { var comp = expression[i](o1, o2); if (comp !== 0) return comp; } return 0; } function reverse(comp, descending) { return toBoolean(descending) ? function(a,b){return comp(b,a);} : comp; } function compare(v1, v2){ var t1 = typeof v1; var t2 = typeof v2; if (t1 == t2) { if (t1 == "string") v1 = v1.toLowerCase(); if (t1 == "string") v2 = v2.toLowerCase(); if (v1 === v2) return 0; return v1 < v2 ? -1 : 1; } else { return t1 < t2 ? -1 : 1; } } }, /** * @workInProgress * @ngdoc function * @name angular.Array.limitTo * @function * * @description * Creates a new array containing only the first, or last `limit` number of elements of the * source `array`. * * Note: this function is used to augment the Array type in angular expressions. See * {@link angular.Array} for more info. * * @param {Array} array Source array to be limited. * @param {string|Number} limit The length of the returned array. If the number is positive, the * first `limit` items from the source array will be copied, if the number is negative, the * last `limit` items will be copied. * @returns {Array} New array of length `limit`. * */ limitTo: function(array, limit) { limit = parseInt(limit, 10); var out = [], i, n; if (limit > 0) { i = 0; n = limit; } else { i = array.length + limit; n = array.length; } for (; i