Created
November 15, 2020 15:05
-
-
Save javierfernandes/34186422ba8a444d1bee4f4deba092f8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
const author = { sessionId: 'my_session', user: { _id: 'JOHN' } } | |
const UNDO = (_id, index = 0, timestamp) => ({ _id: `-${_id}-${index}`, author, reverts: { _id }, timestamp }) | |
const REDO = (_id, index = 0, timestamp) => ({ _id: `+${_id}-${index}`, author, reapplies: { _id }, timestamp }) | |
const change = (_id, timestamp) => ({ _id, author, timestamp }) | |
const parseArray = elementParser => pipe( | |
drop(1), dropLast(1), // [ ... ] | |
trim, | |
split(','), | |
map(trim), | |
filter(pipe(equals(''), not)), | |
map(elementParser) | |
) | |
const extractMatch = regex => pipe(match(regex), nth(1)) | |
const extractParam = extractMatch(/^[UR]\(([^)]*)\)$/) | |
const extractCursorId = extractMatch(/^\(([^)]*)\)$/) | |
const parseHistory = parseArray(cond([ | |
[test(/^U\((.*)\)$/), pipe(extractParam, UNDO)], | |
[test(/^R\((.*)\)$/), pipe(extractParam, REDO)], | |
[T, change] | |
])) | |
const parseItems = parseArray(cond([ | |
[test(/^\([^)]*\)$/), pipe(extractCursorId, change, assoc('hasCursor', true))], | |
[T, change] | |
])) | |
const doParsing = pipe( | |
split('->'), | |
map(trim), | |
applySpec({ | |
history: pipe(nth(0), parseHistory), | |
items: pipe(nth(1), parseItems), | |
}), | |
) | |
const computeCursor = pipe( | |
applySpec({ | |
history: prop('history'), | |
items: prop('items'), | |
cursor: pipe(prop('items'), findIndex(propEq('hasCursor', true))), | |
}), | |
over(lensProp('items'), map(dissoc('hasCursor'))), | |
when(propEq('cursor', -1), e => ({ ...e, cursor: e.items.length })) | |
) | |
const parseInput = pipe(doParsing, computeCursor) | |
describe('Tests for DSL (for testing)', () => { | |
describe('parseInput', () => { | |
it('should parse empty arrays', () => { | |
expect(parseInput('[] -> []')).toEqual({ history: [], items: [], cursor: 0 }) | |
}) | |
describe('history parsing', () => { | |
[ | |
['[A] -> []', [change('A')]], | |
['[A, B] -> []', [change('A'), change('B')]], | |
['[A, B, C, D ] -> []', [change('A'), change('B'), change('C'), change('D')]], | |
['[U(A)] -> []', [UNDO('A')]], | |
['[R(A)] -> []', [REDO('A')]], | |
['[U(B), U(C), C, B, A] -> []', [UNDO('B'), UNDO('C'), change('C'), change('B'), change('A')]], | |
].forEach(([input, expected]) => { | |
it(`${input} -> ${JSON.stringify(expected)}`, () => { | |
expect(parseInput(input)).toEqual({ history: expected, items: [], cursor: 0 }) | |
}) | |
}) | |
}) | |
describe('expected items parsing', () => { | |
it('should parse items with one id', () => { | |
expect(parseInput('[] -> [A]')).toEqual({ history: [], items: [change('A')], cursor: 1 }) | |
}) | |
it('should parse items with two ids', () => { | |
expect(parseInput('[] -> [A, B ]')).toEqual({ history: [], items: [change('A'), change('B')], cursor: 2 }) | |
}) | |
it('should parse items with 1 id that is the current cursor', () => { | |
expect(parseInput('[] -> [(A)]')).toEqual({ history: [], items: [change('A')], cursor: 0 }) | |
}) | |
it('should parse the cursor at the middle', () => { | |
expect(parseInput('[] -> [C, (B), A]')).toEqual({ history: [], items: [change('C'), change('B'), change('A')], cursor: 1 }) | |
}) | |
}) | |
describe('combined examples', () => { | |
it('should parse one with UNDO, REDO and cursor', () => { | |
expect(parseInput('[R(B), R(A), U(A), U(B), B, A] -> [(B), A]')) | |
.toEqual({ history: [REDO('B'), REDO('A'), UNDO('A'), UNDO('B'), change('B'), change('A')], items: [change('B'), change('A')], cursor: 0 }) | |
}) | |
it('should fix a regression', () => { | |
expect(parseInput('[U(B), U(C), C, B, A] -> [C, B, (A)]')) | |
.toEqual({ history: [UNDO('B'), UNDO('C'), change('C'), change('B'), change('A')], items: [change('C'), change('B'), change('A')], cursor: 2 }) | |
}) | |
}) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment