Initial minimal logins API connection to datastore #62
Initial minimal logins API connection to datastore #62
Conversation
Oof, actually: Adding a WIP to the title, as I appear to have broken something just before submitting 😞 |
e444e5f
to
5f749f2
Compare
@@ -37,7 +37,13 @@ export function cacheReducer(state = {items: [], currentItem: null}, action) { | |||
case actions.ADD_ITEM_COMPLETED: | |||
return { | |||
...state, | |||
items: [...state.items, makeItemSummary(action.item)], | |||
items: [ | |||
// HACK: add dispatched via Logins API events may be a duplicate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small hacky wrinkle here: Since I'm broadcasting datastore changes based on Logins API events without any source, the UI source that made the changes will get its own change dispatched back to it. This will look like a duplicate. So, I papered over that by making the "add" action idempotent here.
Okay, I think I worked out the issues. At least, insofar as I'm going to take off the "WIP" title and go get some lunch. |
Oh, but one other thing I may need to investigate for this PR or in a follow-up: Nothing here calls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Seems to be working for me. Called out a couple smallish things.
timeCreated: Date.now(), | ||
timePasswordChanged: Date.now(), | ||
}; | ||
await browser.experiments.logins.add(added); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I can just silently log them, though datastore.js does throw errors for other validation problems and such. Kind of figured it was useful to let these throw too, though it doesn't look like we do anything useful with them yet. (e.g. report an error over a message port, etc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
datastore.js does throw errors for other validation problems and such
Ah, ok. Probably fine as is, then.
That was on the list of things to get to from before; I'll make sure it's accounted for in our issues. |
…API to apply changes
@@ -44,19 +44,16 @@ export default function initializeMessagePorts() { | |||
case "add_item": | |||
return openDataStore().then(async (ds) => { | |||
const item = await ds.add(message.item); | |||
broadcast({type: "added_item", item}, sender); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Realized that since I've got the datastore now broadcasting these on the Logins API event handlers, all these messages got doubled up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes a lot more sense.
I hope it's clear the code was in an "evolutionary transitional" phase when you picked it up (-:
@@ -80,7 +83,6 @@ describe("background > message ports", () => { | |||
itemId = result.item.id; | |||
|
|||
expect(result.item).to.deep.include(item); | |||
expect(selfListener).to.have.callCount(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the datastore broadcasts messages to relay events from the Logins API, there's no sender or self available at that time to refrain from sending the event back to "self"
logins: { | ||
async getAll() { return []; }, | ||
async add(login) { | ||
browser.experiments.logins.onAdded.getListener()({ login }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping I could be less verbose here by just using this
rather than browser.experiments.logins
, but that apparently ends up being the wrong reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔
Addressed comments except for wrapping things in try/catch to log errors. We might want to let those throw, so we can catch those higher up along with datastore validation errors. |
Nice work 👍 Took this branch for a test drive, and all the logins add / update / delete happy paths are seamlessly mirrored across the logins management UI in Firefox, and the Lockbox management UI. I dunno if @linuxwolf wants to take a pass before merging, but LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r+
logins.onRemoved.addListener(({ login }) => dataStore.removeInfo(login)); | ||
} | ||
|
||
export default openDataStore; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this pattern better
@@ -44,19 +44,16 @@ export default function initializeMessagePorts() { | |||
case "add_item": | |||
return openDataStore().then(async (ds) => { | |||
const item = await ds.add(message.item); | |||
broadcast({type: "added_item", item}, sender); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes a lot more sense.
I hope it's clear the code was in an "evolutionary transitional" phase when you picked it up (-:
const LOGINS_METHODS = ["getAll", "add", "update", "remove"]; | ||
const LOGINS_EVENTS = ["Added", "Updated", "Removed"].map(name => `on${name}`); | ||
|
||
describe("background > datastore", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍
logins: { | ||
async getAll() { return []; }, | ||
async add(login) { | ||
browser.experiments.logins.onAdded.getListener()({ login }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔
Connected to #21
This doesn't actually fix #21, but it's kind of a start as it connects up the add-on to the real logins info data.
Testing and Review Notes