test(ui): refactor all tests

This commit is contained in:
hexxa 2021-08-24 20:00:16 +08:00 committed by Hexxa
parent dc3783a091
commit f2dd36c630
12 changed files with 534 additions and 701 deletions

View file

@ -6,115 +6,164 @@ import {
ListSharingsResp,
} from "./";
export class FilesClient {
private url: string;
export interface FilesClientResps {
createMockRespID?: number;
createMockResp?: Response;
deleteMockResp?: Response;
metadataMockResp?: Response;
mkdirMockResp?: Response;
moveMockResp?: Response;
uploadChunkMockResp?: Response<UploadStatusResp>;
uploadChunkMockRespID?: number;
uploadStatusMockResp?: Response<UploadStatusResp>;
uploadStatusMockRespID?: number;
listMockResp?: Response<ListResp>;
listHomeMockResp?: Response<ListResp>;
listUploadingsMockResp?: Response<ListUploadingsResp>;
deleteUploadingMockResp?: Response;
addSharingMockResp?: Response;
deleteSharingMockResp?: Response;
listSharingsMockResp?: Response<ListSharingsResp>;
isSharingMockResp?: Response;
}
private createMockRespID: number = 0;
private createMockResps: Array<Promise<Response>>;
private deleteMockResp: Promise<Response>;
private metadataMockResp: Promise<Response>;
private mkdirMockResp: Promise<Response>;
private moveMockResp: Promise<Response>;
private uploadChunkMockResps: Array<Promise<Response<UploadStatusResp>>>;
private uploadChunkMockRespID: number = 0;
private uploadStatusMockResps: Array<Promise<Response<UploadStatusResp>>>;
private uploadStatusMockRespID: number = 0;
private listMockResp: Promise<Response<ListResp>>;
private listHomeMockResp: Promise<Response<ListResp>>;
private listUploadingsMockResp: Promise<Response<ListUploadingsResp>>;
private deleteUploadingMockResp: Promise<Response>;
private addSharingMockResp: Promise<Response>;
private deleteSharingMockResp: Promise<Response>;
private listSharingsMockResp: Promise<Response<ListSharingsResp>>;
private isSharingMockResp: Promise<Response>;
export const resps = {
createMockResp: { status: 200, statusText: "", data: {} },
deleteMockResp: { status: 200, statusText: "", data: {} },
metadataMockResp: { status: 200, statusText: "", data: {} },
mkdirMockResp: { status: 200, statusText: "", data: {} },
moveMockResp: { status: 200, statusText: "", data: {} },
uploadChunkMockResp: {
status: 200,
statusText: "",
data: {
path: "mockPath/file",
isDir: false,
fileSize: 5,
uploaded: 3,
},
},
uploadChunkMockRespID: 0,
uploadStatusMockResp: {
status: 200,
statusText: "",
data: {
path: "mockPath/file",
isDir: false,
fileSize: 5,
uploaded: 3,
},
},
uploadStatusMockRespID: 0,
listMockResp: {
status: 200,
statusText: "",
data: {
cwd: "mock_cwd",
metadatas: [
{
name: "mock_file",
size: 5,
modTime: "0",
isDir: false,
},
{
name: "mock_dir",
size: 0,
modTime: "0",
isDir: true,
},
],
},
},
listHomeMockResp: {
status: 200,
statusText: "",
data: {
cwd: "mock_home/files",
metadatas: [
{
name: "mock_file",
size: 5,
modTime: "0",
isDir: false,
},
{
name: "mock_dir",
size: 0,
modTime: "0",
isDir: true,
},
],
},
},
listUploadingsMockResp: {
status: 200,
statusText: "",
data: {
uploadInfos: [
{
realFilePath: "mock_ realFilePath1",
size: 5,
uploaded: 3,
},
{
realFilePath: "mock_ realFilePath2",
size: 5,
uploaded: 3,
},
],
},
},
deleteUploadingMockResp: { status: 200, statusText: "", data: {} },
addSharingMockResp: { status: 200, statusText: "", data: {} },
deleteSharingMockResp: { status: 200, statusText: "", data: {} },
listSharingsMockResp: {
status: 200,
statusText: "",
data: {
sharingDirs: ["mock_sharingfolder1", "mock_sharingfolder2"],
},
},
isSharingMockResp: { status: 200, statusText: "", data: {} },
};
export class MockFilesClient {
private url: string;
private resps: FilesClientResps;
constructor(url: string) {
this.url = url;
this.resps = resps;
}
createMock = (resps: Array<Promise<Response>>) => {
this.createMockResps = resps;
setMock = (resps: FilesClientResps) => {
this.resps = resps;
};
deleteMock = (resp: Promise<Response>) => {
this.deleteMockResp = resp;
};
metadataMock = (resp: Promise<Response>) => {
this.metadataMockResp = resp;
};
mkdirMock = (resp: Promise<Response>) => {
this.mkdirMockResp = resp;
};
moveMock = (resp: Promise<Response>) => {
this.moveMockResp = resp;
};
uploadChunkMock = (resps: Array<Promise<Response<UploadStatusResp>>>) => {
this.uploadChunkMockResps = resps;
};
uploadStatusMock = (resps: Array<Promise<Response<UploadStatusResp>>>) => {
this.uploadStatusMockResps = resps;
};
listMock = (resp: Promise<Response<ListResp>>) => {
this.listMockResp = resp;
};
listHomeMock = (resp: Promise<Response<ListResp>>) => {
this.listMockResp = resp;
};
listUploadingsMock = (resp: Promise<Response<ListUploadingsResp>>) => {
this.listUploadingsMockResp = resp;
};
deleteUploadingMock = (resp: Promise<Response>) => {
this.deleteUploadingMockResp = resp;
};
addSharingMock = (resp: Promise<Response>) => {
this.addSharingMockResp = resp;
};
deleteSharingMock = (resp: Promise<Response>) => {
this.deleteSharingMockResp = resp;
};
listSharingsMock = (resp: Promise<Response>) => {
this.listSharingsMockResp = resp;
};
isSharingMock = (resp: Promise<Response>) => {
this.isSharingMockResp = resp;
wrapPromise = (resp: any): Promise<any> => {
return new Promise<any>((resolve) => {
resolve(resp);
});
};
create = (filePath: string, fileSize: number): Promise<Response> => {
if (this.createMockRespID < this.createMockResps.length) {
return this.createMockResps[this.createMockRespID++];
}
throw new Error(
`this.createMockRespID (${this.createMockRespID}) out of bound: ${this.createMockResps.length}`
);
return this.wrapPromise(this.resps.createMockResp);
};
delete = (filePath: string): Promise<Response> => {
return this.deleteMockResp;
return this.wrapPromise(this.resps.deleteMockResp);
};
metadata = (filePath: string): Promise<Response> => {
return this.metadataMockResp;
return this.wrapPromise(this.resps.metadataMockResp);
};
mkdir = (dirpath: string): Promise<Response> => {
return this.mkdirMockResp;
return this.wrapPromise(this.resps.mkdirMockResp);
};
move = (oldPath: string, newPath: string): Promise<Response> => {
return this.moveMockResp;
return this.wrapPromise(this.resps.moveMockResp);
};
uploadChunk = (
@ -122,52 +171,42 @@ export class FilesClient {
content: string | ArrayBuffer,
offset: number
): Promise<Response<UploadStatusResp>> => {
if (this.uploadChunkMockRespID < this.uploadChunkMockResps.length) {
return this.uploadChunkMockResps[this.uploadChunkMockRespID++];
}
throw new Error(
`this.uploadChunkMockRespID (${this.uploadChunkMockRespID}) out of bound: ${this.uploadChunkMockResps.length}`
);
return this.wrapPromise(this.resps.uploadChunkMockResp);
};
uploadStatus = (filePath: string): Promise<Response<UploadStatusResp>> => {
if (this.uploadStatusMockRespID < this.uploadStatusMockResps.length) {
return this.uploadStatusMockResps[this.uploadStatusMockRespID++];
}
throw new Error(
`this.uploadStatusMockRespID (${this.uploadStatusMockRespID}) out of bound: ${this.uploadStatusMockResps.length}`
);
return this.wrapPromise(this.resps.uploadStatusMockResp);
};
list = (dirPath: string): Promise<Response<ListResp>> => {
return this.listMockResp;
return this.wrapPromise(this.resps.listMockResp);
};
listHome = (): Promise<Response<ListResp>> => {
return this.listHomeMockResp;
return this.wrapPromise(this.resps.listHomeMockResp);
};
listUploadings = (): Promise<Response<ListUploadingsResp>> => {
return this.listUploadingsMockResp;
return this.wrapPromise(this.resps.listUploadingsMockResp);
};
deleteUploading = (filePath: string): Promise<Response<Response>> => {
return this.deleteUploadingMockResp;
return this.wrapPromise(this.resps.deleteUploadingMockResp);
};
addSharing = (dirPath: string): Promise<Response> => {
return this.addSharingMockResp;
return this.wrapPromise(this.resps.addSharingMockResp);
};
deleteSharing = (dirPath: string): Promise<Response> => {
return this.deleteSharingMockResp;
return this.wrapPromise(this.resps.deleteSharingMockResp);
};
listSharings = (): Promise<Response<ListSharingsResp>> => {
return this.listSharingsMockResp;
return this.wrapPromise(this.resps.listSharingsMockResp);
};
isSharing = (dirPath: string): Promise<Response> => {
return this.isSharingMockResp;
return this.wrapPromise(this.resps.isSharingMockResp);
};
}

View file

@ -1,115 +1,157 @@
// TODO: replace this with jest mocks
import { Response } from "./";
export interface UsersClientResps {
loginMockResp: Response;
logoutMockResp: Response;
isAuthedMockResp: Response;
setPwdMockResp: Response;
forceSetPwdMockResp: Response;
addUserMockResp: Response;
delUserMockResp: Response;
listUsersMockResp: Response;
addRoleMockResp: Response;
delRoleMockResp: Response;
listRolesMockResp: Response;
selfMockResp: Response;
getCaptchaIDMockResp: Response;
}
export const resps = {
loginMockResp: { status: 200, statusText: "", data: {} },
logoutMockResp: { status: 200, statusText: "", data: {} },
isAuthedMockResp: { status: 200, statusText: "", data: {} },
setPwdMockResp: { status: 200, statusText: "", data: {} },
forceSetPwdMockResp: { status: 200, statusText: "", data: {} },
addUserMockResp: { status: 200, statusText: "", data: {} },
delUserMockResp: { status: 200, statusText: "", data: {} },
listUsersMockResp: {
status: 200,
statusText: "",
data: {
users: [
{
id: "0",
name: "mock_username0",
pwd: "mock_pwd0",
role: "mock_role0",
usedSpace: "128",
quota: {
spaceLimit: 1024,
uploadSpeedLimit: 1024,
downloadSpeedLimit: 1024,
},
},
{
id: "1",
name: "mock_username1",
pwd: "mock_pwd1",
role: "mock_role1",
usedSpace: "256",
quota: {
spaceLimit: 1024,
uploadSpeedLimit: 1024,
downloadSpeedLimit: 1024,
},
},
],
},
},
addRoleMockResp: { status: 200, statusText: "", data: {} },
delRoleMockResp: { status: 200, statusText: "", data: {} },
listRolesMockResp: {
status: 200,
statusText: "",
data: {
roles: ["admin", "users", "visitor"],
},
},
selfMockResp: {
status: 200,
statusText: "",
data: {
id: 0,
name: "mockUser",
role: "admin",
usedSpace: "256",
},
},
getCaptchaIDMockResp: {
status: 200,
statusText: "",
data: {
id: "mockCaptchaID",
},
},
};
export class MockUsersClient {
private url: string;
private loginMockResp: Promise<Response>;
private logoutMockResp: Promise<Response>;
private isAuthedMockResp: Promise<Response>;
private setPwdMockResp: Promise<Response>;
private forceSetPwdMockResp: Promise<Response>;
private addUserMockResp: Promise<Response>;
private delUserMockResp: Promise<Response>;
private listUsersMockResp: Promise<Response>;
private addRoleMockResp: Promise<Response>;
private delRoleMockResp: Promise<Response>;
private listRolesMockResp: Promise<Response>;
private selfMockResp: Promise<Response>;
private getCaptchaIDMockResp: Promise<Response>;
private resps: UsersClientResps;
constructor(url: string) {
this.url = url;
this.resps = resps;
}
loginMock = (resp: Promise<Response>) => {
this.loginMockResp = resp;
setMock = (resps: UsersClientResps) => {
this.resps = resps;
};
logoutMock = (resp: Promise<Response>) => {
this.logoutMockResp = resp;
};
isAuthedMock = (resp: Promise<Response>) => {
this.isAuthedMockResp = resp;
};
setPwdMock = (resp: Promise<Response>) => {
this.setPwdMockResp = resp;
};
forceSetPwdMock = (resp: Promise<Response>) => {
this.forceSetPwdMockResp = resp;
};
addUserMock = (resp: Promise<Response>) => {
this.addUserMockResp = resp;
};
delUserMock = (resp: Promise<Response>) => {
this.delUserMockResp = resp;
};
listUsersMock = (resp: Promise<Response>) => {
this.listUsersMockResp = resp;
};
addRoleMock = (resp: Promise<Response>) => {
this.addRoleMockResp = resp;
};
delRoleMock = (resp: Promise<Response>) => {
this.delRoleMockResp = resp;
};
listRolesMock = (resp: Promise<Response>) => {
this.listRolesMockResp = resp;
};
selfMock = (resp: Promise<Response>) => {
this.selfMockResp = resp;
};
getCaptchaIDMock = (resp: Promise<Response>) => {
this.getCaptchaIDMockResp = resp;
wrapPromise = (resp: any): Promise<any> => {
return new Promise<any>((resolve) => {
resolve(resp);
});
};
login = (user: string, pwd: string): Promise<Response> => {
return this.loginMockResp;
return this.wrapPromise(this.resps.loginMockResp);
};
logout = (): Promise<Response> => {
return this.logoutMockResp;
return this.wrapPromise(this.resps.logoutMockResp);
};
isAuthed = (): Promise<Response> => {
return this.isAuthedMockResp;
return this.wrapPromise(this.resps.isAuthedMockResp);
};
setPwd = (oldPwd: string, newPwd: string): Promise<Response> => {
return this.setPwdMockResp;
return this.wrapPromise(this.resps.setPwdMockResp);
};
forceSetPwd = (userID: string, newPwd: string): Promise<Response> => {
return this.forceSetPwdMockResp;
return this.wrapPromise(this.resps.forceSetPwdMockResp);
};
addUser = (name: string, pwd: string, role: string): Promise<Response> => {
return this.addUserMockResp;
return this.wrapPromise(this.resps.addUserMockResp);
};
delUser = (userID: string): Promise<Response> => {
return this.delUserMockResp;
return this.wrapPromise(this.resps.delUserMockResp);
};
listUsers = (): Promise<Response> => {
return this.listUsersMockResp;
return this.wrapPromise(this.resps.listUsersMockResp);
};
addRole = (role: string): Promise<Response> => {
return this.addRoleMockResp;
return this.wrapPromise(this.resps.addRoleMockResp);
};
delRole = (role: string): Promise<Response> => {
return this.delRoleMockResp;
return this.wrapPromise(this.resps.delRoleMockResp);
};
listRoles = (): Promise<Response> => {
return this.listRolesMockResp;
return this.wrapPromise(this.resps.listRolesMockResp);
};
self = (): Promise<Response> => {
return this.selfMockResp;
return this.wrapPromise(this.resps.selfMockResp);
};
getCaptchaID = (): Promise<Response> => {
return this.getCaptchaIDMockResp;
return this.wrapPromise(this.resps.getCaptchaIDMockResp);
};
}

View file

@ -1,283 +1,121 @@
import * as React from "react";
import { List, Map } from "immutable";
import { mock, instance, anyString, anything, when, verify } from "ts-mockito";
import { mock, instance, verify, when, anything } from "ts-mockito";
import { List } from "immutable";
import { ICoreState, newWithWorker, initState } from "../core_state";
import {
makePromise,
makeNumberResponse,
mockUpdate,
addMockUpdate,
mockFileList,
} from "../../test/helpers";
import { Browser } from "../browser";
// import { Updater, setUpdater } from "../browser.updater";
import { ICoreState, newWithWorker } from "../core_state";
import { updater } from "../state_updater";
import { MockWorker } from "../../worker/interface";
import { MockUsersClient, resps as usersResps } from "../../client/users_mock";
import { MockFilesClient, resps as filesResps } from "../../client/files_mock";
import { mockFileList } from "../../test/helpers";
import { updater, Updater, setUpdater } from "../state_updater";
import { MockUsersClient } from "../../client/users_mock";
import { UsersClient } from "../../client/users";
import { FilesClient } from "../../client/files";
import { FilesClient as MockFilesClient } from "../../client/files_mock";
import { MetadataResp, UploadInfo } from "../../client";
import { MockWorker, UploadEntry } from "../../worker/interface";
import { UploadMgr, setUploadMgr } from "../../worker/upload_mgr";
describe("Browser", () => {
const initBrowser = (): any => {
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
// describe("Browser", () => {
// const mockWorkerClass = mock(MockWorker);
// const mockWorker = instance(mockWorkerClass);
const coreState = newWithWorker(mockWorker);
const usersCl = new MockUsersClient("");
const filesCl = new MockFilesClient("");
// test("Updater: addUploads: add each files to UploadMgr", async () => {
// let coreState = initState();
// const UploadMgrClass = mock(UploadMgr);
// const uploadMgr = instance(UploadMgrClass);
// setUploadMgr(uploadMgr);
updater().init(coreState);
updater().setClients(usersCl, filesCl);
// const filePaths = ["./file1", "./file2"];
// const fileList = mockFileList(filePaths);
// // const updater = new Updater();
// updater().setUploadings = (infos: Map<string, UploadEntry>) => {};
// updater().init(coreState);
const browser = new Browser({
dirPath: coreState.browser.dirPath,
isSharing: coreState.browser.isSharing,
items: coreState.browser.items,
uploadings: coreState.browser.uploadings,
sharings: coreState.browser.sharings,
uploadFiles: coreState.browser.uploadFiles,
uploadValue: coreState.browser.uploadValue,
isVertical: coreState.browser.isVertical,
update: (updater: (prevState: ICoreState) => ICoreState) => {},
});
// updater().addUploads(fileList);
return {
browser,
usersCl,
filesCl,
};
};
// // it seems that new File will do some file path escaping, so just check call time here
// verify(UploadMgrClass.add(anything(), anything())).times(filePaths.length);
// // filePaths.forEach((filePath, i) => {
// // verify(UploadMgrClass.add(anything(), filePath)).once();
// // });
// });
test("addUploads", async () => {
const { browser, usersCl, filesCl } = initBrowser();
// test("Updater: deleteUploads: call UploadMgr and api to delete", async () => {
// let coreState = initState();
// const UploadMgrClass = mock(UploadMgr);
// const uploadMgr = instance(UploadMgrClass);
// setUploadMgr(uploadMgr);
const newSharings = [
"mock_sharingfolder1",
"mock_sharingfolder2",
"newSharing",
];
// // const updater = new Updater();
// const filesClientClass = mock(FilesClient);
// when(filesClientClass.deleteUploading(anyString())).thenResolve({
// status: 200,
// statusText: "",
// data: "",
// });
// const filesClient = instance(filesClientClass);
// const usersClientClass = mock(UsersClient);
// const usersClient = instance(usersClientClass);
// updater().init(coreState);
// updater().setClients(usersClient, filesClient);
filesCl.setMock({
...filesResps,
listSharingsMockResp: {
status: 200,
statusText: "",
data: {
sharingDirs: newSharings,
},
},
});
// const filePath = "./path/file";
// updater().deleteUpload(filePath);
await browser.addSharing();
// verify(filesClientClass.deleteUploading(filePath)).once();
// verify(UploadMgrClass.delete(filePath)).once();
// });
// TODO: check addSharing's input
expect(updater().props.browser.isSharing).toEqual(true);
expect(updater().props.browser.sharings).toEqual(List(newSharings));
});
// test("Updater: delete", async () => {
// const tests = [
// {
// dirPath: "path/path2",
// items: [
// {
// name: "file",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// selected: {
// file: true,
// },
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// },
// },
// filePath: "path/file",
// },
// ];
test("deleteUploads", async () => {
const { browser, usersCl, filesCl } = initBrowser();
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
// // const updater = new Updater();
// updater().setClients(usersClient, filesClient);
// filesClient.listMock(makePromise(tc.listResp));
// filesClient.deleteMock(makeNumberResponse(200));
// const coreState = newWithWorker(mockWorker);
// updater().init(coreState);
const newSharings = ["mock_sharingfolder1", "mock_sharingfolder2"];
// await updater().delete(
// List<string>(tc.dirPath.split("/")),
// List<MetadataResp>(tc.items),
// Map(tc.selected)
// );
filesCl.setMock({
...filesResps,
listSharingsMockResp: {
status: 200,
statusText: "",
data: {
sharingDirs: newSharings,
},
},
});
// const newState = updater().updateBrowser(coreState);
await browser.deleteSharing();
// // TODO: check inputs of delete
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
// TODO: check delSharing's input
expect(updater().props.browser.isSharing).toEqual(false);
expect(updater().props.browser.sharings).toEqual(List(newSharings));
});
// test("Updater: setItems", async () => {
// const tests = [
// {
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "file",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// },
// },
// filePath: "path/file",
// },
// ];
test("chdir", async () => {
const { browser, usersCl, filesCl } = initBrowser();
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
const newSharings = ["mock_sharingfolder1", "mock_sharingfolder2"];
const newCwd = List(["newPos", "subFolder"]);
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
filesCl.setMock({
...filesResps,
listSharingsMockResp: {
status: 200,
statusText: "",
data: {
sharingDirs: newSharings,
},
},
});
// filesClient.listMock(makePromise(tc.listResp));
// updater().setClients(usersClient, filesClient);
// const coreState = newWithWorker(mockWorker);
// updater().init(coreState);
await browser.chdir(newCwd);
// await updater().setItems(List<string>(tc.filePath.split("/")));
// const newState = updater().updateBrowser(coreState);
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
// test("Updater: moveHere", async () => {
// const tests = [
// {
// dirPath1: "path/path1",
// dirPath2: "path/path2",
// selected: {
// file1: true,
// file2: true,
// },
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "file1",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "file2",
// size: 2,
// modTime: "1-1",
// isDir: false,
// },
// ],
// },
// },
// },
// ];
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
// filesClient.listMock(makePromise(tc.listResp));
// filesClient.moveMock(makeNumberResponse(200));
// updater().setClients(usersClient, filesClient);
// const coreState = newWithWorker(mockWorker);
// updater().init(coreState);
// await updater().moveHere(tc.dirPath1, tc.dirPath2, Map(tc.selected));
// const newState = updater().updateBrowser(coreState);
// // TODO: check inputs of move
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
// test("Browser: deleteUpload: tell uploader to deleteUpload and refreshUploadings", async () => {
// let coreState = initState();
// addMockUpdate(coreState.panel.browser);
// const component = new Browser(coreState.panel.browser);
// const UpdaterClass = mock(Updater);
// const mockUpdater = instance(UpdaterClass);
// setUpdater(mockUpdater);
// when(UpdaterClass.setItems(anything())).thenResolve();
// when(UpdaterClass.deleteUpload(anyString())).thenResolve(true);
// when(UpdaterClass.refreshUploadings()).thenResolve(true);
// const filePath = "filePath";
// await component.deleteUpload(filePath);
// verify(UpdaterClass.deleteUpload(filePath)).once();
// verify(UpdaterClass.refreshUploadings()).once();
// });
// test("Browser: stopUploading: tell updater to stopUploading", async () => {
// let coreState = initState();
// addMockUpdate(coreState.panel.browser);
// const component = new Browser(coreState.panel.browser);
// const UpdaterClass = mock(Updater);
// const mockUpdater = instance(UpdaterClass);
// setUpdater(mockUpdater);
// when(UpdaterClass.stopUploading(anyString())).thenReturn();
// const filePath = "filePath";
// component.stopUploading(filePath);
// verify(UpdaterClass.stopUploading(filePath)).once();
// });
// });
expect(updater().props.browser.dirPath).toEqual(newCwd);
expect(updater().props.browser.isSharing).toEqual(true);
expect(updater().props.browser.sharings).toEqual(
List(filesResps.listSharingsMockResp.data.sharingDirs)
);
expect(updater().props.browser.items).toEqual(
List(filesResps.listHomeMockResp.data.metadatas)
);
});
});

View file

@ -1,64 +1,62 @@
import { List, Set, Map } from "immutable";
import { mock, instance } from "ts-mockito";
import { newWithWorker } from "../core_state";
import { User } from "../../client";
import { AuthPane } from "../pane_login";
import { ICoreState, newWithWorker } from "../core_state";
import { updater } from "../state_updater";
import { MockUsersClient } from "../../client/users_mock";
import { FilesClient } from "../../client/files_mock";
import { Response } from "../../client";
import { MockWorker } from "../../worker/interface";
import { MockUsersClient, resps as usersResps } from "../../client/users_mock";
import { MockFilesClient, resps as filesResps } from "../../client/files_mock";
describe("AuthPane", () => {
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
describe("Login", () => {
test("login", async () => {
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
const makePromise = (ret: any): Promise<any> => {
return new Promise<any>((resolve) => {
resolve(ret);
const coreState = newWithWorker(mockWorker);
const pane = new AuthPane({
authed: coreState.login.authed,
captchaID: coreState.login.captchaID,
update: (updater: (prevState: ICoreState) => ICoreState) => {},
});
};
const makeNumberResponse = (status: number): Promise<Response> => {
return makePromise({
status: status,
statusText: "",
data: {},
const usersCl = new MockUsersClient("");
const filesCl = new MockFilesClient("");
updater().init(coreState);
updater().setClients(usersCl, filesCl);
await pane.login();
// TODO: state is not checked
// login
expect(updater().props.login).toEqual({
authed: true,
captchaID: "",
});
};
test("Updater-initIsAuthed", async () => {
const tests = [
{
loginStatus: 200,
logoutStatus: 200,
isAuthedStatus: 200,
setPwdStatus: 200,
isAuthed: true,
},
{
loginStatus: 200,
logoutStatus: 200,
isAuthedStatus: 500,
setPwdStatus: 200,
isAuthed: false,
},
];
// panes
expect(updater().props.panes).toEqual({
userRole: "admin",
displaying: "",
paneNames: Set(["settings", "login", "admin"]),
});
const usersClient = new MockUsersClient("");
const filesClient = new FilesClient("");
for (let i = 0; i < tests.length; i++) {
const tc = tests[i];
usersClient.loginMock(makeNumberResponse(tc.loginStatus));
usersClient.logoutMock(makeNumberResponse(tc.logoutStatus));
usersClient.isAuthedMock(makeNumberResponse(tc.isAuthedStatus));
usersClient.setPwdMock(makeNumberResponse(tc.setPwdStatus));
const coreState = newWithWorker(mockWorker);
updater().setClients(usersClient, filesClient);
updater().init(coreState);
await updater().initIsAuthed();
const newState = updater().updateLogin(coreState);
expect(newState.login.authed).toEqual(tc.isAuthed);
}
// admin
let usersMap = Map({});
usersResps.listUsersMockResp.data.users.forEach((user: User) => {
usersMap = usersMap.set(user.name, user);
});
let roles = Set<string>();
Object.keys(usersResps.listRolesMockResp.data.roles).forEach(
(role: string) => {
roles = roles.add(role);
}
);
expect(updater().props.admin).toEqual({
users: usersMap,
roles: roles,
});
});
});

View file

@ -1,55 +1,31 @@
import { Set } from "immutable";
import { mock, instance } from "ts-mockito";
import { ICoreState, initState } from "../core_state";
import { Panes } from "../panes";
import { mockUpdate } from "../../test/helpers";
import { ICoreState, newWithWorker } from "../core_state";
import { updater } from "../state_updater";
import { MockWorker } from "../../worker/interface";
describe("Panes", () => {
test("Panes: closePane", async () => {
interface TestCase {
preState: ICoreState;
postState: ICoreState;
}
test("closePane", async () => {
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
const tcs: any = [
{
preState: {
panes: {
displaying: "settings",
paneNames: Set<string>(["settings", "login"]),
update: mockUpdate,
},
},
postState: {
panes: {
displaying: "",
paneNames: Set<string>(["settings", "login"]),
update: mockUpdate,
},
},
},
];
const coreState = newWithWorker(mockWorker);
const panes = new Panes({
panes: coreState.panes,
admin: coreState.admin,
login: coreState.login,
update: (updater: (prevState: ICoreState) => ICoreState) => {},
});
const setState = (patch: any, state: ICoreState): ICoreState => {
state.panes = patch.panes;
return state;
};
updater().init(coreState);
tcs.forEach((tc: TestCase) => {
const preState = setState(tc.preState, initState());
const postState = setState(tc.postState, initState());
panes.closePane();
const component = new Panes({
panes: preState.panes,
admin: preState.admin,
login: preState.login,
update: mockUpdate,
});
updater().init(preState);
component.closePane();
expect(updater().props).toEqual(postState);
expect(updater().props.panes).toEqual({
userRole: coreState.panes.userRole,
displaying: "",
paneNames: coreState.panes.paneNames,
});
});
});

View file

@ -0,0 +1,73 @@
import { List, Set, Map } from "immutable";
import { mock, instance } from "ts-mockito";
import { StateMgr } from "../state_mgr";
import { User } from "../../client";
import { MockFilesClient, resps as filesResps } from "../../client/files_mock";
import { MockUsersClient, resps as usersResps } from "../../client/users_mock";
import { ICoreState, newWithWorker } from "../core_state";
import { MockWorker } from "../../worker/interface";
describe("State Manager", () => {
test("initUpdater", async () => {
const usersCl = new MockUsersClient("");
const filesCl = new MockFilesClient("");
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
const mgr = new StateMgr({}); // it will call initUpdater
mgr.setUsersClient(usersCl);
mgr.setFilesClient(filesCl);
// TODO: depress warning
mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => {
// no op
};
const coreState = newWithWorker(mockWorker);
await mgr.initUpdater(coreState);
// browser
expect(coreState.browser.dirPath.join("/")).toEqual("mock_home/files");
expect(coreState.browser.isSharing).toEqual(true);
expect(coreState.browser.sharings).toEqual(
List(filesResps.listSharingsMockResp.data.sharingDirs)
);
expect(coreState.browser.uploadings).toEqual(
List(filesResps.listUploadingsMockResp.data.uploadInfos)
);
expect(coreState.browser.items).toEqual(
List(filesResps.listHomeMockResp.data.metadatas)
);
// panes
expect(coreState.panes).toEqual({
userRole: "admin",
displaying: "browser",
paneNames: Set(["settings", "login", "admin"]),
});
// login
expect(coreState.login).toEqual({
authed: false,
captchaID: "mockCaptchaID",
});
// admin
let usersMap = Map({});
usersResps.listUsersMockResp.data.users.forEach((user: User) => {
usersMap = usersMap.set(user.name, user);
});
let roles = Set<string>();
Object.keys(usersResps.listRolesMockResp.data.roles).forEach(
(role: string) => {
roles = roles.add(role);
}
);
expect(coreState.admin).toEqual({
users: usersMap,
roles: roles,
});
});
});

View file

@ -6,10 +6,7 @@ import FileSize from "filesize";
import { alertMsg, comfirmMsg } from "../common/env";
import { updater } from "./state_updater";
import { ICoreState } from "./core_state";
import {
MetadataResp,
UploadInfo,
} from "../client";
import { MetadataResp, UploadInfo } from "../client";
import { Up } from "../worker/upload_mgr";
import { UploadEntry } from "../worker/interface";
@ -181,12 +178,12 @@ export class Browser extends React.Component<Props, State, {}> {
this.chdir(this.props.dirPath.push(childDirName));
};
chdir = (dirPath: List<string>) => {
chdir = async (dirPath: List<string>) => {
if (dirPath === this.props.dirPath) {
return;
}
updater()
return updater()
.setItems(dirPath)
.then(() => {
return updater().listSharings();
@ -238,8 +235,8 @@ export class Browser extends React.Component<Props, State, {}> {
});
};
addSharing = () => {
updater()
addSharing = async () => {
return updater()
.addSharing()
.then((ok) => {
if (!ok) {
@ -254,8 +251,8 @@ export class Browser extends React.Component<Props, State, {}> {
});
};
deleteSharing = (dirPath: string) => {
updater()
deleteSharing = async (dirPath: string) => {
return updater()
.deleteSharing(dirPath)
.then((ok) => {
if (!ok) {
@ -270,8 +267,8 @@ export class Browser extends React.Component<Props, State, {}> {
});
};
listSharings = () => {
updater()
listSharings = async () => {
return updater()
.listSharings()
.then((ok) => {
if (ok) {

View file

@ -30,7 +30,7 @@ export function newWithWorker(worker: IWorker): ICoreState {
}
export function newState(): ICoreState {
const worker = Worker == null ? new FgWorker() : new BgWorker();
const worker = window.Worker == null ? new FgWorker() : new BgWorker();
initUploadMgr(worker);
return initState();

View file

@ -50,8 +50,8 @@ export class AuthPane extends React.Component<Props, State, {}> {
});
};
login = () => {
updater()
login = async () => {
return updater()
.login(
this.state.user,
this.state.pwd,
@ -72,6 +72,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
this.setState({ user: "", pwd: "" });
alert("Failed to login.");
}
})
.then(() => {
return updater().refreshUploadings();
@ -84,6 +85,23 @@ export class AuthPane extends React.Component<Props, State, {}> {
.then(() => {
return updater().listSharings();
})
.then(() => {
return updater().self();
})
.then(() => {
// TODO: should rely on props to get userRole
if (updater().props.panes.userRole === "admin") {
// TODO: remove hardcode
return updater().listRoles();
}
})
.then(() => {
// TODO: should rely on props to get userRole
if (updater().props.panes.userRole === "admin") {
// TODO: remove hardcode
return updater().listUsers();
}
})
.then((_: boolean) => {
this.update(updater().updateBrowser);
});

View file

@ -18,7 +18,6 @@ export class StateMgr extends React.Component<Props, State, {}> {
constructor(p: Props) {
super(p);
this.state = newState();
this.initUpdater(this.state);
}
setUsersClient = (client: IUsersClient) => {
@ -29,12 +28,16 @@ export class StateMgr extends React.Component<Props, State, {}> {
this.filesClient = client;
};
initUpdater = (state: ICoreState) => {
initUpdater = (state: ICoreState): Promise<void> => {
updater().init(state);
updater().setClients(new UsersClient(""), new FilesClient(""));
if (this.usersClient == null || this.filesClient == null) {
console.error("updater's clients are not inited");
return;
}
updater().setClients(this.usersClient, this.filesClient);
const params = new URLSearchParams(document.location.search.substring(1));
updater()
return updater()
.getCaptchaID()
.then((ok: boolean) => {
if (!ok) {
@ -42,10 +45,10 @@ export class StateMgr extends React.Component<Props, State, {}> {
} else {
this.update(updater().updateLogin);
}
});
updater()
.refreshUploadings()
})
.then(() => {
return updater().refreshUploadings();
})
.then(() => {
const dir = params.get("dir");
if (dir != null && dir !== "") {
@ -84,6 +87,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
})
.then(() => {
this.update(updater().updatePanes);
this.update(updater().updateAdmin);
});
};

View file

@ -1,152 +0,0 @@
import { FileUploader } from "../uploader";
import { FilesClient } from "../../client/files_mock";
import { makePromise } from "../../test/helpers";
describe("Uploader", () => {
const content = ["123456"];
const filePath = "mock/file";
const blob = new Blob(content);
const fileSize = blob.size;
const file = new File(content, filePath);
const makeCreateResp = (status: number): Promise<any> => {
return makePromise({
status: status,
statusText: "",
data: {
path: filePath,
fileSize: fileSize,
},
});
};
const makeStatusResp = (status: number, uploaded: number): Promise<any> => {
return makePromise({
status: status,
statusText: "",
data: {
path: filePath,
isDir: false,
fileSize: fileSize,
uploaded: uploaded,
},
});
};
interface statusResp {
status: number;
uploaded: number;
}
interface TestCase {
createResps: Array<number>;
uploadChunkResps: Array<any>;
uploadStatusResps: Array<any>;
result: boolean;
}
test("test start and upload method", async () => {
const testCases: Array<TestCase> = [
{
// fail to create file 4 times
createResps: [500, 500, 500, 500],
uploadChunkResps: [],
uploadStatusResps: [],
result: false,
},
{
// fail to get status
createResps: [200],
uploadChunkResps: [{ status: 500, uploaded: 0 }],
uploadStatusResps: [{ status: 600, uploaded: 0 }],
result: false,
},
{
// upload ok
createResps: [200],
uploadChunkResps: [
{ status: 200, uploaded: 0 },
{ status: 200, uploaded: 1 },
{ status: 200, uploaded: fileSize },
],
uploadStatusResps: [],
result: true,
},
{
// fail once
createResps: [200],
uploadChunkResps: [
{ status: 200, uploaded: 0 },
{ status: 500, uploaded: 1 },
{ status: 200, uploaded: fileSize },
],
uploadStatusResps: [{ status: 200, uploaded: 1 }],
result: true,
},
{
// fail twice
createResps: [500, 500],
uploadChunkResps: [],
uploadStatusResps: [],
result: false,
},
{
// fail twice
createResps: [500, 200],
uploadChunkResps: [
{ status: 200, uploaded: 0 },
{ status: 500, uploaded: 1 },
{ status: 500, uploaded: 1 },
{ status: 200, uploaded: fileSize },
],
uploadStatusResps: [
{ status: 500, uploaded: 1 },
{ status: 500, uploaded: 1 },
],
result: true,
},
{
// other errors
createResps: [500, 200],
uploadChunkResps: [
{ status: 601, uploaded: 0 },
{ status: 408, uploaded: fileSize },
{ status: 200, uploaded: 1 },
{ status: 200, uploaded: fileSize },
],
uploadStatusResps: [
{ status: 500, uploaded: 1 },
{ status: 500, uploaded: 1 },
],
result: true,
},
];
for (let i = 0; i < testCases.length; i++) {
const tc = testCases[i];
const mockCb = (
filePath: string,
uploaded: number,
done: boolean,
err: string
):void => {};
const uploader = new FileUploader(file, filePath, mockCb);
const mockClient = new FilesClient("");
const createResps = tc.createResps.map((resp) => makeCreateResp(resp));
mockClient.createMock(createResps);
const uploadChunkResps = tc.uploadChunkResps.map((resp) =>
makeStatusResp(resp.status, resp.uploaded)
);
mockClient.uploadChunkMock(uploadChunkResps);
const uploadStatusResps = tc.uploadStatusResps.map((resp) =>
makeStatusResp(resp.status, resp.uploaded)
);
mockClient.uploadStatusMock(uploadStatusResps);
uploader.setClient(mockClient);
const ret = await uploader.start();
expect(ret).toEqual(tc.result);
}
});
});

View file

@ -34,7 +34,7 @@ func IsReachedLimitErr(err error) bool {
}
type Quota struct {
SpaceLimit int64 `json:"spaceLimit,space"`
SpaceLimit int64 `json:"spaceLimit,string"`
UploadSpeedLimit int `json:"uploadSpeedLimit"`
DownloadSpeedLimit int `json:"downloadSpeedLimit"`
}