@roomservice/browser
Advanced tools
Comparing version 0.0.15 to 0.0.16
@@ -19,2 +19,5 @@ "use strict"; | ||
invariant_1.default(result.status !== 405, "Your authorization endpoint does not appear to accept a POST request."); | ||
if (result.status < 200 || result.status >= 400) { | ||
throw new Error(`Your Auth endpoint at '${authorizationUrl}' is not functioning properly, returned status of ${result.status}.`); | ||
} | ||
const res = await result.json(); | ||
@@ -21,0 +24,0 @@ const { room, session } = res; |
@@ -68,3 +68,17 @@ "use strict"; | ||
async connect() { | ||
const { room, session } = await authorize_1.default(this._authorizationUrl, this._reference); | ||
let room; | ||
let session; | ||
try { | ||
const params = await authorize_1.default(this._authorizationUrl, this._reference); | ||
room = params.room; | ||
session = params.session; | ||
} | ||
catch (err) { | ||
console.warn(err); | ||
await this.syncOfflineCache(); | ||
return { | ||
state: this._docs.getDoc("default"), | ||
reference: this._reference | ||
}; | ||
} | ||
this._roomId = room.id; | ||
@@ -87,2 +101,7 @@ this._socket = socket_1.default.newSocket(this._socketURL, { | ||
}); | ||
// Required connect handler | ||
socket_1.default.on(this._socket, "connect", () => { | ||
this._automergeConn.open(); | ||
this.syncOfflineCache(); | ||
}); | ||
/** | ||
@@ -96,6 +115,3 @@ * We don't require these to be defined before hand since they're | ||
if (this._onConnectSocketCallback) { | ||
socket_1.default.on(this._socket, "connect", () => { | ||
this._onConnectSocketCallback(); | ||
this.syncOfflineCache(); | ||
}); | ||
socket_1.default.on(this._socket, "connect", this._onConnectSocketCallback); | ||
} | ||
@@ -117,3 +133,2 @@ if (this._onDisconnectSocketCallback) { | ||
} | ||
this._automergeConn.open(); | ||
return { | ||
@@ -120,0 +135,0 @@ state, |
@@ -9,2 +9,3 @@ "use strict"; | ||
const socket_1 = tslib_1.__importDefault(require("./socket")); | ||
const test_socket_1 = require("./test-socket"); | ||
const URL = "https://coolsite.com"; | ||
@@ -26,133 +27,99 @@ jest.mock("idb-keyval"); | ||
} | ||
describe("RoomServiceClient", () => { | ||
it("should call the authorization endpoint when creating a room", async () => { | ||
const socket = test_socket_1.injectFakeSocket(); | ||
const scope = mockAuthEndpoint(); | ||
// @ts-ignore | ||
jest.spyOn(socket_1.default, "newSocket").mockImplementation(() => ({ | ||
on: jest.fn() | ||
})); | ||
it("should call the authorization endpoint when creating a room", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
await room.connect(); | ||
expect(scope.isDone()).toBeTruthy(); | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
await room.connect(); | ||
expect(scope.isDone()).toBeTruthy(); | ||
}); | ||
test("room gets called with bearer token", async () => { | ||
mockAuthEndpoint(); | ||
const mock = jest | ||
.spyOn(socket_1.default, "newSocket") | ||
.mockImplementation((url, connectopts) => { | ||
// @ts-ignore | ||
return { on: jest.fn() }; | ||
}).mock; | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
await room.connect(); | ||
const [url, args] = mock.calls[0]; | ||
expect(url).toBe("https://api.roomservice.dev"); | ||
// @ts-ignore because bad typings make me sad | ||
expect(args.transportOptions.polling.extraHeaders.authorization).toBe("Bearer short-lived-token"); | ||
}); | ||
test("room.publish() can change a document", async (done) => { | ||
mockAuthEndpoint(); | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
const sockets = test_socket_1.injectFakeSocket(); | ||
await room.connect(); | ||
sockets.emit("connect"); | ||
const newState = room.publishState(prevState => { | ||
prevState.someOption = "hello!"; | ||
}); | ||
test("room gets called with bearer token", async () => { | ||
mockAuthEndpoint(); | ||
const mock = jest | ||
.spyOn(socket_1.default, "newSocket") | ||
.mockImplementation((url, connectopts) => { | ||
// @ts-ignore | ||
return { on: jest.fn() }; | ||
}).mock; | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
await room.connect(); | ||
const [url, args] = mock.calls[0]; | ||
expect(url).toBe("https://api.roomservice.dev"); | ||
// @ts-ignore because bad typings make me sad | ||
expect(args.transportOptions.polling.extraHeaders.authorization).toBe("Bearer short-lived-token"); | ||
expect(newState.someOption).toBe("hello!"); | ||
setTimeout(() => { | ||
// @ts-ignore | ||
expect(room._automergeConn._ourClock.get("default").size).toEqual(1); | ||
done(); | ||
}, 150); | ||
}); | ||
test("room.restore() attempts to restore from offline", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
jest.spyOn(offline_1.default, "get").mockImplementation(async (ref, doc) => { | ||
return automerge_1.save(automerge_1.from({ name: "offlinedoc" })); | ||
}); | ||
test("room.publish() can change a document", async () => { | ||
mockAuthEndpoint(); | ||
const emit = jest.fn(); | ||
jest | ||
.spyOn(socket_1.default, "newSocket") | ||
// @ts-ignore because typescript doesn't like our deep testing magic | ||
.mockImplementation((url, connectopts) => { | ||
return { | ||
emit, | ||
on: jest.fn() | ||
}; | ||
}); | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
await room.connect(); | ||
const newState = room.publishState(prevState => { | ||
prevState.someOption = "hello!"; | ||
}); | ||
expect(newState.someOption).toBe("hello!"); | ||
const doc = await room.restore(); | ||
expect(doc).toEqual({ name: "offlinedoc" }); | ||
}); | ||
test("room.connect() will merge online data with offline data", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
// setup offline | ||
jest.spyOn(offline_1.default, "get").mockImplementation(async (ref, doc) => { | ||
return automerge_1.save(automerge_1.from({ offline: "offline" })); | ||
}); | ||
test("room.restore() attempts to restore from offline", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
jest.spyOn(offline_1.default, "get").mockImplementation(async (ref, doc) => { | ||
return automerge_1.save(automerge_1.from({ name: "offlinedoc" })); | ||
}); | ||
const doc = await room.restore(); | ||
expect(doc).toEqual({ name: "offlinedoc" }); | ||
// setup online | ||
mockAuthEndpoint(automerge_1.save(automerge_1.from({ online: "online" }))); | ||
const { state } = await room.connect(); | ||
expect(state).toEqual({ | ||
offline: "offline", | ||
online: "online" | ||
}); | ||
test("room.connect() will merge online data with offline data", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
// setup offline | ||
jest.spyOn(offline_1.default, "get").mockImplementation(async (ref, doc) => { | ||
return automerge_1.save(automerge_1.from({ offline: "offline" })); | ||
}); | ||
// setup online | ||
mockAuthEndpoint(automerge_1.save(automerge_1.from({ online: "online" }))); | ||
const { state } = await room.connect(); | ||
expect(state).toEqual({ | ||
offline: "offline", | ||
online: "online" | ||
}); | ||
}); | ||
test("room.onUpdate callback tries to save the document to offline", async (done) => { | ||
mockAuthEndpoint(); | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
const cb = jest.fn(); | ||
room.onUpdate(cb); | ||
// @ts-ignore private | ||
const onUpdateSocket = room._onUpdateSocketCallback; | ||
expect(onUpdateSocket).toBeTruthy(); | ||
await room.connect(); | ||
// @ts-ignore private; we'd normally get this from the auth endpoint | ||
room._roomId = "my-room-id"; | ||
const setOffline = jest.spyOn(offline_1.default, "set"); | ||
onUpdateSocket(JSON.stringify({ | ||
meta: { | ||
roomId: "my-room-id" | ||
}, | ||
payload: { | ||
msg: { | ||
clock: new Map(), | ||
docId: "default" | ||
} | ||
}); | ||
test("room.onUpdate callback tries to save the document to offline", async (done) => { | ||
mockAuthEndpoint(); | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
const cb = jest.fn(); | ||
room.onUpdate(cb); | ||
// @ts-ignore private | ||
const onUpdateSocket = room._onUpdateSocketCallback; | ||
expect(onUpdateSocket).toBeTruthy(); | ||
await room.connect(); | ||
// @ts-ignore private; we'd normally get this from the auth endpoint | ||
room._roomId = "my-room-id"; | ||
const setOffline = jest.spyOn(offline_1.default, "set"); | ||
onUpdateSocket(JSON.stringify({ | ||
meta: { | ||
roomId: "my-room-id" | ||
}, | ||
payload: { | ||
msg: { | ||
clock: new Map(), | ||
docId: "default" | ||
} | ||
})); | ||
// Sanity check that our onUpdate callback was called | ||
expect(cb.mock.calls.length).toBe(1); | ||
// We wait here because saving offline is debounced. | ||
setTimeout(() => { | ||
expect(setOffline.mock.calls.length).toBeGreaterThan(1); | ||
done(); | ||
}, 160); // Debounce time | ||
}); | ||
test("will update net with off-synced doc after coming online", async () => { | ||
const client = new client_1.default(URL + "/api/roomservice"); | ||
const room = client.room("my-room"); | ||
// Offline | ||
jest.spyOn(offline_1.default, "get").mockImplementation(async (ref, doc) => { | ||
return automerge_1.save(automerge_1.from({ offline: "offline" })); | ||
}); | ||
// Current online | ||
mockAuthEndpoint(automerge_1.save(automerge_1.from({ current: "current" }))); | ||
// Attempt to publish an update while offline | ||
room.publishState(state => { | ||
state.update = "update"; | ||
}); | ||
const emit = jest.fn(); | ||
jest | ||
.spyOn(socket_1.default, "newSocket") | ||
// @ts-ignore because typescript doesn't like our deep testing magic | ||
.mockImplementation((url, connectopts) => { | ||
return { | ||
emit, | ||
on: jest.fn() | ||
}; | ||
}); | ||
await room.connect(); | ||
console.log(emit.mock.calls); | ||
}); | ||
} | ||
})); | ||
// Sanity check that our onUpdate callback was called | ||
expect(cb.mock.calls.length).toBeGreaterThan(1); | ||
// We wait here because saving offline is debounced. | ||
setTimeout(() => { | ||
expect(setOffline.mock.calls.length).toBeGreaterThanOrEqual(1); | ||
done(); | ||
}, 160); // Debounce time | ||
}); | ||
//# sourceMappingURL=client.test.js.map |
/// <reference types="socket.io-client" /> | ||
declare const Sockets: { | ||
newSocket(url: string, opts: SocketIOClient.ConnectOpts): SocketIOClient.Socket; | ||
on(socket: SocketIOClient.Socket, event: "error" | "connect" | "disconnect" | "sync_room_state", fn: Function): void; | ||
on(socket: SocketIOClient.Socket, event: "error" | "connect" | "disconnect" | "sync_room_state", fn: (...args: any[]) => void): void; | ||
emit(socket: SocketIOClient.Socket, event: "sync_room_state", ...args: any[]): void; | ||
@@ -6,0 +6,0 @@ disconnect(socket: SocketIOClient.Socket): void; |
{ | ||
"name": "@roomservice/browser", | ||
"version": "0.0.15", | ||
"version": "0.0.16", | ||
"main": "dist/index", | ||
@@ -5,0 +5,0 @@ "types": "dist/index", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40883
36
610