Skip to content

Commit

Permalink
fix(wallet-ui): flatten schema into actions and iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Jan 21, 2022
1 parent 2cdf78f commit 21bdfd1
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 90 deletions.
6 changes: 3 additions & 3 deletions packages/wallet/ui/src/components/MakePurse.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const MakePurseWithoutContext = ({
purses,
handleClose,
setPendingPurseCreations,
schema,
schemaActions,
}) => {
const [isSnackbarOpen, setIsSnackbarOpen] = useState(false);
const handleCloseSnackbar = _ => {
Expand Down Expand Up @@ -53,7 +53,7 @@ export const MakePurseWithoutContext = ({
setPendingPurseCreations({ issuerId, isPending: true });
close();
try {
await E(schema.purses.actions).create(issuer, petname);
await E(schemaActions).createPurse(issuer, petname);
showSnackbar('Successfully created purse.');
} catch (e) {
showSnackbar('Failed to create purse.');
Expand Down Expand Up @@ -110,5 +110,5 @@ export default withApplicationContext(MakePurseWithoutContext, context => ({
issuers: context.issuers,
purses: context.purses,
setPendingPurseCreations: context.setPendingPurseCreations,
schema: context.schema,
schemaActions: context.schemaActions,
}));
13 changes: 4 additions & 9 deletions packages/wallet/ui/src/components/tests/MakePurse.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const issuers = [
];

const setPendingPurseCreations = jest.fn();
const schema = { purses: { actions: { create: jest.fn() } } };
const schemaActions = { createPurse: jest.fn() };

const withApplicationContext = (Component, _) => ({ ...props }) => {
return (
Expand All @@ -63,7 +63,7 @@ const withApplicationContext = (Component, _) => ({ ...props }) => {
issuers={issuers}
purses={purses}
setPendingPurseCreations={setPendingPurseCreations}
schema={schema}
schemaActions={schemaActions}
{...props}
/>
</ThemeProvider>
Expand Down Expand Up @@ -138,10 +138,7 @@ test('creates the purse', async () => {
await act(async () => createButton.props.onClick());
component.update();

expect(schema.purses.actions.create).toHaveBeenCalledWith(
issuers[1],
'Savings',
);
expect(schemaActions.createPurse).toHaveBeenCalledWith(issuers[1], 'Savings');
expect(setPendingPurseCreations).toHaveBeenCalledWith({
isPending: true,
issuerId: 1,
Expand All @@ -157,9 +154,7 @@ test('creates the purse', async () => {
});

test('shows an error when purse creation fails', async () => {
schema.purses.actions.create.mockRejectedValue(
new Error('Cannot create purse'),
);
schemaActions.createPurse.mockRejectedValue(new Error('Cannot create purse'));

const component = mount(<MakePurse issuerId={1} handleClose={jest.fn()} />);

Expand Down
24 changes: 12 additions & 12 deletions packages/wallet/ui/src/contexts/Application.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,19 @@ const Provider = ({ children }) => {
const [payments, setPayments] = useReducer(paymentsReducer, null);
const [issuers, setIssuers] = useReducer(issuersReducer, null);
const [services, setServices] = useState(null);
const [schema, setSchema] = useState(null);
const [schemaActions, setSchemaActions] = useState(null);

const setBackend = backend => {
observeIterator(backend, {
updateState: state => {
setSchema(state);
observeIterator(state.services.it, { updateState: setServices });
observeIterator(state.offers.it, { updateState: setInbox });
observeIterator(state.purses.it, { updateState: setPurses });
observeIterator(state.dapps.it, { updateState: setDapps });
observeIterator(state.contacts.it, { updateState: setContacts });
observeIterator(state.payments.it, { updateState: setPayments });
observeIterator(state.issuers.it, { updateState: setIssuers });
updateState: schema => {
setSchemaActions(schema.actions);
observeIterator(schema.services, { updateState: setServices });
observeIterator(schema.offers, { updateState: setInbox });
observeIterator(schema.purses, { updateState: setPurses });
observeIterator(schema.dapps, { updateState: setDapps });
observeIterator(schema.contacts, { updateState: setContacts });
observeIterator(schema.payments, { updateState: setPayments });
observeIterator(schema.issuers, { updateState: setIssuers });
},
});
};
Expand Down Expand Up @@ -179,7 +179,7 @@ const Provider = ({ children }) => {
const state = {
connectionState,
setConnectionState,
schema,
schemaActions,
setBackend,
services,
setServices,
Expand Down Expand Up @@ -208,7 +208,7 @@ const Provider = ({ children }) => {
};

useDebugLogging(state, [
schema,
schemaActions,
inbox,
purses,
dapps,
Expand Down
60 changes: 20 additions & 40 deletions packages/wallet/ui/src/util/WalletBackendAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const makeBackendFromWalletBridge = walletBridge => {
/**
* @param {AsyncIterator<any[], any[], undefined>} offersMembers
*/
const wrapOffersMembers = offersMembers =>
const wrapOffersIterator = offersMembers =>
harden({
next: async () => {
const { done, value } = await offersMembers.next();
Expand All @@ -50,41 +50,23 @@ export const makeBackendFromWalletBridge = walletBridge => {
});

const firstSchema = harden({
services: {
it: iterateNotifier(servicesNotifier),
},
dapps: {
it: iterateNotifier(E(walletBridge).getDappsNotifier()),
},
contacts: {
it: iterateNotifier(E(walletBridge).getContactsNotifier()),
actions: Far('contactsActions', {
create: (depositFacet, id = newId('Contact')) =>
E(walletBridge).addContact(id, depositFacet),
}),
},
issuers: {
it: iterateNotifier(E(walletBridge).getIssuersNotifier()),
actions: Far('issuersActions', {
create: (issuer, id = newId('Issuer')) =>
E(walletBridge).addIssuer(id, issuer, true),
}),
},
offers: {
it: wrapOffersMembers(
iterateNotifier(E(walletBridge).getOffersNotifier()),
),
},
payments: {
it: iterateNotifier(E(walletBridge).getPaymentsNotifier()),
},
purses: {
it: iterateNotifier(E(walletBridge).getPursesNotifier()),
actions: Far('pursesActions', {
create: (issuer, id = newId('Purse')) =>
E(walletBridge).makeEmptyPurse(issuer?.issuerPetname, id),
}),
},
actions: Far('schemaActions', {
createPurse: (issuer, id = newId('Purse')) =>
E(walletBridge).makeEmptyPurse(issuer?.issuerPetname, id),
createContact: (depositFacet, id = newId('Contact')) =>
E(walletBridge).addContact(id, depositFacet),
createIssuer: (issuer, id = newId('Issuer')) =>
E(walletBridge).addIssuer(id, issuer, true),
}),
services: iterateNotifier(servicesNotifier),
dapps: iterateNotifier(E(walletBridge).getDappsNotifier()),
contacts: iterateNotifier(E(walletBridge).getContactsNotifier()),
issuers: iterateNotifier(E(walletBridge).getIssuersNotifier()),
offers: wrapOffersIterator(
iterateNotifier(E(walletBridge).getOffersNotifier()),
),
payments: iterateNotifier(E(walletBridge).getPaymentsNotifier()),
purses: iterateNotifier(E(walletBridge).getPursesNotifier()),
});

// Just produce a single update for the initial backend.
Expand All @@ -95,10 +77,8 @@ export const makeBackendFromWalletBridge = walletBridge => {
// Finish all the other members iterators.
observeIterator(backendIt, {
finish: state => {
Object.values(state).forEach(({ it }) => {
if (it) {
it.return && it.return();
}
Object.values(state).forEach(it => {
typeof it.return === 'function' && it.return();
});
},
});
Expand Down
12 changes: 8 additions & 4 deletions packages/wallet/ui/src/views/Contacts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ const importingContactsReducer = (state, action) => {
};

// Exported for testing only.
export const ContactsWithoutContext = ({ contacts, services, schema }) => {
export const ContactsWithoutContext = ({
contacts,
services,
schemaActions,
}) => {
const [isSnackbarOpen, setIsSnackbarOpen] = useState(false);
const handleCloseSnackbar = _ => {
setIsSnackbarOpen(false);
Expand All @@ -42,8 +46,8 @@ export const ContactsWithoutContext = ({ contacts, services, schema }) => {
const handleImport = async (petname, boardId) => {
incrementImportingContacts();
try {
const obj = await E(services.board).getValue(boardId);
await E(schema.contacts.actions).create(obj, petname);
const contactObj = await E(services.board).getValue(boardId);
await E(schemaActions).createContact(contactObj, petname);
showSnackbar('Successfully imported contact.');
} catch {
showSnackbar('Failed to import contact.');
Expand Down Expand Up @@ -105,6 +109,6 @@ export const ContactsWithoutContext = ({ contacts, services, schema }) => {
export default withApplicationContext(ContactsWithoutContext, context => ({
contacts: context.contacts,
services: context.services,
schema: context.schema,
schemaActions: context.schemaActions,
walletBridge: context.walletBridge,
}));
6 changes: 3 additions & 3 deletions packages/wallet/ui/src/views/Issuers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const importingIssuersReducer = (state, action) => {
export const IssuersWithoutContext = ({
issuers,
pendingPurseCreations,
schema,
schemaActions,
services,
}) => {
const [selectedIssuer, setSelectedIssuer] = useState(null);
Expand Down Expand Up @@ -56,7 +56,7 @@ export const IssuersWithoutContext = ({
incrementImportingIssuers();
try {
const issuerObj = await E(services.board).getValue(boardId);
await E(schema.issuers.actions).create(issuerObj, petname);
await E(schemaActions).createIssuer(issuerObj, petname);
showSnackbar('Successfully imported issuer.');
} catch {
showSnackbar('Failed to import issuer.');
Expand Down Expand Up @@ -144,6 +144,6 @@ export const IssuersWithoutContext = ({
export default withApplicationContext(IssuersWithoutContext, context => ({
issuers: context.issuers,
pendingPurseCreations: context.pendingPurseCreations,
schema: context.schema,
schemaActions: context.schemaActions,
services: context.services,
}));
14 changes: 5 additions & 9 deletions packages/wallet/ui/src/views/tests/Contacts.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@ const services = {
board,
};

const schema = {
contacts: {
actions: {
create: jest.fn(),
},
},
const schemaActions = {
createContact: jest.fn(),
};

const appTheme = createTheme({
Expand All @@ -50,7 +46,7 @@ const withApplicationContext = (Component, _) => ({ ...props }) => {
<Component
contacts={contacts}
services={services}
schema={schema}
schemaActions={schemaActions}
{...props}
/>
</ThemeProvider>
Expand Down Expand Up @@ -116,7 +112,7 @@ test('shows the snackbar after successfully importing a contact', async () => {
board.getValue.mockImplementation(id => id);
let resolveContactP;
const contactP = new Promise(res => (resolveContactP = res));
schema.contacts.actions.create.mockImplementation(_ => contactP);
schemaActions.createContact.mockImplementation(_ => contactP);

expect(component.find(Snackbar).props().open).toBe(false);

Expand All @@ -132,7 +128,7 @@ test('shows the snackbar after successfully importing a contact', async () => {

const snackbar = component.find(Snackbar);
expect(board.getValue).toHaveBeenCalledWith('123');
expect(schema.contacts.actions.create).toHaveBeenCalledWith('123', 'foo');
expect(schemaActions.createContact).toHaveBeenCalledWith('123', 'foo');
expect(snackbar.props().open).toBe(true);
expect(snackbar.props().message).toBe('Successfully imported contact.');
expect(component.find(CircularProgress).length).toBe(0);
Expand Down
2 changes: 1 addition & 1 deletion packages/wallet/ui/src/views/tests/Dapps.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ test('lets you remove a dapp', async () => {
await act(async () =>
firstDappSettingsButton
.props()
.onClick({ currentTarget: firstDappPopover }),
.onClick({ currentTarget: firstDappPopover.getDOMNode() }),
);
component.update();

Expand Down
14 changes: 5 additions & 9 deletions packages/wallet/ui/src/views/tests/Issuers.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ const board = {
const services = {
board,
};
const schema = {
issuers: {
actions: {
create: jest.fn(),
},
},
const schemaActions = {
createIssuer: jest.fn(),
};

const withApplicationContext = (Component, _) => ({ ...props }) => {
Expand All @@ -64,7 +60,7 @@ const withApplicationContext = (Component, _) => ({ ...props }) => {
<Component
pendingPurseCreations={pendingPurseCreations}
issuers={issuers}
schema={schema}
schemaActions={schemaActions}
services={services}
{...props}
/>
Expand Down Expand Up @@ -124,7 +120,7 @@ test('shows the snackbar after successfully importing an issuer', async () => {
board.getValue.mockImplementation(id => id);
let resolveIssuerP;
const issuerP = new Promise(res => (resolveIssuerP = res));
schema.issuers.actions.create.mockImplementation(_ => issuerP);
schemaActions.createIssuer.mockImplementation(_ => issuerP);

expect(component.find(Snackbar).props().open).toBe(false);

Expand All @@ -140,7 +136,7 @@ test('shows the snackbar after successfully importing an issuer', async () => {

const snackbar = component.find(Snackbar);
expect(board.getValue).toHaveBeenCalledWith('123');
expect(schema.issuers.actions.create).toHaveBeenCalledWith('123', 'foo');
expect(schemaActions.createIssuer).toHaveBeenCalledWith('123', 'foo');
expect(snackbar.props().open).toBe(true);
expect(snackbar.props().message).toBe('Successfully imported issuer.');
expect(component.find(CircularProgress).length).toBe(1);
Expand Down

0 comments on commit 21bdfd1

Please sign in to comment.