Undo reported "nothing left to undo" after a successful undo (#72)
Build image / build-and-push (push) Successful in 19s
Build image / build-and-push (push) Successful in 19s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #72.
This commit is contained in:
@@ -49,6 +49,14 @@ describe('describeConflict', () => {
|
||||
describe('describeUndo', () => {
|
||||
const target = changeSet({ counts: [{ entityType: 'object', op: 'update', n: 3 }] })
|
||||
|
||||
// The bug this pair exists for: a real revert response carries a change set
|
||||
// whose counts the server didn't populate. Reading that as "nothing happened"
|
||||
// told the user a successful undo had done nothing.
|
||||
it('trusts the change set, not the tally, for whether anything happened', () => {
|
||||
const out = describeUndo({ id: 5 }, { changeSet: changeSet({ id: 6, counts: [] }), conflicts: [] })
|
||||
expect(out).toEqual({ tone: 'ok', message: 'Undone.' })
|
||||
})
|
||||
|
||||
it('is a plain success when nothing conflicted', () => {
|
||||
const out = describeUndo(target, {
|
||||
changeSet: changeSet({ id: 2, counts: [{ entityType: 'object', op: 'update', n: 3 }] }),
|
||||
@@ -61,6 +69,7 @@ describe('describeUndo', () => {
|
||||
// already a no-op — reachable by undoing a creation whose object is gone.
|
||||
// Claiming "Undone." there reports work that didn't happen.
|
||||
it("doesn't claim to have undone a no-op", () => {
|
||||
// A NULL change set — not an empty tally — is the server's no-op signal.
|
||||
const out = describeUndo(target, { changeSet: null, conflicts: [] })
|
||||
expect(out.tone).toBe('ok')
|
||||
expect(out.message).toBe('Nothing left to undo — this was already reversed.')
|
||||
|
||||
@@ -224,20 +224,23 @@ export interface UndoOutcome {
|
||||
*/
|
||||
export function describeUndo(target: UndoTarget, result: RevertResult): UndoOutcome {
|
||||
const skipped = result.conflicts.map(describeConflict).join('; ')
|
||||
// A NULL change set is the server's signal that nothing needed doing. An empty
|
||||
// `counts` is not the same thing and must not be read as one — that conflation
|
||||
// made a successful undo report "nothing left to undo", which is the worst
|
||||
// possible thing to tell someone about an action that just worked.
|
||||
const didSomething = result.changeSet != null
|
||||
const applied = result.changeSet ? totalChanges(result.changeSet) : 0
|
||||
if (result.conflicts.length === 0) {
|
||||
// The server answers 200 with a null change set when every revision was
|
||||
// already a no-op — reachable by undoing a creation whose object is gone.
|
||||
// Claiming "Undone." there would be reporting work that didn't happen.
|
||||
if (applied === 0) return { tone: 'ok', message: 'Nothing left to undo — this was already reversed.' }
|
||||
// Reachable by undoing a creation whose object is already gone.
|
||||
if (!didSomething) return { tone: 'ok', message: 'Nothing left to undo — this was already reversed.' }
|
||||
return { tone: 'ok', message: 'Undone.' }
|
||||
}
|
||||
if (applied === 0) {
|
||||
if (!didSomething) {
|
||||
return { tone: 'error', message: `Nothing was undone — ${skipped}.` }
|
||||
}
|
||||
// Only claim a denominator when we have one. "2 of 3" from a caller that
|
||||
// never knew the total would be a number invented to fill a sentence.
|
||||
const total = totalChanges(target)
|
||||
const scale = total > 0 ? `${applied} of ${total} changes undone` : 'Partly undone'
|
||||
const scale = total > 0 && applied > 0 ? `${applied} of ${total} changes undone` : 'Partly undone'
|
||||
return { tone: 'partial', message: `${scale} — ${skipped}.` }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user