-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #118 from graasp/88/websockets
Add React hooks calls and integration tests for real-time updates (#88)
- Loading branch information
Showing
8 changed files
with
481 additions
and
26 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,47 @@ | ||
/** | ||
* Mock WebSocket class for Graasp WS protocol | ||
*/ | ||
|
||
// eslint-disable-next-line import/prefer-default-export | ||
export class WebSocket { | ||
constructor() { | ||
this.CLOSED = 0; | ||
this.OPEN = 1; | ||
|
||
this.readyState = this.OPEN; | ||
|
||
this.send = this.send.bind(this); | ||
this.receive = this.receive.bind(this); | ||
this.addEventListener = this.addEventListener.bind(this); | ||
} | ||
|
||
send(msg) { | ||
const req = JSON.parse(msg); | ||
// acknowledge request | ||
if (req.action.includes('subscribe')) { | ||
const res = { | ||
data: JSON.stringify({ | ||
realm: 'notif', | ||
type: 'response', | ||
status: 'success', | ||
request: req, | ||
}), | ||
}; | ||
this.onmessage(res); | ||
} | ||
} | ||
|
||
receive(msg) { | ||
const event = { | ||
data: JSON.stringify(msg), | ||
}; | ||
this.onmessage(event); | ||
} | ||
|
||
addEventListener(event, handler) { | ||
this[`on${event}`] = handler; | ||
if (event === 'open') { | ||
handler(); | ||
} | ||
} | ||
} |
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,131 @@ | ||
import { buildItemPath, SHARED_ITEMS_PATH } from '../../../src/config/paths'; | ||
import { buildItemsTableRowId } from '../../../src/config/selectors'; | ||
import { SAMPLE_ITEMS } from '../../fixtures/items'; | ||
import { CURRENT_USER } from '../../fixtures/members'; | ||
import { WebSocket } from './mock-ws'; | ||
|
||
describe('Websocket interactions', () => { | ||
let client; | ||
|
||
beforeEach(() => { | ||
client = new WebSocket(); | ||
}); | ||
|
||
// paramaterized before, to be called in each test or in beforeEach | ||
const beforeWs = (visitRoute, sampleData) => { | ||
cy.setUpApi(sampleData); | ||
cy.visit(visitRoute, { | ||
onBeforeLoad: (win) => { | ||
cy.stub(win, 'WebSocket', () => client); | ||
}, | ||
}); | ||
}; | ||
|
||
describe('sharedWith me items updates', () => { | ||
it('displays sharedWith create update', () => { | ||
beforeWs(SHARED_ITEMS_PATH, { items: [] }); | ||
|
||
const item = SAMPLE_ITEMS.items[0]; | ||
cy.wait('@getSharedItems').then(() => { | ||
// send mock sharedItem create update | ||
client.receive({ | ||
realm: 'notif', | ||
type: 'update', | ||
channel: CURRENT_USER.id, | ||
body: { | ||
entity: 'member', | ||
kind: 'sharedWith', | ||
op: 'create', | ||
value: item, | ||
}, | ||
}); | ||
}); | ||
|
||
// assert item is in list | ||
cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); | ||
}); | ||
|
||
it('displays sharedWith delete update', () => { | ||
// create items that do not belong to current user | ||
const items = SAMPLE_ITEMS.items.map((i) => ({ | ||
...i, | ||
creator: 'someoneElse', | ||
})); | ||
const item = items[0]; | ||
beforeWs(SHARED_ITEMS_PATH, { items }); | ||
|
||
cy.get(`#${buildItemsTableRowId(item.id)}`).then(() => { | ||
// send mock sharedItem delete update | ||
client.receive({ | ||
realm: 'notif', | ||
type: 'update', | ||
channel: CURRENT_USER.id, | ||
body: { | ||
entity: 'member', | ||
kind: 'sharedWith', | ||
op: 'delete', | ||
value: item, | ||
}, | ||
}); | ||
}); | ||
|
||
// assert item is not in list anymore | ||
cy.get(`#${buildItemsTableRowId(item.id)}`).should('not.exist'); | ||
}); | ||
}); | ||
|
||
describe('childItem updates', () => { | ||
const { id } = SAMPLE_ITEMS.items[0]; | ||
|
||
beforeEach(() => { | ||
beforeWs(buildItemPath(id), SAMPLE_ITEMS); | ||
|
||
// should get children | ||
cy.wait('@getChildren').then(({ response: { body } }) => { | ||
// check item is created and displayed | ||
for (const item of body) { | ||
cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); | ||
} | ||
}); | ||
}); | ||
|
||
it('displays childItem create update', () => { | ||
const item = { ...SAMPLE_ITEMS.items[0], id: 'child0' }; | ||
// send mock childItem create update | ||
client.receive({ | ||
realm: 'notif', | ||
type: 'update', | ||
channel: id, | ||
body: { | ||
entity: 'item', | ||
kind: 'childItem', | ||
op: 'create', | ||
value: item, | ||
}, | ||
}); | ||
|
||
// assert item is in list | ||
cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); | ||
}); | ||
|
||
it('displays childItem delete update', () => { | ||
// this item MUST be a child of id above | ||
const item = SAMPLE_ITEMS.items[2]; | ||
// send mock childItem delete update | ||
client.receive({ | ||
realm: 'notif', | ||
type: 'update', | ||
channel: id, | ||
body: { | ||
entity: 'item', | ||
kind: 'childItem', | ||
op: 'delete', | ||
value: item, | ||
}, | ||
}); | ||
|
||
// assert item is not in list | ||
cy.get(`#${buildItemsTableRowId(item.id)}`).should('not.exist'); | ||
}); | ||
}); | ||
}); |
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
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
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
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
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
Oops, something went wrong.