diff --git a/.husky/pre-commit b/.husky/pre-commit index cf3ad8f8..3757878f 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,4 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" + yarn run test:unit yarn run lint yarn lint-staged \ No newline at end of file diff --git a/README.md b/README.md index 77f432a9..20a9f796 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $ npm install -g @internxt/cli $ internxt COMMAND running command... $ internxt (--version) -@internxt/cli/1.3.0 darwin-arm64 node-v20.14.0 +@internxt/cli/1.3.3 darwin-arm64 node-v20.14.0 $ internxt --help [COMMAND] USAGE $ internxt COMMAND @@ -79,7 +79,7 @@ EXAMPLES $ internxt add-cert ``` -_See code: [src/commands/add-cert.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/add-cert.ts)_ +_See code: [src/commands/add-cert.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/add-cert.ts)_ ## `internxt config` @@ -108,7 +108,7 @@ EXAMPLES $ internxt config ``` -_See code: [src/commands/config.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/config.ts)_ +_See code: [src/commands/config.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/config.ts)_ ## `internxt create-folder` @@ -129,7 +129,7 @@ EXAMPLES $ internxt create-folder ``` -_See code: [src/commands/create-folder.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/create-folder.ts)_ +_See code: [src/commands/create-folder.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/create-folder.ts)_ ## `internxt download` @@ -152,7 +152,7 @@ EXAMPLES $ internxt download ``` -_See code: [src/commands/download.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/download.ts)_ +_See code: [src/commands/download.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/download.ts)_ ## `internxt list` @@ -186,7 +186,7 @@ EXAMPLES $ internxt list ``` -_See code: [src/commands/list.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/list.ts)_ +_See code: [src/commands/list.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/list.ts)_ ## `internxt login` @@ -212,7 +212,7 @@ EXAMPLES $ internxt login ``` -_See code: [src/commands/login.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/login.ts)_ +_See code: [src/commands/login.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/login.ts)_ ## `internxt logout` @@ -229,7 +229,7 @@ EXAMPLES $ internxt logout ``` -_See code: [src/commands/logout.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/logout.ts)_ +_See code: [src/commands/logout.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/logout.ts)_ ## `internxt logs` @@ -246,7 +246,7 @@ EXAMPLES $ internxt logs ``` -_See code: [src/commands/logs.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/logs.ts)_ +_See code: [src/commands/logs.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/logs.ts)_ ## `internxt move` @@ -271,7 +271,7 @@ EXAMPLES $ internxt move ``` -_See code: [src/commands/move.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/move.ts)_ +_See code: [src/commands/move.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/move.ts)_ ## `internxt rename` @@ -296,7 +296,7 @@ EXAMPLES $ internxt rename ``` -_See code: [src/commands/rename.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/rename.ts)_ +_See code: [src/commands/rename.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/rename.ts)_ ## `internxt trash` @@ -320,7 +320,7 @@ EXAMPLES $ internxt trash ``` -_See code: [src/commands/trash.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/trash.ts)_ +_See code: [src/commands/trash.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/trash.ts)_ ## `internxt trash-clear` @@ -347,7 +347,7 @@ EXAMPLES $ internxt trash-clear ``` -_See code: [src/commands/trash-clear.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/trash-clear.ts)_ +_See code: [src/commands/trash-clear.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/trash-clear.ts)_ ## `internxt trash-list` @@ -383,7 +383,7 @@ EXAMPLES $ internxt trash-list ``` -_See code: [src/commands/trash-list.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/trash-list.ts)_ +_See code: [src/commands/trash-list.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/trash-list.ts)_ ## `internxt trash-restore` @@ -411,7 +411,7 @@ EXAMPLES $ internxt trash-restore ``` -_See code: [src/commands/trash-restore.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/trash-restore.ts)_ +_See code: [src/commands/trash-restore.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/trash-restore.ts)_ ## `internxt trash clear` @@ -520,7 +520,7 @@ EXAMPLES $ internxt upload ``` -_See code: [src/commands/upload.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/upload.ts)_ +_See code: [src/commands/upload.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/upload.ts)_ ## `internxt webdav ACTION` @@ -543,7 +543,7 @@ EXAMPLES $ internxt webdav status ``` -_See code: [src/commands/webdav.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/webdav.ts)_ +_See code: [src/commands/webdav.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/webdav.ts)_ ## `internxt webdav-config ACTION` @@ -571,7 +571,7 @@ EXAMPLES $ internxt webdav-config change-port ``` -_See code: [src/commands/webdav-config.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/webdav-config.ts)_ +_See code: [src/commands/webdav-config.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/webdav-config.ts)_ ## `internxt whoami` @@ -588,7 +588,7 @@ EXAMPLES $ internxt whoami ``` -_See code: [src/commands/whoami.ts](https://github.com/internxt/cli/blob/v1.3.0/src/commands/whoami.ts)_ +_See code: [src/commands/whoami.ts](https://github.com/internxt/cli/blob/v1.3.3/src/commands/whoami.ts)_ # Current Limitations diff --git a/package.json b/package.json index ff7b6a36..836397af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "author": "Internxt ", - "version": "1.3.0", + "version": "1.3.3", "description": "Internxt CLI to manage your encrypted storage", "scripts": { "build": "tsc", @@ -8,7 +8,7 @@ "postpack": "shx rm -f oclif.manifest.json", "posttest": "yarn lint", "prepack": "yarn build && oclif manifest && oclif readme", - "prepare": "husky", + "prepare": "husky || true", "test:unit": "nyc --reporter=lcov --reporter=text mocha \"test/**/*.test.ts\" --exit", "dev:webdav": "nodemon -e ts --exec ts-node src/webdav/index.ts", "version": "oclif readme && git add README.md", @@ -16,13 +16,9 @@ "migrate": "sequelize db:migrate", "migrate:undo": "sequelize db:migrate:undo", "publish:npm": "npm run build && npm publish --scope=@internxt --registry=https://registry.npmjs.org/ --access public", - "publish:github": "npm publish", + "publish:github": "npm publish --scope=@internxt --registry=https://npm.pkg.github.com", "postinstall": "node ./scripts/skip-in-ci.js || internxt webdav restart" }, - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org/" - }, "homepage": "https://github.com/internxt/cli", "license": "MIT", "main": "", diff --git a/src/commands/config.ts b/src/commands/config.ts index 38865cec..65a11e1c 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -28,7 +28,7 @@ export default class Config extends Command { const configList = [ { key: 'Email', value: userCredentials.user.email }, { key: 'Root folder ID', value: userCredentials.root_folder_uuid }, - { key: 'Used space', value: FormatUtils.humanFileSize(await UsageService.instance.fetchTotalUsage()) }, + { key: 'Used space', value: FormatUtils.humanFileSize((await UsageService.instance.fetchUsage()).total) }, { key: 'Available space', value: FormatUtils.formatLimit(await UsageService.instance.fetchSpaceLimit()) }, ]; ux.table( diff --git a/src/services/sdk-manager.service.ts b/src/services/sdk-manager.service.ts index e815124c..a935c382 100644 --- a/src/services/sdk-manager.service.ts +++ b/src/services/sdk-manager.service.ts @@ -1,4 +1,4 @@ -import { Auth, Drive, photos, Network as NetworkModule } from '@internxt/sdk'; +import { Auth, Drive, Network as NetworkModule } from '@internxt/sdk'; import { Trash } from '@internxt/sdk/dist/drive'; import { ApiSecurity, AppDetails } from '@internxt/sdk/dist/shared'; import { ConfigService } from './config.service'; @@ -135,15 +135,6 @@ export class SdkManager { }); } - /** Photos SDK */ - getPhotos() { - const PHOTOS_API_URL = ConfigService.instance.get('PHOTOS_API_URL'); - - const newToken = SdkManager.getApiSecurity().newToken; - - return new photos.Photos(PHOTOS_API_URL, newToken); - } - /** Share SDK */ getShare() { const DRIVE_NEW_API_URL = ConfigService.instance.get('DRIVE_NEW_API_URL'); diff --git a/src/services/usage.service.ts b/src/services/usage.service.ts index 92b7a226..91d75603 100644 --- a/src/services/usage.service.ts +++ b/src/services/usage.service.ts @@ -1,19 +1,15 @@ +import { UsageResponse } from '@internxt/sdk/dist/drive/storage/types'; import { SdkManager } from './sdk-manager.service'; export class UsageService { public static readonly instance: UsageService = new UsageService(); public static readonly INFINITE_LIMIT = 99 * Math.pow(1024, 4); - public fetchTotalUsage = async (): Promise => { + public fetchUsage = async (): Promise => { const storageClient = SdkManager.instance.getStorage(); - const photosClient = SdkManager.instance.getPhotos(); + const driveUsage = await storageClient.spaceUsage(); - const [driveUsage, { usage: photosUsage }] = await Promise.all([ - storageClient.spaceUsage(), - photosClient.photos.getUsage(), - ]); - - return driveUsage.total + photosUsage; + return driveUsage; }; public fetchSpaceLimit = async (): Promise => { diff --git a/src/webdav/handlers/PROPFIND.handler.ts b/src/webdav/handlers/PROPFIND.handler.ts index 3e80e175..8a40c193 100644 --- a/src/webdav/handlers/PROPFIND.handler.ts +++ b/src/webdav/handlers/PROPFIND.handler.ts @@ -10,6 +10,7 @@ import mime from 'mime-types'; import { DriveDatabaseManager } from '../../services/database/drive-database-manager.service'; import { WebDavUtils } from '../../utils/webdav.utils'; import { webdavLogger } from '../../utils/logger.utils'; +import { UsageService } from '../../services/usage.service'; export class PROPFINDRequestHandler implements WebDavMethodHandler { constructor( @@ -36,7 +37,6 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { switch (resource.type) { case 'file': { const fileMetaXML = await this.getFileMetaXML(resource, driveItem as DriveFileItem); - console.error({ fileMetaXML }); res.status(207).send(fileMetaXML); break; } @@ -44,14 +44,16 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { case 'folder': { const depth = req.header('depth') ?? '1'; const folderMetaXML = await this.getFolderContentXML(resource, driveItem as DriveFolderItem, depth); - console.error({ folderMetaXML }); res.status(207).send(folderMetaXML); break; } } }; - private async getFileMetaXML(resource: WebDavRequestedResource, driveFileItem: DriveFileItem): Promise { + private readonly getFileMetaXML = async ( + resource: WebDavRequestedResource, + driveFileItem: DriveFileItem, + ): Promise => { const driveFile = this.driveFileItemToXMLNode( { name: driveFileItem.name, @@ -75,9 +77,13 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { }); return xml; - } + }; - private async getFolderContentXML(resource: WebDavRequestedResource, folderItem: DriveFolderItem, depth: string) { + private readonly getFolderContentXML = async ( + resource: WebDavRequestedResource, + folderItem: DriveFolderItem, + depth: string, + ) => { const relativePath = resource.url; const isRootFolder = resource.url === '/'; let XMLNodes: object[] = []; @@ -85,7 +91,7 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { switch (depth) { case '0': if (isRootFolder) { - XMLNodes.push(this.driveFolderRootStatsToXMLNode(folderItem, relativePath)); + XMLNodes.push(await this.driveFolderRootStatsToXMLNode(folderItem, relativePath)); } else { XMLNodes.push(this.driveFolderItemToXMLNode(folderItem, relativePath)); } @@ -93,7 +99,7 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { case '1': default: if (isRootFolder) { - XMLNodes.push(this.driveFolderRootStatsToXMLNode(folderItem, relativePath)); + XMLNodes.push(await this.driveFolderRootStatsToXMLNode(folderItem, relativePath)); XMLNodes = XMLNodes.concat(await this.getFolderChildsXMLNode(relativePath, folderItem.uuid)); } else { XMLNodes.push(this.driveFolderItemToXMLNode(folderItem, relativePath)); @@ -108,9 +114,9 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { suppressEmptyNode: true, }); return xml; - } + }; - private async getFolderChildsXMLNode(relativePath: string, folderUuid: string) { + private readonly getFolderChildsXMLNode = async (relativePath: string, folderUuid: string) => { const { driveFolderService, driveDatabaseManager } = this.dependencies; const folderContent = await driveFolderService.getFolderContent(folderUuid); @@ -195,9 +201,15 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { ); return foldersXML.concat(filesXML); - } + }; + + private readonly driveFolderRootStatsToXMLNode = async ( + driveFolderItem: DriveFolderItem, + relativePath: string, + ): Promise => { + const totalUsage = (await UsageService.instance.fetchUsage()).total; + const spaceLimit = await UsageService.instance.fetchSpaceLimit(); - private driveFolderRootStatsToXMLNode(driveFolderItem: DriveFolderItem, relativePath: string): object { const driveFolderXML = { [XMLUtils.addDefaultNamespace('href')]: encodeURIComponent(relativePath), [XMLUtils.addDefaultNamespace('propstat')]: { @@ -216,6 +228,8 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { '#text': '00000030', '@_xmlns:x3': 'urn:schemas-microsoft-com:', }, + [XMLUtils.addDefaultNamespace('quota-available-bytes')]: spaceLimit - totalUsage, + [XMLUtils.addDefaultNamespace('quota-used-bytes')]: totalUsage, [XMLUtils.addDefaultNamespace('resourcetype')]: { [XMLUtils.addDefaultNamespace('collection')]: '', }, @@ -223,9 +237,9 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { }, }; return driveFolderXML; - } + }; - private driveFolderItemToXMLNode(driveFolderItem: DriveFolderItem, relativePath: string): object { + private readonly driveFolderItemToXMLNode = (driveFolderItem: DriveFolderItem, relativePath: string): object => { const displayName = `${driveFolderItem.name}`; const driveFolderXML = { @@ -244,9 +258,9 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { }; return driveFolderXML; - } + }; - private driveFileItemToXMLNode(driveFileItem: DriveFileItem, relativePath: string): object { + private readonly driveFileItemToXMLNode = (driveFileItem: DriveFileItem, relativePath: string): object => { const displayName = driveFileItem.type ? `${driveFileItem.name}.${driveFileItem.type}` : driveFileItem.name; const driveFileXML = { @@ -265,5 +279,5 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler { }; return driveFileXML; - } + }; } diff --git a/test/services/sdkmanager.service.test.ts b/test/services/sdkmanager.service.test.ts index 4a3e00a2..75f0b234 100644 --- a/test/services/sdkmanager.service.test.ts +++ b/test/services/sdkmanager.service.test.ts @@ -2,7 +2,7 @@ import chai, { expect } from 'chai'; import sinon, { SinonSandbox } from 'sinon'; import sinonChai from 'sinon-chai'; import crypto from 'crypto'; -import { Auth, Drive, Network, photos } from '@internxt/sdk'; +import { Auth, Drive, Network } from '@internxt/sdk'; import { Trash } from '@internxt/sdk/dist/drive'; import { SdkManager, SdkManagerApiSecurity } from '../../src/services/sdk-manager.service'; import { ConfigKeys } from '../../src/types/config.types'; @@ -268,31 +268,6 @@ describe('SDKManager service', () => { expect(newClient).to.eql(client); }); - it('When Photos client is requested, then it is generated using internxt sdk', () => { - const envEndpoint: { key: keyof ConfigKeys; value: string } = { - key: 'PHOTOS_API_URL', - value: 'test/api', - }; - SdkManager.init(apiSecurity); - - const client = new photos.Photos(envEndpoint.value, apiSecurity.newToken); - - const spyConfigService = sdkManagerServiceSandbox - .stub(ConfigService.instance, 'get') - .withArgs(envEndpoint.key) - .returns(envEndpoint.value); - sdkManagerServiceSandbox.stub(SdkManager, 'getApiSecurity').returns(apiSecurity); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - sdkManagerServiceSandbox.stub(SdkManager, 'getAppDetails').returns(appDetails); - - sdkManagerServiceSandbox.stub(photos.Photos, 'prototype').returns(client); - - const newClient = SdkManager.instance.getPhotos(); - - expect(spyConfigService).to.be.calledWith(envEndpoint.key); - expect(newClient).to.eql(client); - }); - it('When Share client is requested, then it is generated using internxt sdk', () => { const envEndpoint: { key: keyof ConfigKeys; value: string } = { key: 'DRIVE_NEW_API_URL', diff --git a/test/services/usage.service.test.ts b/test/services/usage.service.test.ts index 370baeb3..96f9b603 100644 --- a/test/services/usage.service.test.ts +++ b/test/services/usage.service.test.ts @@ -1,11 +1,9 @@ import { expect } from 'chai'; import Sinon, { SinonSandbox } from 'sinon'; -import { randomInt } from 'crypto'; +import { randomInt, randomUUID } from 'crypto'; import { Storage } from '@internxt/sdk/dist/drive'; -import { Photos } from '@internxt/sdk/dist/photos'; import { UsageService } from '../../src/services/usage.service'; import { SdkManager } from '../../src/services/sdk-manager.service'; -import PhotosSubmodule from '@internxt/sdk/dist/photos/photos'; describe('Usage Service', () => { let usageServiceSandbox: SinonSandbox; @@ -19,21 +17,17 @@ describe('Usage Service', () => { }); it('When getting user usage, it should return the total usage', async () => { - const driveSpaceUsage = { total: randomInt(2000000000) }; - const photosSpaceUsage = { usage: randomInt(2000000000) }; + const drive = randomInt(2000000000); + const backups = randomInt(2000000000); + const total = drive + backups; + const driveSpaceUsage = { _id: randomUUID(), total, drive, backups }; - // @ts-expect-error - Partial mock usageServiceSandbox.stub(Storage.prototype, 'spaceUsage').resolves(driveSpaceUsage); usageServiceSandbox.stub(SdkManager.instance, 'getStorage').returns(Storage.prototype); - const photos = new Photos('test'); - usageServiceSandbox.stub(PhotosSubmodule.prototype, 'getUsage').resolves(photosSpaceUsage); - usageServiceSandbox.stub(photos, 'photos').returns(PhotosSubmodule.prototype); - usageServiceSandbox.stub(SdkManager.instance, 'getPhotos').returns(photos); + const result = await UsageService.instance.fetchUsage(); - const result = await UsageService.instance.fetchTotalUsage(); - - expect(result).to.be.equal(driveSpaceUsage.total + photosSpaceUsage.usage); + expect(result).to.be.eql(driveSpaceUsage); }); it('When getting user space limit, it should return the total usage', async () => { diff --git a/test/utils/format.utils.test.ts b/test/utils/format.utils.test.ts index d9956d64..4c7a46f4 100644 --- a/test/utils/format.utils.test.ts +++ b/test/utils/format.utils.test.ts @@ -5,11 +5,8 @@ import { UsageService } from '../../src/services/usage.service'; describe('Format utils', () => { it('When providing a date, it should return a formatted date for WebDav', () => { - // Arrange const date = new Date('2021-10-10T10:10:10Z'); - // Act const result = FormatUtils.formatDateForWebDav(date); - // Assert expect(result).to.be.eq('Sun, 10 Oct 2021 10:10:10 GMT'); }); diff --git a/test/webdav/handlers/PROPFIND.handler.test.ts b/test/webdav/handlers/PROPFIND.handler.test.ts index 8664e7fd..75309ada 100644 --- a/test/webdav/handlers/PROPFIND.handler.test.ts +++ b/test/webdav/handlers/PROPFIND.handler.test.ts @@ -19,6 +19,7 @@ import mime from 'mime-types'; import crypto from 'crypto'; import { NotFoundError } from '../../../src/utils/errors.utils'; import { fail } from 'assert'; +import { UsageService } from '../../../src/services/usage.service'; describe('PROPFIND request handler', () => { const sandbox = sinon.createSandbox(); @@ -53,6 +54,11 @@ describe('PROPFIND request handler', () => { const folderFixture = newFolderItem({ id: UserSettingsFixture.root_folder_id, }); + const drive = crypto.randomInt(2000000000); + const backups = crypto.randomInt(2000000000); + const total = drive + backups; + const usageFixture = { _id: UserSettingsFixture.email, total, drive, backups }; + const spaceLimitFixture = crypto.randomInt(2000000000); const getRequestedResourceStub = sandbox .stub(WebDavUtils, 'getRequestedResource') @@ -63,17 +69,21 @@ describe('PROPFIND request handler', () => { const getFolderContentStub = sandbox .stub(driveFolderService, 'getFolderContent') .resolves({ folders: [], files: [] }); + const getUsageStub = sandbox.stub(UsageService.instance, 'fetchUsage').resolves(usageFixture); + const spaceLimitStub = sandbox.stub(UsageService.instance, 'fetchSpaceLimit').resolves(spaceLimitFixture); await requestHandler.handle(request, response); expect(response.status.calledWith(207)).to.be.true; expect( sendStub.calledWith( - `${encodeURIComponent('/')}HTTP/1.1 200 OKapplication/octet-stream${FormatUtils.formatDateForWebDav(folderFixture.updatedAt)}F00000030`, + `${encodeURIComponent('/')}HTTP/1.1 200 OKapplication/octet-stream${FormatUtils.formatDateForWebDav(folderFixture.updatedAt)}F00000030${spaceLimitFixture - usageFixture.total}${usageFixture.total}`, ), ).to.be.true; expect(getRequestedResourceStub.calledOnce).to.be.true; expect(getAndSearchItemFromResourceStub.calledOnce).to.be.true; expect(getFolderContentStub.calledOnce).to.be.true; + expect(getUsageStub.calledOnce).to.be.true; + expect(spaceLimitStub.calledOnce).to.be.true; }); it('When a WebDav client sends a PROPFIND request for the root folder, and there is content, should return the correct XML', async () => { @@ -107,6 +117,11 @@ describe('PROPFIND request handler', () => { updatedAt: new Date('2024-03-04T15:11:01.000Z'), uuid: 'FOLDER_UUID_1', }); + const drive = crypto.randomInt(2000000000); + const backups = crypto.randomInt(2000000000); + const total = drive + backups; + const usageFixture = { _id: UserSettingsFixture.email, total, drive, backups }; + const spaceLimitFixture = crypto.randomInt(2000000000); const getRequestedResourceStub = sandbox .stub(WebDavUtils, 'getRequestedResource') @@ -118,17 +133,21 @@ describe('PROPFIND request handler', () => { files: [], folders: [paginatedFolder1], }); + const getUsageStub = sandbox.stub(UsageService.instance, 'fetchUsage').resolves(usageFixture); + const spaceLimitStub = sandbox.stub(UsageService.instance, 'fetchSpaceLimit').resolves(spaceLimitFixture); await requestHandler.handle(request, response); expect(response.status.calledWith(207)).to.be.true; expect( sendStub.calledWith( - `${encodeURIComponent('/')}HTTP/1.1 200 OKapplication/octet-stream${FormatUtils.formatDateForWebDav(folderFixture.updatedAt)}F00000030${encodeURIComponent(`/${paginatedFolder1.plainName}/`)}HTTP/1.1 200 OK${paginatedFolder1.plainName}${FormatUtils.formatDateForWebDav(paginatedFolder1.updatedAt)}0`, + `${encodeURIComponent('/')}HTTP/1.1 200 OKapplication/octet-stream${FormatUtils.formatDateForWebDav(folderFixture.updatedAt)}F00000030${spaceLimitFixture - usageFixture.total}${usageFixture.total}${encodeURIComponent(`/${paginatedFolder1.plainName}/`)}HTTP/1.1 200 OK${paginatedFolder1.plainName}${FormatUtils.formatDateForWebDav(paginatedFolder1.updatedAt)}0`, ), ).to.be.true; expect(getRequestedResourceStub.calledOnce).to.be.true; expect(getAndSearchItemFromResourceStub.calledOnce).to.be.true; expect(getFolderContentStub.calledOnce).to.be.true; + expect(getUsageStub.calledOnce).to.be.true; + expect(spaceLimitStub.calledOnce).to.be.true; }); it('When a WebDav client sends a PROPFIND request for a file, should return the correct XML', async () => {