123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // Copyright 2009 The Closure Library Authors. All Rights Reserved.
- //
- // 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.
- goog.provide('goog.events.PasteHandlerTest');
- goog.setTestOnly('goog.events.PasteHandlerTest');
- goog.require('goog.dom');
- goog.require('goog.events');
- goog.require('goog.events.BrowserEvent');
- goog.require('goog.events.EventTarget');
- goog.require('goog.events.EventType');
- goog.require('goog.events.KeyCodes');
- goog.require('goog.events.PasteHandler');
- goog.require('goog.testing.MockClock');
- goog.require('goog.testing.jsunit');
- goog.require('goog.userAgent');
- function setUp() {
- textarea = new goog.events.EventTarget();
- textarea.value = '';
- clock = new goog.testing.MockClock(true);
- handler = new goog.events.PasteHandler(textarea);
- pasted = false;
- goog.events.listen(
- handler, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- }
- function tearDown() {
- textarea.dispose();
- handler.dispose();
- clock.dispose();
- }
- function newBrowserEvent(type) {
- if (goog.isString(type)) {
- return new goog.events.BrowserEvent({type: type});
- } else {
- return new goog.events.BrowserEvent(type);
- }
- }
- function testDispatchingPasteEventSupportedByAFewBrowsersWork() {
- if (!goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- var handlerThatSupportsPasteEvents = new goog.events.PasteHandler(textarea);
- // user clicks on the textarea and give it focus
- goog.events.listen(
- handlerThatSupportsPasteEvents, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- textarea.dispatchEvent(newBrowserEvent('paste'));
- assertTrue(pasted);
- }
- function testJustTypingDoesntFirePasteEvent() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- // user clicks on the textarea and give it focus
- textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
- assertFalse(pasted);
- // user starts typing
- textarea.dispatchEvent(newBrowserEvent({
- type: goog.events.EventType.KEYDOWN,
- keyCode: goog.events.KeyCodes.A
- }));
- textarea.value = 'a';
- assertFalse(pasted);
- // still typing
- textarea.dispatchEvent(
- {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.B});
- textarea.value = 'ab';
- assertFalse(pasted);
- // ends typing
- textarea.dispatchEvent(
- {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.C});
- textarea.value = 'abc';
- assertFalse(pasted);
- }
- function testStartsOnInitialState() {
- assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
- assertFalse(pasted);
- }
- function testBlurOnInit() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.BLUR);
- assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
- assertFalse(pasted);
- }
- function testFocusOnInit() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- assertTrue(handler.getState() == goog.events.PasteHandler.State.FOCUSED);
- assertFalse(pasted);
- }
- function testInputOnFocus() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- // user clicks on the textarea
- textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- // and right click -> paste a text!
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(handler.getState() == goog.events.PasteHandler.State.FOCUSED);
- // make sure we detected it
- assertTrue(pasted);
- }
- function testKeyPressOnFocus() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- // user clicks on the textarea
- textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
- // starts typing something
- textarea.dispatchEvent(newBrowserEvent({
- type: goog.events.EventType.KEYDOWN,
- keyCode: goog.events.KeyCodes.A
- }));
- assertTrue(handler.getState() == goog.events.PasteHandler.State.TYPING);
- assertFalse(pasted);
- // and then presses ctrl+v
- textarea.dispatchEvent(newBrowserEvent({
- type: goog.events.EventType.KEYDOWN,
- keyCode: goog.events.KeyCodes.V,
- ctrlKey: true
- }));
- assertTrue(handler.getState() == goog.events.PasteHandler.State.TYPING);
- // makes sure we detected it
- assertTrue(pasted);
- }
- function testMouseOverOnInit() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- // user has something on the events
- textarea.value = 'pasted string';
- // and right click -> paste it on the textarea, WITHOUT giving focus
- textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.MOUSEOVER));
- assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
- // makes sure we detect it
- assertTrue(pasted);
- pasted = false;
- // user normaly mouseovers the textarea, with no text change
- textarea.dispatchEvent(goog.events.EventType.MOUSEOVER);
- assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
- // text area value doesn't change
- assertFalse(pasted);
- }
- function testMouseOverAfterTyping() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- assertFalse(pasted);
- textarea.dispatchEvent(
- {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
- assertFalse(pasted);
- textarea.value = 'a';
- textarea.dispatchEvent('input');
- assertFalse(pasted);
- assertEquals('a', handler.oldValue_);
- textarea.dispatchEvent(goog.events.EventType.MOUSEOVER);
- assertFalse(pasted);
- }
- function testTypingAndThenRightClickPaste() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- textarea.dispatchEvent(
- {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
- assertFalse(pasted);
- textarea.value = 'a';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- textarea.dispatchEvent('input');
- assertFalse(pasted);
- assertEquals('a', handler.oldValue_);
- textarea.value = 'ab';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- }
- function testTypingReallyFastDispatchesTwoInputEventsBeforeTheKeyDownEvent() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- // keydown and input events seems to be fired indepently: even though input
- // should happen after the key event, it doesn't if the user types fast
- // enough. FF2 + linux doesn't fire keydown events for every key pressed when
- // you type fast enough. if one of the keydown events gets swallowed, two
- // input events are fired consecutively. notice that there is a similar
- // scenario, that actually does produce a valid paste action.
- // {@see testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents}
- textarea.dispatchEvent(
- {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
- assertFalse(pasted);
- textarea.value = 'a';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER -
- 1);
- textarea.dispatchEvent('input');
- assertFalse(pasted);
- // second key down events gets fired on a different order
- textarea.value = 'ab';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER -
- 1);
- textarea.dispatchEvent('input');
- assertFalse(pasted);
- }
- function testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- // there is also another case that two consecutive INPUT events are fired,
- // but in a valid paste action: if the user edit -> paste -> edit -> paste,
- // it is a valid paste action.
- textarea.value = 'a';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- // second key down events gets fired on a different order
- textarea.value = 'ab';
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- }
- function testMiddleClickWithoutFocusTriggersPasteEvent() {
- if (goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- // if the textarea is NOT selected, and then we use the middle button,
- // FF2+linux pastes what was last highlighted, causing a paste action.
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- }
- function testMacRightClickPasteRequiresCtrlBecauseItHasOneButton() {
- if (!goog.userAgent.OPERA || !goog.userAgent.MAC) {
- return;
- }
- var handler = new goog.events.PasteHandler(textarea);
- // user clicks on the textarea and give it focus
- goog.events.listen(
- handler, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- assertFalse(pasted);
- textarea.dispatchEvent({type: goog.events.EventType.KEYDOWN, keyCode: 0});
- assertFalse(pasted);
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- }
- function testOperaMacFiresKeyCode17WhenAppleKeyPressedButDoesNotFireKeyDown() {
- if (!goog.userAgent.OPERA || !goog.userAgent.MAC) {
- return;
- }
- var handler = new goog.events.PasteHandler(textarea);
- // user clicks on the textarea and give it focus
- goog.events.listen(
- handler, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- textarea.dispatchEvent(goog.events.EventType.FOCUS);
- assertFalse(pasted);
- // apple key is pressed, generating a keydown event
- textarea.dispatchEvent({type: goog.events.EventType.KEYDOWN, keyCode: 17});
- assertFalse(pasted);
- clock.tick(
- goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
- 1);
- // and then text is added magically without any extra keydown events.
- textarea.dispatchEvent(newBrowserEvent('input'));
- assertTrue(pasted);
- }
- function testScriptingDoesntTriggerPasteEvents() {
- var handlerUsedToListenForScriptingChanges =
- new goog.events.PasteHandler(textarea);
- pasted = false;
- // user clicks on the textarea and give it focus
- goog.events.listen(
- handlerUsedToListenForScriptingChanges,
- goog.events.PasteHandler.EventType.PASTE, function() { pasted = true; });
- goog.dom.getElement('foo').value = 'dear paste handler,';
- assertFalse(pasted);
- goog.dom.getElement('foo').value = 'please dont misunderstand script changes';
- assertFalse(pasted);
- goog.dom.getElement('foo').value = 'with user generated paste events';
- assertFalse(pasted);
- goog.dom.getElement('foo').value = 'thanks!';
- assertFalse(pasted);
- }
- function testAfterPaste() {
- if (!goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- var handlerThatSupportsPasteEvents = new goog.events.PasteHandler(textarea);
- pasted = false;
- goog.events.listen(
- handlerThatSupportsPasteEvents, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- var afterPasteFired = false;
- goog.events.listen(
- handlerThatSupportsPasteEvents,
- goog.events.PasteHandler.EventType.AFTER_PASTE,
- function() { afterPasteFired = true; });
- // Initial paste event comes before AFTER_PASTE has fired.
- textarea.dispatchEvent(newBrowserEvent('paste'));
- assertTrue(pasted);
- assertFalse(afterPasteFired);
- // Once text is pasted, it takes a bit to detect it, at which point
- // AFTER_PASTE is fired.
- clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
- textarea.value = 'text';
- clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
- assertTrue(afterPasteFired);
- }
- function testAfterPasteNotFiredIfDelayTooLong() {
- if (!goog.events.PasteHandler.SUPPORTS_NATIVE_PASTE_EVENT) {
- return;
- }
- var handlerThatSupportsPasteEvents = new goog.events.PasteHandler(textarea);
- pasted = false;
- goog.events.listen(
- handlerThatSupportsPasteEvents, goog.events.PasteHandler.EventType.PASTE,
- function() { pasted = true; });
- var afterPasteFired = false;
- goog.events.listen(
- handlerThatSupportsPasteEvents,
- goog.events.PasteHandler.EventType.AFTER_PASTE,
- function() { afterPasteFired = true; });
- // Initial paste event comes before AFTER_PASTE has fired.
- textarea.dispatchEvent(newBrowserEvent('paste'));
- assertTrue(pasted);
- assertFalse(afterPasteFired);
- // If the new text doesn't show up in time, we never fire AFTER_PASTE.
- clock.tick(goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_);
- textarea.value = 'text';
- clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
- assertFalse(afterPasteFired);
- }
|