<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<style>
#dropTarget, #dragMe { text-align: center; display: table-cell; vertical-align: middle }
#dropTarget {width: 256px; height: 256px; border: 1px dashed}
#dragMe {-webkit-user-drag: element; -webkit-user-select: none; background: #ff0000; width: 64px; height: 64px; color: white}
</style>
<script>
    var dragMe;
    var dropTarget;
    var effectAllowedElem;
    var dropEffectElem;
    var consoleElm;
    var event;
    
    window.onload = function()
    {
        dragMe = document.getElementById("dragMe");
        dropTarget = document.getElementById("dropTarget");
        consoleElm = document.getElementById("console");
        
        if (!dragMe || !dropTarget || !consoleElm)
            return;
        
        dragMe.ondragstart = dragStart;
        dragMe.ondragend = dragEnd;
        
        dropTarget.ondragenter = dragEntered;
        dropTarget.ondragover = dragOver;
        dropTarget.ondrop = drop;
        
        runTest();
    }
    
    function dragStart(e)
    {
        var validEffectAllowedList = ["all", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "none", "uninitialized"];
        var effectAllowedListToTest = ["all", "copy", "bogus", "copyLink", "wrong", "copyMove", "linkCopyMove", "link",
            "linkMove", "move", "none", "uninitialized", "dummy", "bogus", "fake", "illegal"];
        
        event = e;
        
        for (var i = 0; i < effectAllowedListToTest.length; i++) {
            var effectAllowedBefore = e.dataTransfer.effectAllowed;
            e.dataTransfer.effectAllowed = effectAllowedListToTest[i];
            if (validEffectAllowedList.indexOf(effectAllowedListToTest[i]) != -1)
                shouldBeEqualToString("event.dataTransfer.effectAllowed", effectAllowedListToTest[i]);
            else
                shouldBeEqualToString("event.dataTransfer.effectAllowed", effectAllowedBefore);
        }
        
        e.dataTransfer.setData('Text', e.target.textContent);
    }
    
    function dragEnd(e)
    {
        return;
    }
    
    function dragEntered(e)
    {
        dragEnteredAndUpdated(e);
    }
    
    function dragOver(e)
    {
        dragEnteredAndUpdated(e);
    }
    
    function dragEnteredAndUpdated(e)
    {
        var validDropEffectList = ["none", "copy", "link", "move", "link"];
        var dropEffectListToTest = ["all", "copy", "bogus", "copyLink", "wrong", "copyMove", "linkCopyMove", "link",
            "linkMove", "move", "none", "uninitialized", "dummy", "bogus", "fake", "illegal"];
        
        event = e;
        
        for (var i = 0; i < dropEffectListToTest.length; i++) {
            var dropEffectBefore = e.dataTransfer.dropEffect;
            e.dataTransfer.dropEffect = dropEffectListToTest[i];

            if (validDropEffectList.indexOf(dropEffectListToTest[i]) != -1)
                shouldBeEqualToString("event.dataTransfer.dropEffect", dropEffectListToTest[i]);
            else
                shouldBeEqualToString("event.dataTransfer.dropEffect", dropEffectBefore);

        }

        cancelDrag(e);
    }
    
    function drop(e)
    {
        cancelDrag(e);
    }
    
    function cancelDrag(e)
    {
        e.preventDefault();
    }

    function runTest()
    {
        if (!window.eventSender)
            return;
            
        if (window.testRunner)
            testRunner.dumpAsText();
            
        var startX = dragMe.offsetLeft + 10;
        var startY = dragMe.offsetTop + dragMe.offsetHeight / 2;
        var endX = dropTarget.offsetLeft + 10;
        var endY = dropTarget.offsetTop + dropTarget.offsetHeight / 2;
        
        eventSender.mouseMoveTo(startX, startY);
        eventSender.mouseDown();
        eventSender.leapForward(100);
        eventSender.mouseMoveTo(endX, endY);
        eventSender.mouseUp();

        var testContainer = document.getElementById("test-container");
        if (testContainer)
            document.body.removeChild(testContainer);
        debug('<br /><span class="pass">TEST COMPLETE</span>');
    }
</script>
</head>
<body>
    <p id="description"></p>
    <div id="test-container">
        <br/><br/>
        <div id="dropTarget">Drop the red square onto me.<br/><br/></div>
        <hr/>
        <p>Items that can be dragged to the drop target:</p>
        <div id="dragMe" draggable="true">Square</div>
        <hr/>
    </div>
    <div id="console"></div>
    <script>
        description("This test checks that effectAllowed and dropEffect cannot be set to values that aren't defined in the spec");
    </script>
</body>
</html>
