diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b7e788a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: node_js + +node_js: + - '12' + +env: + - workerCount=3 timeout=600000 + +script: + - npm run test + +install: + - npm run bootstrap + +cache: + directories: + - node_modules \ No newline at end of file diff --git a/package.json b/package.json index 9ffa8d5..114024e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "build": "lerna run build --stream", "watch": "lerna run --parallel watch", "prebuild": "rm -rf ./packages/**/lib/", + "test": "lerna run test --stream", "format": "prettier --write" }, "workspaces": [ @@ -22,7 +23,7 @@ } }, "lint-staged": { - "*.{js,jsx,ts,tsx,json,babelrc}": [ + "*.{js,jsx,ts,tsx,babelrc}": [ "yarn run format", "git add" ] diff --git a/packages/backend/package.json b/packages/backend/package.json index b559b56..061790d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "@slate-collaborative/backend", - "version": "0.0.1", + "version": "0.0.2", "files": [ "lib" ], @@ -25,7 +25,7 @@ "watch": "yarn build:js -w" }, "dependencies": { - "@slate-collaborative/bridge": "^0.0.1", + "@slate-collaborative/bridge": "^0.0.2", "automerge": "^0.12.1", "lodash": "^4.17.15", "socket.io": "^2.2.0", diff --git a/packages/bridge/.babelrc b/packages/bridge/.babelrc index a2309a2..89aef8b 100644 --- a/packages/bridge/.babelrc +++ b/packages/bridge/.babelrc @@ -1,5 +1,15 @@ { - "presets": ["@babel/env", "@babel/typescript"], + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "esmodules": false + } + } + ], + "@babel/typescript" + ], "plugins": [ "@babel/proposal-class-properties", "@babel/proposal-object-rest-spread" diff --git a/packages/bridge/package.json b/packages/bridge/package.json index 7e412f1..ae6b788 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -1,6 +1,6 @@ { "name": "@slate-collaborative/bridge", - "version": "0.0.1", + "version": "0.0.2", "files": [ "lib" ], @@ -21,7 +21,8 @@ "build": "yarn run build:types && yarn run build:js", "build:types": "tsc --emitDeclarationOnly", "build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline", - "watch": "yarn build:js -w" + "watch": "yarn build:js -w", + "test": "jest" }, "dependencies": { "typescript": "^3.6.3" @@ -32,7 +33,10 @@ "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/preset-env": "^7.6.0", - "@babel/preset-typescript": "^7.6.0" + "@babel/preset-typescript": "^7.6.0", + "@types/jest": "^24.0.19", + "jest": "^24.9.0", + "ts-jest": "^24.1.0" }, "directories": { "lib": "lib" @@ -41,5 +45,14 @@ "slate", "automerge", "bridge" - ] + ], + "jest": { + "roots": [ + "/src" + ], + "transform": { + "^.+\\.ts?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$" + } } diff --git a/packages/bridge/src/apply/annotation.ts b/packages/bridge/src/apply/annotation.ts index dd7326a..b31b595 100644 --- a/packages/bridge/src/apply/annotation.ts +++ b/packages/bridge/src/apply/annotation.ts @@ -1,17 +1,19 @@ import { Operation, SyncDoc } from '../model/index' +// TODO: handle annotation ops + export const addAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { - console.log('addAnnotation!!!', op.toJS()) + // console.log('addAnnotation!!!', op.toJS()) return doc } export const removeAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { - console.log('removeAnnotation!!!', op.toJS()) + // console.log('removeAnnotation!!!', op.toJS()) return doc } export const setAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { - console.log('setAnnotation!!!', op.toJS()) + // console.log('setAnnotation!!!', op.toJS()) return doc } diff --git a/packages/bridge/src/apply/index.ts b/packages/bridge/src/apply/index.ts index 2679830..b4ea794 100644 --- a/packages/bridge/src/apply/index.ts +++ b/packages/bridge/src/apply/index.ts @@ -17,7 +17,7 @@ const opType: any = { // set_value: setValue } -export const applyOperation = (doc: SyncDoc, op: Operation): SyncDoc => { +const applyOperation = (doc: SyncDoc, op: Operation): SyncDoc => { try { const applyOp = opType[op.type] @@ -34,5 +34,7 @@ export const applyOperation = (doc: SyncDoc, op: Operation): SyncDoc => { } } -export const applySlateOps = (doc: SyncDoc, operations: Operations) => +const applySlateOps = (doc: SyncDoc, operations: Operations) => operations.reduce(applyOperation, doc) + +export { applyOperation, applySlateOps } diff --git a/packages/bridge/src/convert/convert.spec.ts b/packages/bridge/src/convert/convert.spec.ts new file mode 100644 index 0000000..a2636d8 --- /dev/null +++ b/packages/bridge/src/convert/convert.spec.ts @@ -0,0 +1,34 @@ +import * as Automerge from 'automerge' +import { toSlateOp } from './index' +import { createDoc, cloneDoc, createParagraphJSON } from '../utils' + +describe('convert operations to slatejs model', () => { + it('convert insert operations', () => { + const doc1 = createDoc() + const doc2 = cloneDoc(doc1) + + const change = Automerge.change(doc1, 'change', (d: any) => { + d.document.nodes.push(createParagraphJSON('hello!')) + d.document.nodes[1].nodes[0].text = 'hello!' + }) + + const operations = Automerge.diff(doc2, change) + + const slateOps = toSlateOp(operations, change) + + const expectedOps = [ + { + type: 'insert_node', + path: [1], + node: { object: 'block', type: 'paragraph', nodes: [] } + }, + { + type: 'insert_node', + path: [1, 0], + node: { object: 'text', marks: [], text: 'hello!' } + } + ] + + expect(slateOps).toStrictEqual(expectedOps) + }) +}) diff --git a/packages/bridge/src/convert/set.ts b/packages/bridge/src/convert/set.ts index 8927b33..25451a0 100644 --- a/packages/bridge/src/convert/set.ts +++ b/packages/bridge/src/convert/set.ts @@ -20,6 +20,7 @@ const AnnotationSetOp = ({ key, value }: Automerge.Diff) => (map, doc) => { /** * Looks like set_annotation option is broken, temporary disabled */ + // if (!doc.annotations[key]) { op = { type: 'add_annotation', diff --git a/packages/bridge/src/cursor/index.ts b/packages/bridge/src/cursor/index.ts index c8d7087..878902d 100644 --- a/packages/bridge/src/cursor/index.ts +++ b/packages/bridge/src/cursor/index.ts @@ -51,7 +51,7 @@ export const removeCursor = (doc: SyncDoc, key: CursorKey) => { return doc } -export const cursorOpFilter = (ops: Immutable.List, type: string) => +export const cursorOpFilter = (ops: any, type: string): any => ops.filter(op => { if (op.type === 'set_annotation') { return !( diff --git a/packages/bridge/src/utils/index.ts b/packages/bridge/src/utils/index.ts index 3029458..d0368fd 100644 --- a/packages/bridge/src/utils/index.ts +++ b/packages/bridge/src/utils/index.ts @@ -1,7 +1,9 @@ import toSync from './toSync' import hexGen from './hexGen' -export const toJS = node => { +export * from './testUtils' + +const toJS = node => { try { return JSON.parse(JSON.stringify(node)) } catch (e) { @@ -10,8 +12,8 @@ export const toJS = node => { } } -export const cloneNode = node => toSync(toJS(node)) +const cloneNode = node => toSync(toJS(node)) const toSlatePath = path => (path ? path.filter(d => Number.isInteger(d)) : []) -export { toSync, toSlatePath, hexGen } +export { toSync, toJS, toSlatePath, hexGen, cloneNode } diff --git a/packages/bridge/src/utils/testUtils.ts b/packages/bridge/src/utils/testUtils.ts new file mode 100644 index 0000000..28ca52a --- /dev/null +++ b/packages/bridge/src/utils/testUtils.ts @@ -0,0 +1,24 @@ +import * as Automerge from 'automerge' +import { ValueJSON, TextJSON, NodeJSON } from 'slate' + +export const createTextJSON = (text: string = ''): TextJSON => ({ + object: 'text', + marks: [], + text +}) + +export const createParagraphJSON = (text: string = ''): NodeJSON => ({ + object: 'block', + type: 'paragraph', + nodes: [createTextJSON(text)] +}) + +export const createValueJSON = (): ValueJSON => ({ + document: { + nodes: [createParagraphJSON()] + } +}) + +export const createDoc = () => Automerge.from(createValueJSON()) + +export const cloneDoc = doc => Automerge.change(doc, '', d => d) diff --git a/packages/client/package.json b/packages/client/package.json index 6682be4..78081c1 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@slate-collaborative/client", - "version": "0.0.1", + "version": "0.0.2", "files": [ "lib" ], @@ -25,7 +25,7 @@ }, "dependencies": { "@babel/preset-react": "^7.0.0", - "@slate-collaborative/bridge": "^0.0.1", + "@slate-collaborative/bridge": "^0.0.2", "automerge": "^0.12.1", "immutable": "^4.0.0-rc.12", "react": "^16.9.0", diff --git a/packages/example/package.json b/packages/example/package.json index 5a05cd2..d5bc7e3 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -5,8 +5,8 @@ "dependencies": { "@emotion/core": "^10.0.17", "@emotion/styled": "^10.0.17", - "@slate-collaborative/backend": "0.0.1", - "@slate-collaborative/client": "0.0.1", + "@slate-collaborative/backend": "0.0.2", + "@slate-collaborative/client": "0.0.2", "@types/faker": "^4.1.5", "@types/jest": "24.0.18", "@types/node": "12.7.5", @@ -27,7 +27,6 @@ }, "scripts": { "start": "react-scripts start", - "build": "react-scripts build", "dev": "concurrently \"yarn start\" \"yarn serve\"", "serve": "nodemon --watch ../backend/lib --inspect server.js" }, diff --git a/packages/example/tsconfig.json b/packages/example/tsconfig.json index 3821f08..7f81348 100644 --- a/packages/example/tsconfig.json +++ b/packages/example/tsconfig.json @@ -1,9 +1,15 @@ { - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "extends": "../../tsconfig.base.json", "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "baseUrl": "src", "jsx": "react", "allowJs": true,