-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { effector } from "./effect"; | ||
import { trigger } from "./event"; | ||
|
||
/** | ||
* Effect that triggers an event with args. | ||
* | ||
* @example | ||
* | ||
* { | ||
* trigger: ["event-id", "arg1", "arg2"] | ||
* } | ||
*/ | ||
effector("trigger", ([eventId, ...args]) => trigger(eventId, ...args)); | ||
|
||
const STATUS_OK = 200; | ||
const STATUS_CREATED = 201; | ||
const STATUS_ACCEPTED = 202; | ||
const STATUS_NO_CONTENT = 204; | ||
const STATUS_PARTIAL_CONTENT = 206; | ||
const STATUS_NOT_MODIFIED = 304; | ||
|
||
/** | ||
* Effect that performs an XML HTTP request to interact with a server. | ||
* | ||
* @example | ||
* | ||
* { | ||
* xhr: { | ||
* url: "/endpoint", | ||
* method: "GET", | ||
* onSuccess: ["success"] | ||
* } | ||
* } | ||
*/ | ||
effector( | ||
"xhr", | ||
({ | ||
url, | ||
method = "GET", | ||
responseType = "", | ||
timeout = 3000, | ||
headers = {}, | ||
data, | ||
onSuccess, | ||
onError, | ||
}) => { | ||
const xhr = new XMLHttpRequest(); | ||
xhr.open(method, url); | ||
xhr.responseType = responseType; | ||
xhr.timeout = timeout; | ||
for (let name in headers) { | ||
xhr.setRequestHeader(name, headers[name]); | ||
} | ||
xhr.onload = xhr.onerror = function() { | ||
switch (this.status) { | ||
case STATUS_OK: | ||
case STATUS_CREATED: | ||
case STATUS_ACCEPTED: | ||
case STATUS_NO_CONTENT: | ||
case STATUS_PARTIAL_CONTENT: | ||
case STATUS_NOT_MODIFIED: | ||
if (onSuccess) { | ||
trigger(...onSuccess, this.response); | ||
} | ||
break; | ||
default: | ||
if (onError) { | ||
trigger(...onError, { | ||
status: this.status, | ||
statusText: this.statusText, | ||
response: this.response, | ||
}); | ||
} | ||
} | ||
}; | ||
xhr.send(data); | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import "./batteries"; | ||
import { effect } from "./effect"; | ||
import { trigger } from "./event"; | ||
|
||
jest.mock("./event"); | ||
|
||
let xhrs = []; | ||
beforeEach(() => { | ||
xhrs = []; | ||
trigger.mockClear(); | ||
}); | ||
|
||
window.XMLHttpRequest = function() { | ||
let xhr = { | ||
open: jest.fn(), | ||
send: jest.fn(), | ||
setRequestHeader: jest.fn(), | ||
}; | ||
// remember created xhr requests | ||
xhrs = [...xhrs, xhr]; | ||
return xhr; | ||
}; | ||
|
||
describe("trigger effect", () => { | ||
it("should trigger the described event", () => { | ||
effect("trigger", ["foo", "bar", "baz"]); | ||
expect(trigger).toHaveBeenCalledTimes(1); | ||
expect(trigger).toHaveBeenCalledWith("foo", "bar", "baz"); | ||
}); | ||
}); | ||
|
||
describe("xhr effect", () => { | ||
it("has sane defaults", () => { | ||
effect("xhr", {}); | ||
|
||
const xhr = xhrs[0]; | ||
expect(xhr.open.mock.calls[0]).toEqual(["GET", undefined]); | ||
expect(xhr.send.mock.calls[0]).toEqual([undefined]); | ||
expect(xhr.responseType).toBe(""); | ||
expect(xhr.timeout).toBe(3000); | ||
expect(xhr.setRequestHeader.mock.calls.length).toBe(0); | ||
}); | ||
it("overrides defaults", () => { | ||
effect("xhr", { | ||
url: "/foo", | ||
method: "POST", | ||
responseType: "json", | ||
timeout: 42, | ||
headers: { Foo: "my-foo", Bar: "my-bar" }, | ||
data: "some-data", | ||
}); | ||
|
||
const xhr = xhrs[0]; | ||
expect(xhr.open.mock.calls[0]).toEqual(["POST", "/foo"]); | ||
expect(xhr.send.mock.calls[0]).toEqual(["some-data"]); | ||
expect(xhr.responseType).toBe("json"); | ||
expect(xhr.timeout).toBe(42); | ||
expect(xhr.setRequestHeader.mock.calls[0]).toEqual(["Foo", "my-foo"]); | ||
expect(xhr.setRequestHeader.mock.calls[1]).toEqual(["Bar", "my-bar"]); | ||
}); | ||
it("triggers an event on success", () => { | ||
effect("xhr", { | ||
onSuccess: ["success", "foo"], | ||
onError: ["error", "foo"], | ||
}); | ||
|
||
const xhr = xhrs[0]; | ||
[200, 201, 202, 204, 206, 304].forEach(status => { | ||
trigger.mockClear(); | ||
xhr.onload.call({ | ||
status: status, | ||
statusText: "${status}", | ||
response: "response", | ||
}); | ||
expect(trigger).toHaveBeenCalledTimes(1); | ||
expect(trigger).toHaveBeenCalledWith("success", "foo", "response"); | ||
}); | ||
}); | ||
it("triggers an event on error", () => { | ||
effect("xhr", { | ||
onSuccess: ["success", "foo"], | ||
onError: ["error", "foo"], | ||
}); | ||
|
||
const xhr = xhrs[0]; | ||
const response = { | ||
status: 500, | ||
statusText: "Server error", | ||
response: "response", | ||
}; | ||
xhr.onload.call(response); | ||
expect(trigger).toHaveBeenCalledTimes(1); | ||
expect(trigger).toHaveBeenCalledWith("error", "foo", response); | ||
}); | ||
it("ignores success if onSuccess is unset", () => { | ||
effect("xhr", {}); | ||
|
||
const xhr = xhrs[0]; | ||
const response = { | ||
status: 200, | ||
statusText: "OK", | ||
response: "response", | ||
}; | ||
xhr.onload.call(response); | ||
expect(trigger).not.toHaveBeenCalled(); | ||
}); | ||
it("ignores errors if onError is unset", () => { | ||
effect("xhr", {}); | ||
|
||
const xhr = xhrs[0]; | ||
const response = { | ||
status: 500, | ||
statusText: "Server error", | ||
response: "response", | ||
}; | ||
xhr.onload.call(response); | ||
expect(trigger).not.toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters