diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 52a3449..771cbb4 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -2132,6 +2132,17 @@
"proto-list": "~1.2.1"
}
},
+ "connect": {
+ "version": "3.6.6",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
+ "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.0",
+ "parseurl": "~1.3.2",
+ "utils-merge": "1.0.1"
+ }
+ },
"console-browserify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
@@ -2478,6 +2489,14 @@
"node-addon-api": "^1.6.0"
}
},
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
@@ -2732,8 +2751,7 @@
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
- "dev": true
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.96",
@@ -2759,8 +2777,7 @@
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "dev": true
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"encoding": {
"version": "0.1.12",
@@ -2812,8 +2829,7 @@
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
- "dev": true
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -3124,6 +3140,27 @@
}
}
},
+ "finalhandler": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+ "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.1",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.3.1",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ }
+ }
+ },
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
@@ -3210,8 +3247,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -3232,14 +3268,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3254,20 +3288,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -3384,8 +3415,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -3397,7 +3427,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3412,7 +3441,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3420,14 +3448,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -3446,7 +3472,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -3527,8 +3552,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -3540,7 +3564,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3626,8 +3649,7 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -3663,7 +3685,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -3683,7 +3704,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3727,14 +3747,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -5419,8 +5437,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"nan": {
"version": "2.12.1",
@@ -5809,7 +5826,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "dev": true,
"requires": {
"ee-first": "1.1.1"
}
@@ -6002,8 +6018,7 @@
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
- "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
- "dev": true
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"pascalcase": {
"version": "0.1.1",
@@ -7190,6 +7205,14 @@
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
"dev": true
},
+ "rea": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/rea/-/rea-0.0.1.tgz",
+ "integrity": "sha1-EO+mFMyQc1Ib2mdLb8lQsDFb16Q=",
+ "requires": {
+ "connect": ">=1.4.1"
+ }
+ },
"react": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz",
@@ -8657,6 +8680,11 @@
"integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
"dev": true
},
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
"unquote": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
@@ -8781,6 +8809,11 @@
"object.getownpropertydescriptors": "^2.0.3"
}
},
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 40fe194..93055b1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -19,6 +19,7 @@
"dependencies": {
"@blueprintjs/core": "^3.10.0",
"@blueprintjs/icons": "^3.4.0",
+ "rea": "0.0.1",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-redux": "^6.0.0",
diff --git a/frontend/src/Documents/List.tsx b/frontend/src/Documents/List.tsx
new file mode 100644
index 0000000..444f13c
--- /dev/null
+++ b/frontend/src/Documents/List.tsx
@@ -0,0 +1,5 @@
+import * as React from "react";
+
+export function List() {
+ return
;
+}
diff --git a/frontend/src/Documents/Overview.tsx b/frontend/src/Documents/Overview.tsx
new file mode 100644
index 0000000..8c39515
--- /dev/null
+++ b/frontend/src/Documents/Overview.tsx
@@ -0,0 +1,62 @@
+import { H1 } from "@blueprintjs/core";
+import * as React from "react";
+import { connect } from "react-redux";
+import { Dispatch } from "redux";
+import { IDocumentJSON } from "~../../src/entity/Document";
+import { fetchDocsStart } from "~redux/docs/actions";
+import { IAppState } from "~redux/reducers";
+
+export interface IOverviewComponentProps {
+ recent: IDocumentJSON[] | null;
+ all: IDocumentJSON[] | null;
+ fetching: boolean;
+
+ fetchDocs: () => void;
+}
+
+export class OverviewComponent extends React.PureComponent<
+ IOverviewComponentProps,
+ null
+> {
+ constructor(props: IOverviewComponentProps) {
+ super(props);
+ }
+
+ public componentDidMount() {
+ if (!this.props.all) {
+ this.props.fetchDocs();
+ }
+ }
+
+ public render() {
+ let docsList;
+ if (this.props.all) {
+ docsList = this.props.all.map(doc => (
+
+
{doc.name}
+
{doc.content}
+
+ ));
+ }
+ return docsList || Loading
;
+ }
+}
+
+function mapStateToProps(state: IAppState) {
+ return {
+ recent: state.docs.recent,
+ all: state.docs.all,
+ fetching: state.docs.fetching,
+ };
+}
+
+function mapDispatchToProps(dispatch: Dispatch) {
+ return {
+ fetchDocs: () => dispatch(fetchDocsStart()),
+ };
+}
+
+export const Overview = connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(OverviewComponent);
diff --git a/frontend/src/Home/Home.tsx b/frontend/src/Home/Home.tsx
index 6f7b2bf..1ee152e 100644
--- a/frontend/src/Home/Home.tsx
+++ b/frontend/src/Home/Home.tsx
@@ -8,9 +8,10 @@ import {
} from "@blueprintjs/core";
import * as React from "react";
import { connect } from "react-redux";
-import { RouteComponentProps, withRouter } from "react-router";
+import { Route, RouteComponentProps, Switch, withRouter } from "react-router";
import { Dispatch } from "redux";
import { IUserJSON } from "~../../src/entity/User";
+import { Overview } from "~Documents/Overview";
import { IAppState } from "~redux/reducers";
import { logoutUser } from "~redux/user/actions";
@@ -70,7 +71,11 @@ export class HomeComponent extends React.PureComponent {
/>
-
+
+
+
+
+
>
)
);
diff --git a/frontend/src/redux/api/docs/index.ts b/frontend/src/redux/api/docs/index.ts
new file mode 100644
index 0000000..6dac8c7
--- /dev/null
+++ b/frontend/src/redux/api/docs/index.ts
@@ -0,0 +1,14 @@
+import { IDocumentJSON } from "~../../src/entity/Document";
+import { IAPIResponse } from "~../../src/types";
+
+import { fetchJSONAuth } from "../utils";
+
+export async function fetchRecentDocs(): Promise<
+ IAPIResponse
+> {
+ return fetchJSONAuth("/docs/list/recent", "GET");
+}
+
+export async function fetchAllDocs(): Promise> {
+ return fetchJSONAuth("/docs/list", "GET");
+}
diff --git a/frontend/src/redux/docs/actions.ts b/frontend/src/redux/docs/actions.ts
new file mode 100644
index 0000000..a347450
--- /dev/null
+++ b/frontend/src/redux/docs/actions.ts
@@ -0,0 +1,47 @@
+import { Action } from "redux";
+import { IDocumentJSON } from "~../../src/entity/Document";
+
+export enum DocsTypes {
+ DOCS_FETCH_START = "DOCS_FETCH_START",
+ DOCS_FETCH_FAIL = "DOCS_FETCH_FAIL",
+ DOCS_FETCH_SUCCESS = "DOCS_FETCH_SUCCESS",
+}
+
+export interface IDocsFetchStartAction extends Action {
+ type: DocsTypes.DOCS_FETCH_START;
+}
+
+export interface IDocsFetchFailAction extends Action {
+ type: DocsTypes.DOCS_FETCH_FAIL;
+ payload: {
+ error: string;
+ };
+}
+
+export interface IDocsFetchSuccessAction extends Action {
+ type: DocsTypes.DOCS_FETCH_SUCCESS;
+ payload: {
+ recent: IDocumentJSON[];
+ all: IDocumentJSON[];
+ };
+}
+
+export function fetchDocsStart(): IDocsFetchStartAction {
+ return { type: DocsTypes.DOCS_FETCH_START };
+}
+
+export function fetchDocsFail(error: string): IDocsFetchFailAction {
+ return { type: DocsTypes.DOCS_FETCH_FAIL, payload: { error } };
+}
+
+export function fetchDocsSuccess(
+ recent: IDocumentJSON[],
+ all: IDocumentJSON[],
+): IDocsFetchSuccessAction {
+ return { type: DocsTypes.DOCS_FETCH_SUCCESS, payload: { recent, all } };
+}
+
+export type DocsAction =
+ | IDocsFetchStartAction
+ | IDocsFetchFailAction
+ | IDocsFetchSuccessAction;
diff --git a/frontend/src/redux/docs/reducer.ts b/frontend/src/redux/docs/reducer.ts
new file mode 100644
index 0000000..d4d7ce8
--- /dev/null
+++ b/frontend/src/redux/docs/reducer.ts
@@ -0,0 +1,35 @@
+import { Reducer } from "react";
+import { IDocumentJSON } from "~../../src/entity/Document";
+
+import { DocsAction, DocsTypes } from "./actions";
+
+export interface IDocsState {
+ recent: IDocumentJSON[] | null;
+ all: IDocumentJSON[] | null;
+ fetching: boolean;
+ error: string | null;
+}
+
+const defaultDocsState: IDocsState = {
+ recent: null,
+ all: null,
+ fetching: false,
+ error: null,
+};
+
+export const docsReducer: Reducer = (
+ state: IDocsState = defaultDocsState,
+ action: DocsAction,
+) => {
+ switch (action.type) {
+ case DocsTypes.DOCS_FETCH_START:
+ return { ...defaultDocsState, fetching: true };
+ case DocsTypes.DOCS_FETCH_SUCCESS:
+ return { ...defaultDocsState, ...action.payload };
+ case DocsTypes.DOCS_FETCH_FAIL:
+ return { ...defaultDocsState, ...action.payload };
+ default:
+ return state;
+ break;
+ }
+};
diff --git a/frontend/src/redux/docs/sagas.ts b/frontend/src/redux/docs/sagas.ts
new file mode 100644
index 0000000..2d698dd
--- /dev/null
+++ b/frontend/src/redux/docs/sagas.ts
@@ -0,0 +1,56 @@
+import { delay } from "redux-saga";
+import {
+ all,
+ call,
+ cancel,
+ fork,
+ put,
+ race,
+ takeLatest,
+} from "redux-saga/effects";
+import { fetchAllDocs, fetchRecentDocs } from "~redux/api/docs";
+
+import {
+ DocsTypes,
+ fetchDocsFail,
+ fetchDocsSuccess,
+ IDocsFetchStartAction,
+} from "./actions";
+
+function* startSpinner() {
+ yield delay(300);
+}
+
+function* docsFetchStart(action: IDocsFetchStartAction) {
+ try {
+ const spinner = yield fork(startSpinner);
+
+ const { response, timeout } = yield race({
+ response: all([call(fetchRecentDocs), call(fetchAllDocs)]),
+ timeout: call(delay, 10000),
+ });
+
+ yield cancel(spinner);
+
+ if (timeout) {
+ yield put(fetchDocsFail("Timeout"));
+ return;
+ }
+
+ if (response) {
+ if (response[0].data == null || response[1].data == null) {
+ yield put(fetchDocsFail(response[0].error));
+ } else {
+ const recentDocs = response[0].data;
+ const allDocs = response[1].data;
+ yield put(fetchDocsSuccess(recentDocs, allDocs));
+ }
+ }
+ } catch (e) {
+ yield put(fetchDocsFail("Internal error"));
+ }
+}
+
+export function* docsSaga() {
+ yield all([takeLatest(DocsTypes.DOCS_FETCH_START, docsFetchStart)]);
+}
diff --git a/frontend/src/redux/reducers.ts b/frontend/src/redux/reducers.ts
index eedb765..433e49d 100644
--- a/frontend/src/redux/reducers.ts
+++ b/frontend/src/redux/reducers.ts
@@ -3,11 +3,13 @@ import { persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import { authReducer, IAuthState } from "~redux/auth/reducer";
+import { docsReducer, IDocsState } from "./docs/reducer";
import { IUserState, userReducer } from "./user/reducer";
export interface IAppState {
auth: IAuthState;
user: IUserState;
+ docs: IDocsState;
}
const authPersistConfig = {
@@ -19,4 +21,5 @@ const authPersistConfig = {
export const rootReducer = combineReducers({
auth: persistReducer(authPersistConfig, authReducer),
user: userReducer,
+ docs: docsReducer,
});
diff --git a/frontend/src/redux/store.ts b/frontend/src/redux/store.ts
index 6dc7290..dfb31b4 100644
--- a/frontend/src/redux/store.ts
+++ b/frontend/src/redux/store.ts
@@ -5,6 +5,7 @@ import { rootReducer } from "~redux/reducers";
import { setToken } from "./api/utils";
import { authSaga } from "./auth/sagas";
+import { docsSaga } from "./docs/sagas";
import { getUser } from "./user/actions";
import { userSaga } from "./user/sagas";
@@ -22,3 +23,4 @@ export const persistor = persistStore(store, null, () => {
sagaMiddleware.run(authSaga);
sagaMiddleware.run(userSaga);
+sagaMiddleware.run(docsSaga);
diff --git a/src/entity/Document.ts b/src/entity/Document.ts
index 1eff3fc..0ba71f5 100644
--- a/src/entity/Document.ts
+++ b/src/entity/Document.ts
@@ -8,10 +8,14 @@ import {
import { User } from "./User";
-export type IDocumentJSON = Pick<
- Document,
- "id" | "user" | "name" | "content" | "createdAt"
->;
+export interface IDocumentJSON {
+ id: number;
+ user: number;
+ name: string;
+ content: string;
+ createdAt: number;
+ editedAt: number;
+}
@Entity()
export class Document extends BaseEntity {
@@ -41,4 +45,15 @@ export class Document extends BaseEntity {
this.name = name;
this.content = content;
}
+
+ public toJSON(user: number): IDocumentJSON {
+ return {
+ id: this.id,
+ user: user as any,
+ name: this.name,
+ content: this.content,
+ createdAt: this.createdAt.getTime(),
+ editedAt: this.editedAt.getTime(),
+ };
+ }
}
diff --git a/src/routes/docs.ts b/src/routes/docs.ts
index 3b60db2..556fc77 100644
--- a/src/routes/docs.ts
+++ b/src/routes/docs.ts
@@ -3,8 +3,6 @@ import { Document } from "~entity/Document";
export const docsRouter = new Router();
-export type IDocumentJSON = Pick;
-
docsRouter.post("/docs/new", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
@@ -31,11 +29,7 @@ docsRouter.post("/docs/new", async ctx => {
ctx.body = {
error: false,
- data: {
- id: document.id,
- name: document.name,
- content: document.content,
- },
+ data: document.toJSON(user.id),
};
});
@@ -81,11 +75,7 @@ docsRouter.patch("/docs/byID/:id", async ctx => {
ctx.body = {
error: false,
- data: {
- id: document.id,
- name: document.name,
- content: document.content,
- },
+ data: document.toJSON(user.id),
};
});
@@ -100,11 +90,25 @@ docsRouter.get("/docs/list", async ctx => {
ctx.body = {
error: false,
- data: documents.map(document => ({
- id: document.id,
- name: document.name,
- content: document.content,
- })),
+ data: documents.map(document => document.toJSON(user.id)),
+ };
+});
+
+docsRouter.get("/docs/list/recent", async ctx => {
+ if (!ctx.state.user) {
+ ctx.throw(401);
+ }
+
+ const { user } = ctx.state;
+
+ const documents = await Document.find({
+ where: { user: user.id },
+ order: { editedAt: "DESC" },
+ });
+
+ ctx.body = {
+ error: false,
+ data: documents.map(document => document.toJSON(user.id)),
};
});
@@ -131,11 +135,7 @@ docsRouter.get("/docs/byID/:id", async ctx => {
ctx.body = {
error: false,
- data: {
- id: document.id,
- name: document.name,
- content: document.content,
- },
+ data: document.toJSON(user.id),
};
});
diff --git a/src/types.ts b/src/types.ts
new file mode 100644
index 0000000..88b4e40
--- /dev/null
+++ b/src/types.ts
@@ -0,0 +1,4 @@
+export interface IAPIResponse {
+ data: T | null;
+ error: string | null;
+}
diff --git a/tests/integration/docs.test.ts b/tests/integration/docs.test.ts
index 0e041e3..28150a6 100644
--- a/tests/integration/docs.test.ts
+++ b/tests/integration/docs.test.ts
@@ -3,8 +3,7 @@ import { connect } from "config/database";
import * as request from "supertest";
import { getConnection } from "typeorm";
import { app } from "~app";
-import { Document } from "~entity/Document";
-import { IDocumentJSON } from "~routes/docs";
+import { Document, IDocumentJSON } from "~entity/Document";
import { ISeed, seedDB } from "./util";
@@ -89,12 +88,38 @@ describe("docs", () => {
const documents = response.body.data as IDocumentJSON[];
+ const userDocs = [seed.doc1.toJSON(seed.user1.id)];
+
+ expect(documents).to.deep.equal(userDocs);
+ });
+
+ it("should list recent docs", async () => {
+ const doc1 = new Document(seed.user1, "doc1", "");
+ doc1.editedAt = new Date(doc1.editedAt.getTime() + 10000);
+ await doc1.save();
+ const doc2 = new Document(seed.user1, "doc2", "");
+ doc2.editedAt = new Date(doc2.editedAt.getTime() + 20000);
+ await doc2.save();
+ const doc3 = new Document(seed.user1, "doc3", "");
+ doc3.editedAt = new Date(doc3.editedAt.getTime() + 30000);
+ await doc3.save();
+
+ const response = await request(callback)
+ .get("/docs/list/recent")
+ .set({
+ Authorization: `Bearer ${seed.user1.toJWT()}`,
+ })
+ .expect(200);
+
+ expect(response.body.error).to.be.false;
+
+ const documents = response.body.data as IDocumentJSON[];
+
const userDocs = [
- {
- id: seed.doc1.id,
- name: seed.doc1.name,
- content: seed.doc1.content,
- },
+ doc3.toJSON(seed.user1.id),
+ doc2.toJSON(seed.user1.id),
+ doc1.toJSON(seed.user1.id),
+ seed.doc1.toJSON(seed.user1.id),
];
expect(documents).to.deep.equal(userDocs);
@@ -112,11 +137,7 @@ describe("docs", () => {
const document = response.body.data as IDocumentJSON;
- const usedDoc = {
- id: seed.doc1.id,
- name: seed.doc1.name,
- content: seed.doc1.content,
- };
+ const usedDoc = seed.doc1.toJSON(seed.user1.id);
expect(document).to.deep.equal(usedDoc);
});