Skip to content

Commit

Permalink
Merge pull request #855 from danielrentz/task/820-SubmitEvent
Browse files Browse the repository at this point in the history
#820@minor: Add SubmitEvent.
  • Loading branch information
capricorn86 committed Apr 13, 2023
2 parents e697ebc + 920809d commit 5b87a3a
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 2 deletions.
6 changes: 6 additions & 0 deletions packages/happy-dom/src/event/events/ISubmitEventInit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import IHTMLElement from '../../nodes/html-element/IHTMLElement';
import IEventInit from '../IEventInit';

export default interface ISubmitEventInit extends IEventInit {
submitter?: IHTMLElement;
}
22 changes: 22 additions & 0 deletions packages/happy-dom/src/event/events/SubmitEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Event from '../Event';
import ISubmitEventInit from './ISubmitEventInit';
import IHTMLElement from '../../nodes/html-element/IHTMLElement';

/**
* An event triggered by form submit buttons.
*/
export default class SubmitEvent extends Event {
public readonly submitter: IHTMLElement;

/**
* Constructor.
*
* @param type Event type.
* @param [eventInit] Event init.
*/
constructor(type: string, eventInit: ISubmitEventInit = null) {
super(type, eventInit);

this.submitter = eventInit?.submitter || null;
}
}
4 changes: 4 additions & 0 deletions packages/happy-dom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ import IInputEventInit from './event/events/IInputEventInit';
import IKeyboardEventInit from './event/events/IKeyboardEventInit';
import IMouseEventInit from './event/events/IMouseEventInit';
import IProgressEventInit from './event/events/IProgressEventInit';
import ISubmitEventInit from './event/events/ISubmitEventInit';
import IWheelEventInit from './event/events/IWheelEventInit';
import InputEvent from './event/events/InputEvent';
import KeyboardEvent from './event/events/KeyboardEvent';
import MouseEvent from './event/events/MouseEvent';
import ProgressEvent from './event/events/ProgressEvent';
import SubmitEvent from './event/events/SubmitEvent';
import WheelEvent from './event/events/WheelEvent';
import DOMParser from './dom-parser/DOMParser';
import Document from './nodes/document/Document';
Expand Down Expand Up @@ -180,11 +182,13 @@ export {
IKeyboardEventInit,
IMouseEventInit,
IProgressEventInit,
ISubmitEventInit,
IWheelEventInit,
InputEvent,
KeyboardEvent,
MouseEvent,
ProgressEvent,
SubmitEvent,
WheelEvent,
DOMParser,
Document,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import HTMLElement from '../html-element/HTMLElement';
import IHTMLFormElement from './IHTMLFormElement';
import Event from '../../event/Event';
import SubmitEvent from '../../event/events/SubmitEvent';
import HTMLFormControlsCollection from './HTMLFormControlsCollection';
import IHTMLFormControlsCollection from './IHTMLFormControlsCollection';
import INode from '../node/INode';
Expand Down Expand Up @@ -209,7 +210,9 @@ export default class HTMLFormElement extends HTMLElement implements IHTMLFormEle
public requestSubmit(submitter?: IHTMLInputElement | IHTMLButtonElement): void {
const noValidate = submitter?.formNoValidate || this.noValidate;
if (noValidate || this.checkValidity()) {
this.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
this.dispatchEvent(
new SubmitEvent('submit', { bubbles: true, cancelable: true, submitter: submitter || this })
);
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/happy-dom/src/window/IWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import InputEvent from '../event/events/InputEvent';
import UIEvent from '../event/UIEvent';
import ErrorEvent from '../event/events/ErrorEvent';
import StorageEvent from '../event/events/StorageEvent';
import SubmitEvent from '../event/events/SubmitEvent';
import MessageEvent from '../event/events/MessageEvent';
import MessagePort from '../event/MessagePort';
import Screen from '../screen/Screen';
Expand Down Expand Up @@ -192,6 +193,7 @@ export default interface IWindow extends IEventTarget, INodeJSGlobal {
readonly InputEvent: typeof InputEvent;
readonly ErrorEvent: typeof ErrorEvent;
readonly StorageEvent: typeof StorageEvent;
readonly SubmitEvent: typeof SubmitEvent;
readonly MessageEvent: typeof MessageEvent;
readonly MessagePort: typeof MessagePort;
readonly ProgressEvent: typeof ProgressEvent;
Expand Down
2 changes: 2 additions & 0 deletions packages/happy-dom/src/window/Window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import InputEvent from '../event/events/InputEvent';
import UIEvent from '../event/UIEvent';
import ErrorEvent from '../event/events/ErrorEvent';
import StorageEvent from '../event/events/StorageEvent';
import SubmitEvent from '../event/events/SubmitEvent';
import Screen from '../screen/Screen';
import AsyncTaskManager from '../async-task-manager/AsyncTaskManager';
import IResponse from '../fetch/types/IResponse';
Expand Down Expand Up @@ -235,6 +236,7 @@ export default class Window extends EventTarget implements IWindow {
public readonly InputEvent = InputEvent;
public readonly ErrorEvent = ErrorEvent;
public readonly StorageEvent = StorageEvent;
public readonly SubmitEvent = SubmitEvent;
public readonly ProgressEvent = ProgressEvent;
public readonly MediaQueryListEvent = MediaQueryListEvent;
public readonly EventTarget = EventTarget;
Expand Down
16 changes: 16 additions & 0 deletions packages/happy-dom/test/event/events/SubmitEvent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Event from '../../../src/event/Event';
import SubmitEvent from '../../../src/event/events/SubmitEvent';
import HTMLButtonElement from '../../../src/nodes/html-button-element/HTMLButtonElement';

describe('SubmitEvent', () => {
describe('constructor', () => {
it('Creates a submit event.', () => {
const submitter = new HTMLButtonElement();
const event = new SubmitEvent('submit', { bubbles: true, submitter });
expect(event).toBeInstanceOf(Event);
expect(event.bubbles).toBe(true);
expect(event.cancelable).toBe(false);
expect(event.submitter).toBe(submitter);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import HTMLFormElement from '../../../src/nodes/html-form-element/HTMLFormElemen
import RadioNodeList from '../../../src/nodes/html-form-element/RadioNodeList';
import IHTMLInputElement from '../../../src/nodes/html-input-element/IHTMLInputElement';
import Event from '../../../src/event/Event';
import SubmitEvent from '../../../src/event/events/SubmitEvent';
import IHTMLSelectElement from '../../../src/nodes/html-select-element/IHTMLSelectElement';
import IHTMLTextAreaElement from '../../../src/nodes/html-text-area-element/IHTMLTextAreaElement';
import IHTMLButtonElement from '../../../src/nodes/html-button-element/IHTMLButtonElement';

describe('HTMLFormElement', () => {
let window: Window;
Expand Down Expand Up @@ -298,7 +300,9 @@ describe('HTMLFormElement', () => {
element.noValidate = true;
element.requestSubmit();

expect(submitEvent).toBeInstanceOf(SubmitEvent);
expect(submitEvent.type).toBe('submit');
expect((<SubmitEvent>submitEvent).submitter).toBe(element);

submitEvent = null;

Expand All @@ -311,9 +315,10 @@ describe('HTMLFormElement', () => {
(<IHTMLInputElement>root.children[2]).click();
(<IHTMLInputElement>root.children[6]).click();

element.requestSubmit();
element.requestSubmit(<IHTMLButtonElement>root.children[1]);

expect(submitEvent.type).toBe('submit');
expect((<SubmitEvent>submitEvent).submitter).toBe(root.children[1]);
});

it('Skips validating if a submitter is sent that has "formNoValidate" set to "true".', () => {
Expand Down

0 comments on commit 5b87a3a

Please sign in to comment.