<!DOCTYPE html>
<title>IDBCursor direction - object store</title>
<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
<link rel=assert title="If position is defined, and source is an object store, the record's key is greater than position.">
<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
<link rel=assert title="If position is defined, and source is an object store, the record's key is less than position.">
<link rel=assert title="Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.">
<link rel=assert title="Set cursor's key to found record's key.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>

<script>
    var records = [ "Alice", "Bob", "Greg" ];
    var directions = ["next", "prev", "nextunique", "prevunique"];
    var tests = {};

    directions.forEach(function(dir) {
        tests[dir] = async_test(document.title + ' - ' + dir);
    });

    var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());

    open_rq.onupgradeneeded = function(e) {
        var objStore = e.target.result.createObjectStore("test");

        for (var i = 0; i < records.length; i++)
            objStore.add(records[i], records[i]);
    };

    open_rq.onsuccess = function(e) {
        var db = e.target.result;
        db.onerror = fail_helper("db.onerror");


        // The tests
        testdir('next',       ['Alice', 'Bob', 'Greg']);
        testdir('prev',       ['Greg', 'Bob', 'Alice']);
        testdir('nextunique', ['Alice', 'Bob', 'Greg']);
        testdir('prevunique', ['Greg', 'Bob', 'Alice']);


        // Test function
        function testdir(dir, expect) {
            var count = 0;
            var t = tests[dir];
            var rq = db.transaction("test").objectStore("test").openCursor(undefined, dir);
            rq.onsuccess = t.step_func(function(e) {
                var cursor = e.target.result;
                if (!cursor) {
                    assert_equals(count, expect.length, "cursor runs");
                    t.done();
                }
                assert_equals(cursor.value, expect[count], "cursor.value");
                count++;
                cursor.continue();
            });
            rq.onerror = t.step_func(function(e) {
                e.preventDefault();
                e.stopPropagation();
                assert_unreached("rq.onerror - " + e.message);
            });
        }
    };

    // Fail handling
    function fail_helper(name) {
        return function() {
            directions.forEach(function(dir) {
                tests[dir].step(function() { assert_unreached(name); });
            });
        };
    }
    open_rq.onblocked = fail_helper('open_rq.onblocked');
    open_rq.onerror = fail_helper('open_rq.onerror');
</script>

<div id=log> </div>
