diff --git a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts index 80b66371..d2ebf627 100644 --- a/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts +++ b/tdrive/backend/node/src/core/platform/services/database/services/orm/connectors/postgres/postgres.ts @@ -165,7 +165,18 @@ export class PostgresConnector extends AbstractConnector { - logger.info("Drop database is not implemented for security reasons."); + const query = ` + DO $$ + DECLARE + tablename text; + BEGIN + FOR tablename IN (SELECT table_name FROM information_schema.tables WHERE table_schema = 'public') + LOOP + EXECUTE 'DELETE FROM "' || tablename || '" CASCADE'; + END LOOP; + END $$;`; + logger.debug(`service.database.orm.postgres.drop - Query: "${query}"`); + await this.client.query(query); return this; } diff --git a/tdrive/backend/node/src/services/documents/services/index.ts b/tdrive/backend/node/src/services/documents/services/index.ts index 3395b043..9a90cac4 100644 --- a/tdrive/backend/node/src/services/documents/services/index.ts +++ b/tdrive/backend/node/src/services/documents/services/index.ts @@ -1,10 +1,6 @@ import SearchRepository from "../../../core/platform/services/search/repository"; import { getLogger, logger, TdriveLogger } from "../../../core/platform/framework"; -import { - CrudException, - ExecutionContext, - ListResult, -} from "../../../core/platform/framework/api/crud-service"; +import { CrudException, ListResult } from "../../../core/platform/framework/api/crud-service"; import Repository, { comparisonType, inType, diff --git a/tdrive/backend/node/src/services/files/services/index.ts b/tdrive/backend/node/src/services/files/services/index.ts index 9766ab03..0d285e9f 100644 --- a/tdrive/backend/node/src/services/files/services/index.ts +++ b/tdrive/backend/node/src/services/files/services/index.ts @@ -311,7 +311,5 @@ export class FileServiceImpl { } function getFilePath(entity: File): string { - return `${gr.platformServices.storage.getHomeDir()}/files/${entity.company_id}/${ - entity.user_id || "anonymous" - }/${entity.id}`; + return `/files/${entity.company_id}/${entity.user_id || "anonymous"}/${entity.id}`; } diff --git a/tdrive/backend/node/src/services/user/services/users/service.ts b/tdrive/backend/node/src/services/user/services/users/service.ts index cd069c61..07f61999 100644 --- a/tdrive/backend/node/src/services/user/services/users/service.ts +++ b/tdrive/backend/node/src/services/user/services/users/service.ts @@ -33,10 +33,7 @@ import { getPublicUserRoom, getUserRoom } from "../../realtime"; import NodeCache from "node-cache"; import gr from "../../../global-resolver"; import { formatUser } from "../../../../utils/users"; -import { getDefaultDriveItem } from "../../../documents/utils"; -import { CompanyExecutionContext } from "../../../documents/types"; import { TYPE as DriveFileType, DriveFile } from "../../../documents/entities/drive-file"; -import config from "config"; export class UserServiceImpl { version: "1"; diff --git a/tdrive/backend/node/test/e2e/common/common_test_helpers.ts b/tdrive/backend/node/test/e2e/common/common_test_helpers.ts deleted file mode 100644 index 3d55090c..00000000 --- a/tdrive/backend/node/test/e2e/common/common_test_helpers.ts +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-ignore -import fs from "fs"; -import { ResourceUpdateResponse, Workspace } from "../../../src/utils/types"; -import { File } from "../../../src/services/files/entities/file"; -import { deserialize } from "class-transformer"; -import formAutoContent from "form-auto-content"; -import { TestPlatform, User } from "../setup"; -import { v1 as uuidv1 } from "uuid"; -import { TestDbService } from "../utils.prepare.db"; -import { DriveFile } from "../../../src/services/documents/entities/drive-file"; -import { FileVersion } from "../../../src/services/documents/entities/file-version"; -import { - AccessTokenMockClass, - DriveItemDetailsMockClass, - SearchResultMockClass, - UserQuotaMockClass -} from "./entities/mock_entities"; -import { logger } from "../../../src/core/platform/framework"; -import { expect } from "@jest/globals"; -import { publicAccessLevel } from "../../../src/services/documents/types"; -import { UserQuota } from "../../../src/services/user/web/types"; - -export default class TestHelpers { - - private static readonly DOC_URL = "/internal/services/documents/v1"; - - static readonly ALL_FILES = [ - "sample.png", - "sample.gif", - "sample.pdf", - "sample.doc", - "sample.zip", - "sample.mp4", - ] - - platform: TestPlatform; - dbService: TestDbService; - user: User; - anonymous: User; - workspace: Workspace; - jwt: string; - - private constructor( - platform: TestPlatform, - ) { - this.platform = platform - } - - private async init(newUser: boolean, options?: {}) { - this.dbService = await TestDbService.getInstance(this.platform, true); - if (newUser) { - this.workspace = this.platform.workspace; - const workspacePK = {id: this.workspace.workspace_id, company_id: this.workspace.company_id}; - this.user = await this.dbService.createUser([workspacePK], options, uuidv1()); - this.anonymous = await this.dbService.createUser([workspacePK], - { ...options, - identity_provider: "anonymous", - }, - uuidv1()); - } else { - this.user = this.platform.currentUser; - this.workspace = this.platform.workspace; - } - this.jwt = this.getJWTTokenForUser(this.user.id); - } - - public static async getInstance(platform: TestPlatform, newUser = false, options?: {}): Promise { - const helpers = new TestHelpers(platform); - await helpers.init(newUser, options) - return helpers; - } - - async uploadRandomFile() { - return await this.uploadFile(TestHelpers.ALL_FILES[Math.floor((Math.random()*TestHelpers.ALL_FILES.length))]) - } - - async uploadFile(filename: string) { - logger.info(`Upload ${filename} for the user: ${this.user.id}`); - const fullPath = `${__dirname}/assets/${filename}` - const url = "/internal/services/files/v1"; - const form = formAutoContent({file: fs.createReadStream(fullPath)}); - form.headers["authorization"] = `Bearer ${this.jwt}`; - - const filesUploadRaw = await this.platform.app.inject({ - method: "POST", - url: `${url}/companies/${this.platform.workspace.company_id}/files?thumbnail_sync=0`, - ...form, - }); - - const filesUpload: ResourceUpdateResponse = deserialize>( - ResourceUpdateResponse, - filesUploadRaw.body, - ); - return filesUpload.resource; - } - - private getJWTTokenForUser(userId: string): string { - const payload = { - sub: userId, - role: "", - } - return this.platform.authService.sign(payload); - } - - async uploadFileAndCreateDocument( - filename: string, - parent_id = "root" - ) { - return this.uploadFile(filename).then(f => this.createDocumentFromFile(f, parent_id)); - }; - - async uploadRandomFileAndCreateDocument(parent_id = "root") { - return this.uploadRandomFile().then(f => this.createDocumentFromFile(f, parent_id)); - }; - - async uploadAllFilesAndCreateDocuments(parent_id = "root") { - return await Promise.all(TestHelpers.ALL_FILES.map(f => this.uploadFileAndCreateDocument(f, parent_id))) - }; - - async uploadAllFilesOneByOne(parent_id = "root") { - const files: Array = []; - for (const idx in TestHelpers.ALL_FILES) { - const f = await this.uploadFile(TestHelpers.ALL_FILES[idx]); - const doc = await this.createDocumentFromFile(f, parent_id); - files.push(doc); - } - return files; - }; - - async createDirectory(parent = "root") { - const directory = await this.createDocument({ - company_id: this.platform.workspace.company_id, - name: "Test Folder Name", - parent_id: parent, - is_directory: true, - }, {}); - expect(directory).toBeDefined(); - expect(directory).not.toBeNull(); - expect(directory.id).toBeDefined() - expect(directory.id).not.toBeNull(); - return directory; - } - - private async createDocument( - item: Partial, - version: Partial - ) { - - const response = await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/item`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - payload: { - item, - version, - }, - }); - return deserialize(DriveFile, response.body); - }; - - async shareWithPublicLink(doc: Partial, accessLevel: publicAccessLevel) { - return await this.updateDocument(doc.id, { - ...doc, - access_info: { - ...doc.access_info, - public: { - ...doc.access_info.public!, - level: accessLevel, - } - } - }); - } - - async getPublicLinkAccessToken(doc: Partial) { - const accessRes = await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${doc.company_id}/anonymous/token`, - headers: {}, - payload: { - company_id: doc.company_id, - document_id: doc.id, - token: doc.access_info.public?.token, - }, - }); - const { access_token } = deserialize( - AccessTokenMockClass, - accessRes.body, - ); - expect(access_token).toBeDefined(); - - return access_token; - } - - async createRandomDocument( - parent_id = "root", - ) { - const file = await this.uploadRandomFile(); - - const doc = await this.createDocumentFromFile(file, parent_id); - - expect(doc).toBeDefined(); - expect(doc).not.toBeNull(); - expect(doc.parent_id).toEqual(parent_id) - - return doc; - }; - - async createDocumentFromFilename( - file_name: "sample.png", - parent_id = "root", - ) { - const file = await this.uploadFile(file_name); - - const doc = await this.createDocumentFromFile(file, parent_id); - - expect(doc).toBeDefined(); - expect(doc).not.toBeNull(); - expect(doc.parent_id).toEqual(parent_id) - - return doc; - }; - - async createDocumentFromFile( - file: File, - parent_id = "root", - ) { - const item = { - name: file.metadata.name, - parent_id: parent_id, - company_id: file.company_id, - }; - - const version = { - file_metadata: { - name: file.metadata.name, - size: file.upload_data?.size, - thumbnails: [], - external_id: file.id - } - } - - return await this.createDocument(item, version); - }; - - async updateDocument( - id: string | "root" | "trash" | "shared_with_me", - item: Partial - ) { - return await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - payload: item, - }); - }; - - async searchDocument ( - payload: Record - ){ - const response = await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/search`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - payload, - }); - - return deserialize( - SearchResultMockClass, - response.body) - }; - - async browseDocuments ( - id: string, - payload: Record - ){ - const response = await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/browse/${id}`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - payload, - }); - - return deserialize( - DriveItemDetailsMockClass, - response.body) - }; - - async getDocument(id: string | "root" | "trash" | "shared_with_me") { - return await this.platform.app.inject({ - method: "GET", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - }); - }; - - async getFolder(id: string | "root" | "trash" | "shared_with_me") { - return await this.platform.app.inject({ - method: "GET", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/item/download/zip?items=${id}`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - }); - }; - - - async getDocumentOKCheck(id: string | "root" | "trash" | "shared_with_me") { - const response = await this.getDocument(id); - expect(response.statusCode).toBe(200); - const doc = deserialize(DriveItemDetailsMockClass, response.body); - expect(doc.item?.id).toBe(id); - }; - - async getFolderOKCheck(id: string | "root" | "trash" | "shared_with_me") { - const response = await this.getFolder(id); - expect(response.statusCode).toBe(200); - const doc = deserialize(DriveItemDetailsMockClass, response.body); - expect(doc.item?.id).toBe(id); - }; - - async sharedWithMeDocuments ( - payload: Record - ){ - const response = await this.platform.app.inject({ - method: "POST", - url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/shared-with-me`, - headers: { - authorization: `Bearer ${this.jwt}`, - }, - payload, - }); - - return deserialize( - SearchResultMockClass, - response.body) - }; - - async quota() { - const url = "/internal/services/users/v1/users"; - - const response = await this.platform.app.inject({ - method: "GET", - headers: { "authorization": `Bearer ${this.jwt}` }, - url: `${url}/${this.user.id}/quota?companyId=${this.platform.workspace.company_id}`, - }) - - return deserialize(UserQuotaMockClass, response.body) - } -} - diff --git a/tdrive/backend/node/test/e2e/common/entities/mock_entities.ts b/tdrive/backend/node/test/e2e/common/entities/mock_entities.ts index bd4eb48e..8105cd6c 100644 --- a/tdrive/backend/node/test/e2e/common/entities/mock_entities.ts +++ b/tdrive/backend/node/test/e2e/common/entities/mock_entities.ts @@ -21,7 +21,7 @@ export class DriveFileMockClass { id: string; name: string; size: number; - added: string; + added: number; parent_id: string; extension: string; description: string; diff --git a/tdrive/backend/node/test/e2e/common/user-api.ts b/tdrive/backend/node/test/e2e/common/user-api.ts new file mode 100644 index 00000000..758cf1e5 --- /dev/null +++ b/tdrive/backend/node/test/e2e/common/user-api.ts @@ -0,0 +1,370 @@ +// @ts-ignore +import fs from "fs"; +import { ResourceUpdateResponse, Workspace } from "../../../src/utils/types"; +import { File } from "../../../src/services/files/entities/file"; +import { deserialize } from "class-transformer"; +import formAutoContent from "form-auto-content"; +import { TestPlatform, User } from "../setup"; +import { v1 as uuidv1 } from "uuid"; +import { TestDbService } from "../utils.prepare.db"; +import { DriveFile } from "../../../src/services/documents/entities/drive-file"; +import { FileVersion } from "../../../src/services/documents/entities/file-version"; +import { + AccessTokenMockClass, DriveFileMockClass, + DriveItemDetailsMockClass, + SearchResultMockClass, + UserQuotaMockClass +} from "./entities/mock_entities"; +import { logger } from "../../../src/core/platform/framework"; +import { expect } from "@jest/globals"; +import { publicAccessLevel } from "../../../src/services/documents/types"; +import { UserQuota } from "../../../src/services/user/web/types"; +import { Api } from "../utils.api"; + +export default class UserApi { + + private static readonly DOC_URL = "/internal/services/documents/v1"; + + static readonly ALL_FILES = [ + "sample.png", + "sample.gif", + "sample.pdf", + "sample.doc", + "sample.zip", + "sample.mp4" + ]; + + platform: TestPlatform; + dbService: TestDbService; + + user: User; + anonymous: User; + workspace: Workspace; + jwt: string; + api: Api; + + private constructor( + platform: TestPlatform + ) { + this.platform = platform; + } + + private async init(newUser: boolean, options?: {}) { + this.dbService = await TestDbService.getInstance(this.platform, true); + if (newUser) { + this.workspace = this.platform.workspace; + const workspacePK = { id: this.workspace.workspace_id, company_id: this.workspace.company_id }; + this.user = await this.dbService.createUser([workspacePK], options, uuidv1()); + this.anonymous = await this.dbService.createUser([workspacePK], + { + ...options, + identity_provider: "anonymous" + }, + uuidv1()); + } else { + this.user = this.platform.currentUser; + this.workspace = this.platform.workspace; + } + this.api = new Api(this.platform, this.user); + this.jwt = this.getJWTTokenForUser(this.user.id); + } + + public static async getInstance(platform: TestPlatform, newUser = false, options?: {}): Promise { + const helpers = new UserApi(platform); + await helpers.init(newUser, options); + return helpers; + } + + async uploadRandomFile() { + return await this.uploadFile(UserApi.ALL_FILES[Math.floor((Math.random() * UserApi.ALL_FILES.length))]); + } + + async uploadFile(filename: string) { + logger.info(`Upload ${filename} for the user: ${this.user.id}`); + const fullPath = `${__dirname}/assets/${filename}`; + const url = "/internal/services/files/v1"; + const form = formAutoContent({ file: fs.createReadStream(fullPath) }); + form.headers["authorization"] = `Bearer ${this.jwt}`; + + const filesUploadRaw = await this.platform.app.inject({ + method: "POST", + url: `${url}/companies/${this.platform.workspace.company_id}/files?thumbnail_sync=0`, + ...form + }); + + const filesUpload: ResourceUpdateResponse = deserialize>( + ResourceUpdateResponse, + filesUploadRaw.body + ); + return filesUpload.resource; + } + + private getJWTTokenForUser(userId: string): string { + const payload = { + sub: userId, + role: "" + }; + return this.platform.authService.sign(payload); + } + + async uploadFileAndCreateDocument( + filename: string, + parent_id = "root" + ) { + return this.uploadFile(filename).then(f => this.createDocumentFromFile(f, parent_id)); + }; + + async uploadRandomFileAndCreateDocument(parent_id = "root") { + return this.uploadRandomFile().then(f => this.createDocumentFromFile(f, parent_id)); + }; + + async uploadAllFilesAndCreateDocuments(parent_id = "root") { + return await Promise.all(UserApi.ALL_FILES.map(f => this.uploadFileAndCreateDocument(f, parent_id))); + }; + + async uploadAllFilesOneByOne(parent_id = "root") { + const files: Array = []; + for (const idx in UserApi.ALL_FILES) { + const f = await this.uploadFile(UserApi.ALL_FILES[idx]); + const doc = await this.createDocumentFromFile(f, parent_id); + files.push(doc); + } + return files; + }; + + async createDirectory(parent = "root") { + const directory = await this.createDocument({ + company_id: this.platform.workspace.company_id, + name: "Test Folder Name", + parent_id: parent, + is_directory: true + }, {}); + expect(directory).toBeDefined(); + expect(directory).not.toBeNull(); + expect(directory.id).toBeDefined(); + expect(directory.id).not.toBeNull(); + return directory; + } + + async createDocument( + item: Partial, + version: Partial + ) { + const response = await this.api.post(`${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item`, + { + item, + version + }, { + authorization: `Bearer ${this.jwt}` + }); + return deserialize(DriveFile, response.body); + }; + + async createDefaultDocument(): Promise { + const scope: "personal" | "shared" = "shared"; + const item = { + name: "new test file", + parent_id: "root", + company_id: this.platform.workspace.company_id, + scope, + }; + + return await this.createDocument(item, {}); + }; + + async shareWithPublicLink(doc: Partial, accessLevel: publicAccessLevel) { + return await this.updateDocument(doc.id, { + ...doc, + access_info: { + ...doc.access_info, + public: { + ...doc.access_info.public!, + level: accessLevel + } + } + }); + } + + async getPublicLinkAccessToken(doc: Partial) { + const accessRes = await this.platform.app.inject({ + method: "POST", + url: `${UserApi.DOC_URL}/companies/${doc.company_id}/anonymous/token`, + headers: {}, + payload: { + company_id: doc.company_id, + document_id: doc.id, + token: doc.access_info.public?.token + } + }); + const { access_token } = deserialize( + AccessTokenMockClass, + accessRes.body + ); + expect(access_token).toBeDefined(); + + return access_token; + } + + async createRandomDocument( + parent_id = "root" + ) { + const file = await this.uploadRandomFile(); + + const doc = await this.createDocumentFromFile(file, parent_id); + + expect(doc).toBeDefined(); + expect(doc).not.toBeNull(); + expect(doc.parent_id).toEqual(parent_id); + + return doc; + }; + + async createDocumentFromFilename( + file_name: "sample.png", + parent_id = "root" + ) { + const file = await this.uploadFile(file_name); + + const doc = await this.createDocumentFromFile(file, parent_id); + + expect(doc).toBeDefined(); + expect(doc).not.toBeNull(); + expect(doc.parent_id).toEqual(parent_id); + + return doc; + }; + + async createDocumentFromFile( + file: File, + parent_id = "root" + ) { + const item = { + name: file.metadata.name, + parent_id: parent_id, + company_id: file.company_id + }; + + const version = { + file_metadata: { + name: file.metadata.name, + size: file.upload_data?.size, + thumbnails: [], + external_id: file.id + } + }; + + return await this.createDocument(item, version); + }; + + async updateDocument( + id: string | "root" | "trash" | "shared_with_me", + item: Partial + ) { + return await this.api.post( + `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`, + item, + { + authorization: `Bearer ${this.jwt}` + }); + }; + + async searchDocument( + payload: Record + ) { + const response = await this.platform.app.inject({ + method: "POST", + url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/search`, + headers: { + authorization: `Bearer ${this.jwt}` + }, + payload + }); + + return deserialize( + SearchResultMockClass, + response.body); + }; + + async browseDocuments( + id: string, + payload: Record + ) { + const response = await this.platform.app.inject({ + method: "POST", + url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/browse/${id}`, + headers: { + authorization: `Bearer ${this.jwt}` + }, + payload + }); + + return deserialize( + DriveItemDetailsMockClass, + response.body); + }; + + async getDocument(id: string | "root" | "trash" | "shared_with_me") { + return await this.platform.app.inject({ + method: "GET", + url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`, + headers: { + authorization: `Bearer ${this.jwt}` + } + }); + }; + + async getFolder(id: string | "root" | "trash" | "shared_with_me") { + return await this.platform.app.inject({ + method: "GET", + url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/download/zip?items=${id}`, + headers: { + authorization: `Bearer ${this.jwt}` + } + }); + }; + + + async getDocumentOKCheck(id: string | "root" | "trash" | "shared_with_me") { + const response = await this.getDocument(id); + expect(response.statusCode).toBe(200); + const doc = deserialize(DriveItemDetailsMockClass, response.body); + expect(doc.item?.id).toBe(id); + }; + + async getFolderOKCheck(id: string | "root" | "trash" | "shared_with_me") { + const response = await this.getFolder(id); + expect(response.statusCode).toBe(200); + const doc = deserialize(DriveItemDetailsMockClass, response.body); + expect(doc.item?.id).toBe(id); + }; + + async sharedWithMeDocuments( + payload: Record + ) { + const response = await this.platform.app.inject({ + method: "POST", + url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/shared-with-me`, + headers: { + authorization: `Bearer ${this.jwt}` + }, + payload + }); + + return deserialize( + SearchResultMockClass, + response.body); + }; + + async quota() { + const url = "/internal/services/users/v1/users"; + + const response = await this.platform.app.inject({ + method: "GET", + headers: { "authorization": `Bearer ${this.jwt}` }, + url: `${url}/${this.user.id}/quota?companyId=${this.platform.workspace.company_id}` + }); + + return deserialize(UserQuotaMockClass, response.body); + } +} + diff --git a/tdrive/backend/node/test/e2e/documents/documents-browser.spec.ts b/tdrive/backend/node/test/e2e/documents/documents-browser.spec.ts index c8cb5aff..6beaed30 100644 --- a/tdrive/backend/node/test/e2e/documents/documents-browser.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/documents-browser.spec.ts @@ -1,11 +1,11 @@ import { describe, beforeEach, afterEach, it, expect, afterAll } from "@jest/globals"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; describe("The Documents Browser Window and API", () => { let platform: TestPlatform; - let currentUser: TestHelpers; + let currentUser: UserApi; let dbService: TestDbService; beforeEach(async () => { @@ -26,7 +26,7 @@ describe("The Documents Browser Window and API", () => { "documents", ], }); - currentUser = await TestHelpers.getInstance(platform); + currentUser = await UserApi.getInstance(platform); dbService = await TestDbService.getInstance(platform, true); }); @@ -43,25 +43,25 @@ describe("The Documents Browser Window and API", () => { expect(result).toBeDefined(); expect(result.entries()).toBeDefined(); - expect(Array.from(result.entries())).toHaveLength(TestHelpers.ALL_FILES.length); + expect(Array.from(result.entries())).toHaveLength(UserApi.ALL_FILES.length); const docs = await currentUser.browseDocuments(myDriveId, {}); expect(docs).toBeDefined(); expect(docs.children).toBeDefined(); - expect(docs.children.length).toEqual(TestHelpers.ALL_FILES.length) + expect(docs.children.length).toEqual(UserApi.ALL_FILES.length) }); it("Should not be visible for other users", async () => { const myDriveId = "user_" + currentUser.user.id; - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); + const anotherUser = await UserApi.getInstance(platform, true, {companyRole: "admin"}); await currentUser.uploadAllFilesOneByOne(myDriveId); await new Promise(r => setTimeout(r, 5000)); const docs = await currentUser.browseDocuments(myDriveId, {}); expect(docs).toBeDefined(); expect(docs.children).toBeDefined(); - expect(docs.children.length).toEqual(TestHelpers.ALL_FILES.length) + expect(docs.children.length).toEqual(UserApi.ALL_FILES.length) const anotherUserDocs = await anotherUser.searchDocument({}); expect(anotherUserDocs).toBeDefined(); @@ -77,13 +77,13 @@ describe("The Documents Browser Window and API", () => { const result = await currentUser.uploadAllFilesOneByOne("root"); expect(result).toBeDefined(); expect(result.entries()).toBeDefined(); - expect(Array.from(result.entries())).toHaveLength(TestHelpers.ALL_FILES.length); + expect(Array.from(result.entries())).toHaveLength(UserApi.ALL_FILES.length); const docs = await currentUser.browseDocuments("root", {}); expect(docs).toBeDefined(); expect(docs.children).toBeDefined(); - expect(docs.children.length).toEqual(TestHelpers.ALL_FILES.length); + expect(docs.children.length).toEqual(UserApi.ALL_FILES.length); }); }); @@ -107,8 +107,8 @@ describe("The Documents Browser Window and API", () => { it("Should contain files that were shared with the user", async () => { const sharedWIthMeFolder = "shared_with_me"; - const oneUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); + const oneUser = await UserApi.getInstance(platform, true, {companyRole: "admin"}); + const anotherUser = await UserApi.getInstance(platform, true, {companyRole: "admin"}); let files = await oneUser.uploadAllFilesOneByOne(); await new Promise(r => setTimeout(r, 5000)); diff --git a/tdrive/backend/node/test/e2e/documents/documents-notifications.spec.ts b/tdrive/backend/node/test/e2e/documents/documents-notifications.spec.ts index 63b4c598..b9b3694e 100644 --- a/tdrive/backend/node/test/e2e/documents/documents-notifications.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/documents-notifications.spec.ts @@ -1,13 +1,11 @@ import { describe, beforeEach, it, expect, afterAll, jest } from "@jest/globals"; import { init, TestPlatform } from "../setup"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; import { DocumentsEngine } from "../../../src/services/documents/services/engine"; import { deserialize } from "class-transformer"; import { File } from "../../../src/services/files/entities/file"; import { ResourceUpdateResponse } from "../../../src/utils/types"; -import { e2e_createDocument, e2e_createDocumentFile, e2e_createVersion } from "./utils"; -import { DriveFileMockClass } from "../common/entities/mock_entities"; -import { TestDbService } from "../utils.prepare.db"; +import { e2e_createDocumentFile, e2e_createVersion } from "./utils"; describe("the Drive feature", () => { let platform: TestPlatform; @@ -16,6 +14,7 @@ describe("the Drive feature", () => { DocumentsEngine.prototype, "notifyDocumentVersionUpdated", ); + let currentUser: UserApi; beforeEach(async () => { platform = await init({ @@ -40,7 +39,8 @@ describe("the Drive feature", () => { "documents", ], }); - }, 300000000); + currentUser = await UserApi.getInstance(platform); + }); afterAll(async () => { await platform?.tearDown(); @@ -49,27 +49,12 @@ describe("the Drive feature", () => { platform = null; }); - const createItem = async (): Promise => { - await TestDbService.getInstance(platform, true); - const scope: "personal" | "shared" = "shared"; - const item = { - name: "new test file", - parent_id: "root", - company_id: platform.workspace.company_id, - scope, - }; - - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - return deserialize(DriveFileMockClass, response.body); - }; it("Did notify the user after sharing a file.", async () => { // jest.setTimeout(20000); //given:: user uploaded one doc and give permission to another user - const oneUser = await TestHelpers.getInstance(platform, true, { companyRole: "admin" }); - const anotherUser = await TestHelpers.getInstance(platform, true, { companyRole: "admin" }); + const oneUser = await UserApi.getInstance(platform, true, { companyRole: "admin" }); + const anotherUser = await UserApi.getInstance(platform, true, { companyRole: "admin" }); //upload files const doc = await oneUser.uploadRandomFileAndCreateDocument(); await new Promise(r => setTimeout(r, 3000)); @@ -88,7 +73,7 @@ describe("the Drive feature", () => { }); it("Did notify the user after creating a new version for a file.", async () => { - const item = await createItem(); + const item = await currentUser.createDefaultDocument(); const fileUploadResponse = await e2e_createDocumentFile(platform); const fileUploadResult = deserialize>( ResourceUpdateResponse, diff --git a/tdrive/backend/node/test/e2e/documents/documents-search.spec.ts b/tdrive/backend/node/test/e2e/documents/documents-search.spec.ts new file mode 100644 index 00000000..47c6689e --- /dev/null +++ b/tdrive/backend/node/test/e2e/documents/documents-search.spec.ts @@ -0,0 +1,250 @@ +import { describe, it, expect, afterAll } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +import UserApi from "../common/user-api"; +import { DriveFileMockClass } from "../common/entities/mock_entities"; +import { DriveFile } from "../../../src/services/documents/entities/drive-file"; + +describe("the Drive Search feature", () => { + let platform: TestPlatform; + let userOne: UserApi; + let start: number; + let end: number; + let userTwo: UserApi; + const uploadedByUserOne = []; + const uploadedByUserTwo = []; + + beforeAll(async () => { + platform = await init({ + services: [ + "webserver", + "database", + "applications", + "search", + "storage", + "message-queue", + "user", + "search", + "files", + "websocket", + "messages", + "auth", + "realtime", + "channels", + "statistics", + "platform-services", + "documents", + ], + }); + }); + + afterAll(async () => { + await platform?.tearDown(); + platform = null; + }); + + + // Create data for all test at once, due not to have a lot of setTimeouts, + // And test basic searches at once + //TODO[ASH] refactor this after refactoring events handling in enittymanager + it("Crete test data", async () => { + //create one document for default user + // await currentUser.createDefaultDocument(); // 1 + // await currentUser.uploadAllFilesOneByOne(); // 6 + + userOne = await UserApi.getInstance(platform, true, {companyRole: "admin"}); + userTwo = await UserApi.getInstance(platform, true, {companyRole: "admin"}); + + //user one upload 6 file to the personal folder + uploadedByUserOne.push(...(await userOne.uploadAllFilesOneByOne("user_" + userOne.user.id))); + start = new Date().getTime(); + //user on uploaded 6 files to the root folder + uploadedByUserOne.push(...(await userOne.uploadAllFilesOneByOne("root"))); + end = new Date().getTime(); + //another user uploaded 6 files to the personal folder + uploadedByUserTwo.push(...(await userTwo.uploadAllFilesOneByOne("user_" + userTwo.user.id))); + //another user uploaded 6 files to the root folder + uploadedByUserTwo.push(...(await userTwo.uploadAllFilesOneByOne("root"))); + await new Promise(resolve => setTimeout(resolve, 3000)); + + //user one give permissions to user two to one of the documents from personal folder + const doc = uploadedByUserOne[0] + doc.access_info.entities.push({ + type: "user", + id: userTwo.user.id, + level: "read", + grantor: null, + }); + await userOne.updateDocument(doc.id, doc); + + await new Promise(resolve => setTimeout(resolve, 10000)); + }); + + it("did search for an item", async () => { + const searchPayload = { + search: "sample", + }; + + const searchResult = await userOne.searchDocument(searchPayload); + expect(searchResult.entities.length).toBeGreaterThanOrEqual(6); + }); + + + it("did search for an item and check that all the fields for 'shared_with_me' view", async () => { + // jest.setTimeout(20000); + //when:: user search for a doc + const searchResponse = await userOne.searchDocument({ view: "shared_with_me" }); + + //then:: + expect(searchResponse.entities?.length).toEqual(UserApi.ALL_FILES.length * 3); + const docs = searchResponse.entities.filter(e => e.id === uploadedByUserOne[0].id) + expect(docs.length).toEqual(1) + expectSharedDoc( docs[0], uploadedByUserOne[0]); + }); + + it("'shared_with_me' shouldn't return files uploaded by me", async () => { + //when:: user search for a doc + const searchResponse = await userTwo.sharedWithMeDocuments({}); + + //then:: + expect(searchResponse.entities?.length).toEqual(1); + }) + + it("did search for an item that doesn't exist", async () => { + const unexistingSeachPayload = { + search: "somethingthatdoesn'tandshouldn'texist", + }; + const failSearchResult = await userOne.searchDocument(unexistingSeachPayload); + + expect(failSearchResult.entities).toHaveLength(0); + }); + + + it("did search by mime type", async () => { + const filters = { + mime_type: "application/pdf", + }; + + //when + let documents = await userOne.searchDocument(filters); + + //then + expect(documents.entities).toHaveLength(3); + expect(documents.entities[0].name.includes("pdf")).toBeTruthy(); + expect(documents.entities[1].name.includes("pdf")).toBeTruthy(); + expect(documents.entities[2].name.includes("pdf")).toBeTruthy(); + }); + + it("did search by last modified", async () => { + //then:: only file uploaded in the [start, end] interval are shown in the search results + const filters = { + last_modified_gt: start.toString(), + last_modified_lt: end.toString(), + }; + const documents = await userOne.searchDocument(filters); + expect(documents.entities).toHaveLength(UserApi.ALL_FILES.length); + }); + + it("did search a file shared by another user", async () => { + //then file become searchable + expect((await userTwo.sharedWithMeDocuments({})).entities).toHaveLength(1); + }); + + it("did search a file by file owner", async () => { + //and searchable for user that have + expect( + ( + await userTwo.searchDocument({ + creator: userOne.user.id, + }) + ).entities, + ).toHaveLength(7); + }); + + it("did search by 'added' date", async () => { + //then:: only file uploaded in the [start, end] interval are shown in the search results + const filters = { + added_gt: start.toString(), + added_lt: end.toString(), + }; + const documents = await userOne.searchDocument(filters); + expect(documents.entities).toHaveLength(UserApi.ALL_FILES.length); + }); + + it("did search order by name", async () => { + //when:: sort files by name is ascending order + const options = { + sort: { + name_keyword: "asc", + }, + }; + const documents = await userOne.searchDocument(options); + + //then all the files are sorted properly by name + let actualNames = documents.entities.map(e => e.name); + expect(actualNames).toEqual(actualNames.slice().sort()); + }); + + it("did search order by name desc", async () => { + //when:: sort files by name is ascending order + const options = { + sort: { + name_keyword: "desc", + }, + }; + const documents = await userOne.searchDocument(options); + + //then all the files are sorted properly by name + let actualNames = documents.entities.map(e => e.name); + expect(actualNames).toEqual(actualNames.slice().sort().reverse()); + }); + + it("did search order by added date", async () => { + //when:: ask to sort files by the 'added' field + const options = { + sort: { + added: "asc", + }, + }; + const documents = await userOne.searchDocument(options); + + //then:: files should be sorted properly + let actualDocs = documents.entities; + let expectedDocs = actualDocs.slice() + .sort((a, b) => a.added - b.added) + .map(d => d.name); + expect(actualDocs.map(d => d.name)).toEqual(expectedDocs); + }); + + it("did search order by added date desc", async () => { + //when:: ask to sort files by the 'added' field desc + const options = { + sort: { + added: "desc", + }, + }; + const documents = await userOne.searchDocument(options); + + //then:: files should be sorted properly + let actualDocs = documents.entities; + let expectedDocs = actualDocs.slice() + .sort((a, b) => a.added - b.added) + .map(d => d.name) + .reverse(); + expect(actualDocs.map(d => d.name)).toEqual(expectedDocs); + }); + + function expectSharedDoc(actual: DriveFileMockClass, doc: DriveFile) { + expect(actual.name).toEqual(doc.name); + //file type + expect(actual.extension).toEqual(doc.extension); + expect(actual.id).toEqual(doc.id); + expect(actual.is_directory).toEqual(doc.is_directory); + expect(actual.last_modified).toEqual(doc.last_modified); + expect(actual.added).toEqual(doc.added); + expect(actual.parent_id).toEqual(doc.parent_id); + expect(actual.created_by?.id).toEqual(userOne.user.id); + expect(actual.created_by?.first_name).toEqual(userOne.user.first_name); + expect(actual.shared_by?.id).toEqual(userOne.user.id); + expect(actual.shared_by?.first_name).toEqual(userOne.user.first_name); + } +}); diff --git a/tdrive/backend/node/test/e2e/documents/documents-tab.spec.ts b/tdrive/backend/node/test/e2e/documents/documents-tab.spec.ts index 05ff43ef..e5b1fe57 100644 --- a/tdrive/backend/node/test/e2e/documents/documents-tab.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/documents-tab.spec.ts @@ -1,14 +1,15 @@ -import { afterAll, afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterAll, beforeEach, describe, expect, it } from "@jest/globals"; import { deserialize } from "class-transformer"; import { AccessInformation } from "../../../src/services/documents/entities/drive-file"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; -import { e2e_createDocument, e2e_getDocument } from "./utils"; +import UserApi from "../common/user-api"; const url = "/internal/services/documents/v1"; describe("the Drive Tdrive tabs feature", () => { let platform: TestPlatform; + let currentUser: UserApi; class DriveFileMockClass { id: string; @@ -49,6 +50,7 @@ describe("the Drive Tdrive tabs feature", () => { "documents", ], }); + currentUser = await UserApi.getInstance(platform); }); afterAll(async () => { @@ -59,16 +61,7 @@ describe("the Drive Tdrive tabs feature", () => { it("did create a tab configuration on Drive side", async () => { await TestDbService.getInstance(platform, true); - const item = { - name: "new tab test file", - parent_id: "root", - company_id: platform.workspace.company_id, - }; - - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - const doc = deserialize(DriveFileMockClass, response.body); + const doc = await currentUser.createDefaultDocument(); const tab = { company_id: platform.workspace.company_id, @@ -109,7 +102,7 @@ describe("the Drive Tdrive tabs feature", () => { expect(getTabResponse.json().tab_id).toBe(tab.tab_id); expect(getTabResponse.json().item_id).toBe(tab.item_id); - const documentResponse = await e2e_getDocument(platform, doc.id); + const documentResponse = await currentUser.getDocument(doc.id); const documentResult = deserialize( DriveItemDetailsMockClass, documentResponse.body, @@ -132,25 +125,7 @@ describe("the Drive Tdrive tabs feature", () => { }; const otherUser = await dbService.createUser([ws0pk]); - const item = { - name: "new tab test file", - parent_id: "root", - company_id: platform.workspace.company_id, - access_info: { - entities: [ - { - type: "folder", - id: "parent", - level: "none", - } as any, - ], - }, - }; - - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - const doc = deserialize(DriveFileMockClass, response.body); + const doc = await currentUser.createDefaultDocument(); const tab = { company_id: platform.workspace.company_id, diff --git a/tdrive/backend/node/test/e2e/documents/documents.spec.ts b/tdrive/backend/node/test/e2e/documents/documents.spec.ts index 9febc0fb..1ebcb5f0 100644 --- a/tdrive/backend/node/test/e2e/documents/documents.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/documents.spec.ts @@ -5,25 +5,20 @@ import { ResourceUpdateResponse } from "../../../src/utils/types"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { - e2e_createDocument, e2e_createDocumentFile, e2e_createVersion, e2e_deleteDocument, - e2e_getDocument, - e2e_searchDocument, e2e_updateDocument, } from "./utils"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; import { DriveFileMockClass, DriveItemDetailsMockClass, - SearchResultMockClass, } from "../common/entities/mock_entities"; describe("the Drive feature", () => { let platform: TestPlatform; - let currentUser: TestHelpers; - let dbService: TestDbService; + let currentUser: UserApi; beforeEach(async () => { platform = await init({ @@ -48,33 +43,17 @@ describe("the Drive feature", () => { "documents", ], }); - currentUser = await TestHelpers.getInstance(platform); - dbService = await TestDbService.getInstance(platform, true); - }, 300000000); + currentUser = await UserApi.getInstance(platform); + }); afterAll(async () => { await platform?.tearDown(); platform = null; }); - const createItem = async (): Promise => { - await TestDbService.getInstance(platform, true); - const scope: "personal" | "shared" = "shared"; - const item = { - name: "new test file", - parent_id: "root", - company_id: platform.workspace.company_id, - scope, - }; - - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - return deserialize(DriveFileMockClass, response.body); - }; it("did create the drive item", async () => { - const result = await createItem(); + const result = await currentUser.createDefaultDocument(); expect(result).toBeDefined(); expect(result.name).toEqual("new test file"); @@ -84,7 +63,7 @@ describe("the Drive feature", () => { it("did fetch the drive item", async () => { await TestDbService.getInstance(platform, true); - const response = await e2e_getDocument(platform, ""); + const response = await currentUser.getDocument(""); const result = deserialize(DriveItemDetailsMockClass, response.body); expect(result.item.id).toEqual("root"); @@ -94,7 +73,7 @@ describe("the Drive feature", () => { it("did fetch the trash", async () => { await TestDbService.getInstance(platform, true); - const response = await e2e_getDocument(platform, "trash"); + const response = await currentUser.getDocument("trash"); const result = deserialize(DriveItemDetailsMockClass, response.body); expect(result.item.id).toEqual("trash"); @@ -102,7 +81,7 @@ describe("the Drive feature", () => { }); it("did delete an item", async () => { - const createItemResult = await createItem(); + const createItemResult = await currentUser.createDefaultDocument(); expect(createItemResult.id).toBeDefined(); @@ -111,7 +90,7 @@ describe("the Drive feature", () => { }); it("did update an item", async () => { - const createItemResult = await createItem(); + const createItemResult = await currentUser.createDefaultDocument(); expect(createItemResult.id).toBeDefined(); @@ -130,14 +109,14 @@ describe("the Drive feature", () => { }); it("did move an item to trash", async () => { - const createItemResult = await createItem(); + const createItemResult = await currentUser.createDefaultDocument(); expect(createItemResult.id).toBeDefined(); const moveToTrashResponse = await e2e_deleteDocument(platform, createItemResult.id); expect(moveToTrashResponse.statusCode).toEqual(200); - const listTrashResponse = await e2e_getDocument(platform, "trash"); + const listTrashResponse = await currentUser.getDocument("trash"); const listTrashResult = deserialize( DriveItemDetailsMockClass, listTrashResponse.body, @@ -148,115 +127,8 @@ describe("the Drive feature", () => { expect(listTrashResult.children.some(({ id }) => id === createItemResult.id)).toBeTruthy(); }); - it("did search for an item", async () => { - // jest.setTimeout(10000); - const createItemResult = await createItem(); - - expect(createItemResult.id).toBeDefined(); - - await e2e_getDocument(platform, "root"); - await e2e_getDocument(platform, createItemResult.id); - - await new Promise(resolve => setTimeout(resolve, 3000)); - - const searchPayload = { - search: "test", - }; - - const searchResponse = await e2e_searchDocument(platform, searchPayload); - const searchResult = deserialize( - SearchResultMockClass, - searchResponse.body, - ); - - expect(searchResult.entities.length).toBeGreaterThanOrEqual(1); - }); - - it("did search for an item and check that all the fields for 'shared_with_me' view", async () => { - // jest.setTimeout(20000); - //given:: user uploaded one doc and give permission to another user - const oneUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - //upload files - const doc = await oneUser.uploadRandomFileAndCreateDocument(); - await new Promise(r => setTimeout(r, 3000)); - //give permissions to the file - doc.access_info.entities.push({ - type: "user", - id: anotherUser.user.id, - level: "read", - grantor: null, - }); - await oneUser.updateDocument(doc.id, doc); - - await new Promise(resolve => setTimeout(resolve, 5000)); - - //when:: user search for a doc - const searchResponse = await anotherUser.searchDocument({ view: "shared_with_me" }); - - //then:: - expect(searchResponse.entities?.length).toEqual(1); - const actual = searchResponse.entities[0]; - - //file name - expect(actual.name).toEqual(doc.name); - //file type - expect(actual.extension).toEqual(doc.extension); - expect(actual.id).toEqual(doc.id); - expect(actual.is_directory).toEqual(doc.is_directory); - expect(actual.last_modified).toEqual(doc.last_modified); - expect(actual.added).toEqual(doc.added); - expect(actual.parent_id).toEqual(doc.parent_id); - expect(actual.created_by?.id).toEqual(oneUser.user.id); - expect(actual.created_by?.first_name).toEqual(oneUser.user.first_name); - expect(actual.shared_by?.id).toEqual(oneUser.user.id); - expect(actual.shared_by?.first_name).toEqual(oneUser.user.first_name); - }); - - it("'shared_with_me' shouldn't return files uploaded by me", async () => { - // jest.setTimeout(20000); - //given:: user uploaded one doc and give permission to another user - const oneUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const doc = await oneUser.uploadRandomFileAndCreateDocument(); - await new Promise(r => setTimeout(r, 3000)); - //give permissions to the file - doc.access_info.entities.push({ - type: "user", - id: anotherUser.user.id, - level: "read", - grantor: null, - }); - await oneUser.updateDocument(doc.id, doc); - //another user also uploaded several files - await anotherUser.uploadRandomFileAndCreateDocument(); - - await new Promise(resolve => setTimeout(resolve, 5000)); - - //when:: user search for a doc - const searchResponse = await anotherUser.sharedWithMeDocuments({}); - - //then:: - expect(searchResponse.entities?.length).toEqual(1); - }) - - it("did search for an item that doesn't exist", async () => { - await createItem(); - - const unexistingSeachPayload = { - search: "somethingthatdoesn'tandshouldn'texist", - }; - const failSearchResponse = await e2e_searchDocument(platform, unexistingSeachPayload); - const failSearchResult = deserialize( - SearchResultMockClass, - failSearchResponse.body, - ); - - expect(failSearchResult.entities).toHaveLength(0); - }); - it("did create a version for a drive item", async () => { - const item = await createItem(); + const item = await currentUser.createDefaultDocument(); const fileUploadResponse = await e2e_createDocumentFile(platform); const fileUploadResult = deserialize>( ResourceUpdateResponse, @@ -269,7 +141,7 @@ describe("the Drive feature", () => { await e2e_createVersion(platform, item.id, { filename: "file3", file_metadata }); await e2e_createVersion(platform, item.id, { filename: "file4", file_metadata }); - const fetchItemResponse = await e2e_getDocument(platform, item.id); + const fetchItemResponse = await currentUser.getDocument(item.id); const fetchItemResult = deserialize( DriveItemDetailsMockClass, fetchItemResponse.body, @@ -278,216 +150,4 @@ describe("the Drive feature", () => { expect(fetchItemResult.versions).toHaveLength(4); }); - it("did search by mime type", async () => { - // jest.setTimeout(10000); - // given:: all the sample files uploaded and documents for them created - await currentUser.uploadAllFilesOneByOne(); - - const filters = { - mime_type: "application/pdf", - }; - - await new Promise(r => setTimeout(r, 5000)); - - let documents = await currentUser.searchDocument(filters); - expect(documents.entities).toHaveLength(1); - - const actualFile = documents.entities[0]; - expect(actualFile.name).toEqual("sample.pdf"); - }); - - it("did search by last modified", async () => { - // jest.setTimeout(10000); - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - const start = new Date().getTime(); - await user.uploadAllFilesOneByOne(); - const end = new Date().getTime(); - await user.uploadAllFilesOneByOne(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 5000)); - - //then:: all the files are searchable without filters - let documents = await user.searchDocument({}); - expect(documents.entities).toHaveLength(TestHelpers.ALL_FILES.length * 2); - - //then:: only file uploaded in the [start, end] interval are shown in the search results - const filters = { - last_modified_gt: start.toString(), - last_modified_lt: end.toString(), - }; - documents = await user.searchDocument(filters); - expect(documents.entities).toHaveLength(TestHelpers.ALL_FILES.length); - }); - - it("did search a file shared by another user", async () => { - //given: - const oneUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - //upload files - let files = await oneUser.uploadAllFilesOneByOne(); - - await new Promise(r => setTimeout(r, 5000)); - - //then:: files are not searchable for user without permissions - expect((await anotherUser.sharedWithMeDocuments({})).entities).toHaveLength(0); - - //and searchable for user that have - expect((await oneUser.searchDocument({})).entities).toHaveLength(TestHelpers.ALL_FILES.length); - - //give permissions to the file - files[0].access_info.entities.push({ - type: "user", - id: anotherUser.user.id, - level: "read", - grantor: null, - }); - await oneUser.updateDocument(files[0].id, files[0]); - await new Promise(r => setTimeout(r, 3000)); - - //then file become searchable - expect((await anotherUser.sharedWithMeDocuments({})).entities).toHaveLength(1); - }, 30000000); - - it("did search a file by file owner", async () => { - // jest.setTimeout(30000); - //given: - const oneUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - const anotherUser = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - //upload files - let files = await oneUser.uploadAllFilesOneByOne(); - await anotherUser.uploadAllFilesOneByOne(); - //give permissions for all files to 'another user' - await Promise.all( - files.map(f => { - f.access_info.entities.push({ - type: "user", - id: anotherUser.user.id, - level: "read", - grantor: null, - }); - return oneUser.updateDocument(f.id, f); - }), - ); - - await new Promise(r => setTimeout(r, 5000)); - - //then:: all files are searchable for 'another user' - expect((await anotherUser.searchDocument({})).entities).toHaveLength( - TestHelpers.ALL_FILES.length * 2, - ); - - //and searchable for user that have - expect( - ( - await oneUser.searchDocument({ - creator: oneUser.user.id, - }) - ).entities, - ).toHaveLength(TestHelpers.ALL_FILES.length); - }); - - it("did search by 'added' date", async () => { - // jest.setTimeout(10000); - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - await user.uploadRandomFileAndCreateDocument(); - const start = new Date().getTime(); - await user.uploadAllFilesAndCreateDocuments(); - const end = new Date().getTime(); - await user.uploadRandomFileAndCreateDocument(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 3000)); - - //then:: all the files are searchable without filters - let documents = await user.searchDocument({}); - expect(documents.entities).toHaveLength(TestHelpers.ALL_FILES.length + 2); - - //then:: only file uploaded in the [start, end] interval are shown in the search results - const filters = { - added_gt: start.toString(), - added_lt: end.toString(), - }; - documents = await user.searchDocument(filters); - expect(documents.entities).toHaveLength(TestHelpers.ALL_FILES.length); - }); - - it("did search order by name", async () => { - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - await user.uploadAllFilesAndCreateDocuments(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 5000)); - - //when:: sort files by name is ascending order - const options = { - sort: { - name_keyword: "asc", - }, - }; - const documents = await user.searchDocument(options); - - //then all the files are sorted properly by name - expect(documents.entities.map(e => e.name)).toEqual(TestHelpers.ALL_FILES.sort()); - }, 30000); - - it("did search order by name desc", async () => { - // jest.setTimeout(10000); - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - await user.uploadAllFilesOneByOne(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 5000)); - - //when:: sort files by name is ascending order - const options = { - sort: { - name_keyword: "desc", - }, - }; - const documents = await user.searchDocument(options); - - //then all the files are sorted properly by name - expect(documents.entities.map(e => e.name)).toEqual(TestHelpers.ALL_FILES.sort().reverse()); - }); - - it("did search order by added date", async () => { - // jest.setTimeout(10000); - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - await user.uploadAllFilesOneByOne(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 5000)); - - //when:: ask to sort files by the 'added' field - const options = { - sort: { - added: "asc", - }, - }; - const documents = await user.searchDocument(options); - - //then:: files should be sorted properly - expect(documents.entities.map(e => e.name)).toEqual(TestHelpers.ALL_FILES); - }); - - it("did search order by added date desc", async () => { - // jest.setTimeout(10000); - const user = await TestHelpers.getInstance(platform, true, {companyRole: "admin"}); - // given:: all the sample files uploaded and documents for them created - await user.uploadAllFilesOneByOne(); - //wait for putting docs to elastic and its indexing - await new Promise(r => setTimeout(r, 5000)); - - //when:: ask to sort files by the 'added' field desc - const options = { - sort: { - added: "desc", - }, - }; - const documents = await user.searchDocument(options); - - //then:: files should be sorted properly - expect(documents.entities.map(e => e.name)).toEqual(TestHelpers.ALL_FILES.reverse()); - }); }); diff --git a/tdrive/backend/node/test/e2e/documents/my-drive.spec.ts b/tdrive/backend/node/test/e2e/documents/my-drive.spec.ts index d50d5d06..1313a7a7 100644 --- a/tdrive/backend/node/test/e2e/documents/my-drive.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/my-drive.spec.ts @@ -1,21 +1,16 @@ import { describe, beforeEach, afterEach, it, expect, afterAll } from "@jest/globals"; import { deserialize } from "class-transformer"; -import { File } from "../../../src/services/files/entities/file"; -import { ResourceUpdateResponse } from "../../../src/utils/types"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { - e2e_createDocument, - e2e_createDocumentFile, - e2e_createVersion, - e2e_deleteDocument, - e2e_getDocument, - e2e_searchDocument, e2e_updateDocument, } from "./utils"; +import UserApi from "../common/user-api"; +import { DriveFile } from "../../../src/services/documents/entities/drive-file"; describe("the My Drive feature", () => { let platform: TestPlatform; + let currentUser: UserApi; class DriveFileMockClass { id: string; @@ -60,6 +55,7 @@ describe("the My Drive feature", () => { "documents", ], }); + currentUser = await UserApi.getInstance(platform); }); afterAll(async () => { @@ -67,7 +63,7 @@ describe("the My Drive feature", () => { platform = null; }); - const createItem = async (): Promise => { + const createItem = async (): Promise => { await TestDbService.getInstance(platform, true); const item = { @@ -76,10 +72,7 @@ describe("the My Drive feature", () => { company_id: platform.workspace.company_id, }; - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - return deserialize(DriveFileMockClass, response.body); + return await currentUser.createDocument(item, {}); }; it("did create the drive item in my user folder", async () => { diff --git a/tdrive/backend/node/test/e2e/documents/public-links.spec.ts b/tdrive/backend/node/test/e2e/documents/public-links.spec.ts index 535e8b38..22a52471 100644 --- a/tdrive/backend/node/test/e2e/documents/public-links.spec.ts +++ b/tdrive/backend/node/test/e2e/documents/public-links.spec.ts @@ -4,14 +4,15 @@ import { AccessInformation, DriveFile } from "../../../src/services/documents/en import { FileVersion } from "../../../src/services/documents/entities/file-version"; import { DriveFileAccessLevel, DriveItemDetails } from "../../../src/services/documents/types"; import { init, TestPlatform } from "../setup"; -import { e2e_createDocument, e2e_updateDocument } from "./utils"; -import TestHelpers from "../common/common_test_helpers"; +import { e2e_updateDocument } from "./utils"; +import UserApi from "../common/user-api"; import { AccessTokenMockClass } from "../common/entities/mock_entities"; const url = "/internal/services/documents/v1"; describe("the public links feature", () => { let platform: TestPlatform; + let currentUser: UserApi; class DriveFileMockClass { id: string; @@ -54,6 +55,7 @@ describe("the public links feature", () => { "documents", ], }); + currentUser = await UserApi.getInstance(platform); }); afterAll(async () => { @@ -62,29 +64,14 @@ describe("the public links feature", () => { }); describe("Basic Flow", () => { - const createItem = async (): Promise => { - await TestHelpers.getInstance(platform, true, { companyRole: "admin" }); - - const item = { - name: "public file", - parent_id: "root", - company_id: platform.workspace.company_id, - }; - - const version = {}; - - const response = await e2e_createDocument(platform, item, version); - return deserialize(DriveFileMockClass, response.body); - }; - let publicFile: DriveFileMockClass; it("did create the drive item", async () => { - const result = await createItem(); + const result = await currentUser.createDefaultDocument(); publicFile = result; expect(result).toBeDefined(); - expect(result.name).toEqual("public file"); + expect(result.name).toEqual("new test file"); expect(result.added).toBeDefined(); expect(result.access_info).toBeDefined(); }); @@ -283,8 +270,8 @@ describe("the public links feature", () => { describe("Download Folder from shared link", () => { it("Share folder", async () => { - const user = await TestHelpers.getInstance(platform, true); - const anotherUser = await TestHelpers.getInstance(platform, true); + const user = await UserApi.getInstance(platform, true); + const anotherUser = await UserApi.getInstance(platform, true); //create directory in "My Drive" and upload a file const directory = await user.createDirectory("user_" + user.user.id); diff --git a/tdrive/backend/node/test/e2e/documents/utils.ts b/tdrive/backend/node/test/e2e/documents/utils.ts index bea33119..f2c377ff 100644 --- a/tdrive/backend/node/test/e2e/documents/utils.ts +++ b/tdrive/backend/node/test/e2e/documents/utils.ts @@ -6,38 +6,6 @@ import * as fs from "fs"; const url = "/internal/services/documents/v1"; -export const e2e_createDocument = async ( - platform: TestPlatform, - item: Partial, - version: Partial, -) => { - const token = await platform.auth.getJWTToken(); - - return await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/item`, - headers: { - authorization: `Bearer ${token}`, - }, - payload: { - item, - version, - }, - }); -}; - -export const e2e_getDocument = async (platform: TestPlatform, id: string | "root" | "trash") => { - const token = await platform.auth.getJWTToken(); - - return await platform.app.inject({ - method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/item/${id}`, - headers: { - authorization: `Bearer ${token}`, - }, - }); -}; - export const e2e_deleteDocument = async (platform: TestPlatform, id: string | "root" | "trash") => { const token = await platform.auth.getJWTToken(); @@ -67,21 +35,6 @@ export const e2e_updateDocument = async ( }); }; -export const e2e_searchDocument = async ( - platform: TestPlatform, - payload: Record, -) => { - const token = await platform.auth.getJWTToken(); - - return await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/search`, - headers: { - authorization: `Bearer ${token}`, - }, - payload, - }); -}; export const e2e_createVersion = async ( platform: TestPlatform, diff --git a/tdrive/backend/node/test/e2e/files/files.spec.ts b/tdrive/backend/node/test/e2e/files/files.spec.ts index c0d48729..32336ba2 100644 --- a/tdrive/backend/node/test/e2e/files/files.spec.ts +++ b/tdrive/backend/node/test/e2e/files/files.spec.ts @@ -5,20 +5,20 @@ import { init, TestPlatform } from "../setup"; // @ts-ignore import fs from "fs"; import LocalConnectorService from "../../../src/core/platform/services/storage/connectors/local/service"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; describe("The Files feature", () => { const url = "/internal/services/files/v1"; let platform: TestPlatform; - let helpers: TestHelpers; + let helpers: UserApi; beforeAll(async () => { platform = await init({ services: ["webserver", "database", "storage", "files", "previews"], }); await platform.database.getConnector().init(); - helpers = await TestHelpers.getInstance(platform) + helpers = await UserApi.getInstance(platform) }); afterAll(async () => { @@ -68,8 +68,8 @@ describe("The Files feature", () => { }, 120000); it.skip("should save file and generate previews", async () => { - for (const i in TestHelpers.ALL_FILES) { - const file = TestHelpers.ALL_FILES[i]; + for (const i in UserApi.ALL_FILES) { + const file = UserApi.ALL_FILES[i]; const filesUpload = await helpers.uploadFile(file); diff --git a/tdrive/backend/node/test/e2e/users/users.quota.spec.ts b/tdrive/backend/node/test/e2e/users/users.quota.spec.ts index 177a1e73..b1aea3ce 100644 --- a/tdrive/backend/node/test/e2e/users/users.quota.spec.ts +++ b/tdrive/backend/node/test/e2e/users/users.quota.spec.ts @@ -1,14 +1,14 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect} from "@jest/globals"; import { init, TestPlatform } from "../setup"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; describe("The /users/quota API", () => { let platform: TestPlatform; - let currentUser: TestHelpers; + let currentUser: UserApi; beforeEach(async () => { platform = await init(); - currentUser = await TestHelpers.getInstance(platform); + currentUser = await UserApi.getInstance(platform); }, 30000000); afterEach(async () => { diff --git a/tdrive/backend/node/test/e2e/users/users.spec.ts b/tdrive/backend/node/test/e2e/users/users.spec.ts index 534db1a4..8339b0dc 100644 --- a/tdrive/backend/node/test/e2e/users/users.spec.ts +++ b/tdrive/backend/node/test/e2e/users/users.spec.ts @@ -3,7 +3,7 @@ import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; import { CompanyLimitsEnum } from "../../../src/services/user/web/types"; -import TestHelpers from "../common/common_test_helpers"; +import UserApi from "../common/user-api"; describe("The /users API", () => { const url = "/internal/services/users/v1"; @@ -213,7 +213,7 @@ describe("The /users API", () => { }); it("shouldn't return anonymous accounts ", async () => { - const oneUser = await TestHelpers.getInstance(platform, true); + const oneUser = await UserApi.getInstance(platform, true); const response = await platform.app.inject({ method: "GET", diff --git a/tdrive/backend/node/test/e2e/utils.api.ts b/tdrive/backend/node/test/e2e/utils.api.ts index b7ef87ab..3bbf19e4 100644 --- a/tdrive/backend/node/test/e2e/utils.api.ts +++ b/tdrive/backend/node/test/e2e/utils.api.ts @@ -1,4 +1,4 @@ -import { TestPlatform } from "./setup"; +import { TestPlatform, User } from "./setup"; import { InjectPayload, Response } from "light-my-request"; import { logger as log } from "../../src/core/platform/framework"; @@ -10,39 +10,33 @@ declare global { } export class Api { - constructor(protected platform: TestPlatform) {} - private async convertResponse(response: Promise): Promise { - const apiResponse = (await response) as ApiResponse; - if (apiResponse.statusCode !== 204) { - const json = apiResponse.json(); - apiResponse.resources = json.resources; - apiResponse.resource = json.resource; - } - return apiResponse; + private jwt: string; + + constructor(protected platform: TestPlatform, protected user: User) { } - private getJwtToken(userId: string) { - return this.platform.auth.getJWTToken({ sub: userId }); + private async getJwtToken() { + if (!this.jwt) { + this.jwt = await this.platform.auth.getJWTToken({ sub: this.user.id }); + } + return this.jwt; } async request( method: "GET" | "POST", url: string, payload: InjectPayload, - userId: string, headers: any, - ): Promise { - if (!userId) userId = this.platform.currentUser.id; + ): Promise { - let totalHeaders = { authorization: `Bearer ${await this.getJwtToken(userId)}` }; + let totalHeaders = { authorization: `Bearer ${await this.getJwtToken()}` }; if (headers) { totalHeaders = { ...totalHeaders, ...headers }; } - return this.convertResponse( - this.platform.app + return this.platform.app .inject({ method, url, @@ -54,20 +48,18 @@ export class Api { log.debug(a.json(), `${method} ${url}`); } return a; - }), - ); + }); } - public async get(url: string, userId?: string, headers?: any): Promise { - return this.request("GET", url, undefined, userId, headers); + public async get(url: string, headers?: any): Promise { + return this.request("GET", url, undefined, headers); } public async post( url: string, payload: InjectPayload, - userId?: string, headers?: any, - ): Promise { - return this.request("POST", url, payload, userId, headers); + ): Promise { + return this.request("POST", url, payload, headers); } } diff --git a/tdrive/backend/node/test/e2e/utils.prepare.db.ts b/tdrive/backend/node/test/e2e/utils.prepare.db.ts index 12284a8e..ac30b4ce 100644 --- a/tdrive/backend/node/test/e2e/utils.prepare.db.ts +++ b/tdrive/backend/node/test/e2e/utils.prepare.db.ts @@ -36,7 +36,6 @@ export class TestDbService { public company: Company; public users: User[]; private workspacesMap: Map; - private userService; rand = () => Math.floor(Math.random() * 100000); private database: DatabaseServiceAPI; @@ -256,6 +255,10 @@ export class TestDbService { return this; } + async cleanUp() { + await this.database.getConnector().drop() + } + getRepository = (type, entity) => { return this.database.getRepository(type, entity); };