Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 0 additions & 283 deletions test/integration/api/admin/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1350,291 +1350,8 @@ describe("api", function () {
});
});
});
describe('.restore', function () {
it.skip('should restore different versions of a deleted asset', async function () {
this.timeout(TIMEOUT.LARGE);

// Upload the same file twice (upload->delete->upload->delete)

// Upload and delete a file
const firstUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true
});
await wait(1000)();

const firstDelete = await API_V2.delete_resources([PUBLIC_ID_BACKUP_1]);


// Upload and delete it again, this time add angle to create a different 'version'
const secondUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true,
angle: '0'
});
await wait(1000)();

const secondDelete = await API_V2.delete_resources([PUBLIC_ID_BACKUP_1]);
await wait(1000)();

// Sanity, ensure these uploads are different before we continue
expect(firstUpload.bytes).not.to.equal(secondUpload.bytes);

// Ensure all files were uploaded correctly
expect(firstUpload).not.to.be(null);
expect(secondUpload).not.to.be(null);

// Ensure all files were deleted correctly
expect(firstDelete).to.have.property("deleted");
expect(secondDelete).to.have.property("deleted");

// Get the versions of the deleted asset
const getVersionsResp = await API_V2.resource(PUBLIC_ID_BACKUP_1, {versions: true});

const firstAssetVersion = getVersionsResp.versions[0].version_id;
const secondAssetVersion = getVersionsResp.versions[1].version_id;

// Restore first version, ensure it's equal to the upload size
await wait(2000)();
const firstVerRestore = await API_V2.restore([PUBLIC_ID_BACKUP_1], {versions: [firstAssetVersion]});
expect(firstVerRestore[PUBLIC_ID_BACKUP_1].bytes).to.eql(firstUpload.bytes);

// Restore second version, ensure it's equal to the upload size
await wait(2000)();
const secondVerRestore = await API_V2.restore([PUBLIC_ID_BACKUP_1], {versions: [secondAssetVersion]});
expect(secondVerRestore[PUBLIC_ID_BACKUP_1].bytes).to.eql(secondUpload.bytes);

// Cleanup,
const finalDeleteResp = await API_V2.delete_resources([PUBLIC_ID_BACKUP_1]);
expect(finalDeleteResp).to.have.property("deleted");
});

it.skip('should restore two different deleted assets', async () => {
this.timeout(TIMEOUT.LARGE);

// Upload two different files
const firstUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true
});
const secondUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_2,
backup: true,
angle: '0'
});

// delete both resources
const deleteAll = await API_V2.delete_resources([PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2]);

// Expect correct deletion of the assets
expect(deleteAll.deleted[PUBLIC_ID_BACKUP_1]).to.be("deleted");
expect(deleteAll.deleted[PUBLIC_ID_BACKUP_2]).to.be("deleted");

const getFirstAssetVersion = await API_V2.resource(PUBLIC_ID_BACKUP_1, {versions: true});
const getSecondAssetVersion = await API_V2.resource(PUBLIC_ID_BACKUP_2, {versions: true});

const firstAssetVersion = getFirstAssetVersion.versions[0].version_id;
const secondAssetVersion = getSecondAssetVersion.versions[0].version_id;

const IDS_TO_RESTORE = [PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2];
const VERSIONS_TO_RESTORE = [firstAssetVersion, secondAssetVersion];

const restore = await API_V2.restore(IDS_TO_RESTORE, {versions: VERSIONS_TO_RESTORE});

// Expect correct restorations
expect(restore[PUBLIC_ID_BACKUP_1].bytes).to.equal(firstUpload.bytes);
expect(restore[PUBLIC_ID_BACKUP_2].bytes).to.equal(secondUpload.bytes);

// Cleanup
const finalDelete = await API_V2.delete_resources([PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2]);
// Expect correct deletion of the assets
expect(finalDelete.deleted[PUBLIC_ID_BACKUP_1]).to.be("deleted");
expect(finalDelete.deleted[PUBLIC_ID_BACKUP_2]).to.be("deleted");
});
});

describe("restore_by_asset_ids", function () {
this.timeout(TIMEOUT.MEDIUM);

const publicId = "api_test_restore" + UNIQUE_JOB_SUFFIX_ID;
let uploadedAssetId;

before(() => uploadImage({
public_id: publicId,
backup: true,
tags: UPLOAD_TAGS
})
.then(wait(2000))
.then(() => cloudinary.v2.api.resource(publicId))
.then((resource) => {
uploadedAssetId = resource.asset_id;
expect(resource).not.to.be(null);
expect(resource.bytes).to.eql(3381);
return cloudinary.v2.api.delete_resources(publicId);
})
.then(() => cloudinary.v2.api.resource(publicId))
.then((resource) => {
expect(resource).not.to.be(null);
expect(resource.bytes).to.eql(0);
expect(resource.placeholder).to.eql(true);
})
);

it("should restore a deleted resource when passed an asset ID", () => cloudinary.v2.api
.restore_by_asset_ids([uploadedAssetId])
.then((response) => {
let info = response[uploadedAssetId];
expect(info).not.to.be(null);
expect(info.bytes).to.eql(3381);
return cloudinary.v2.api.resources_by_asset_ids([uploadedAssetId]);
})
.then((response) => {
const { resources } = response;
expect(resources[0]).not.to.be(null);
expect(resources[0].bytes).to.eql(3381);
}));

it.skip("should restore different versions of a deleted asset when passed an asset ID", async function () {
this.timeout(TIMEOUT.LARGE);

// Upload the same file twice (upload->delete->upload->delete)

// Upload and delete a file
const firstUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true
});
await wait(1000)();

const firstDelete = await API_V2.delete_resources([
PUBLIC_ID_BACKUP_1
]);

// Upload and delete it again, this time add angle to create a different 'version'
const secondUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true,
angle: "0"
});
await wait(1000)();

const secondDelete = await API_V2.delete_resources([
PUBLIC_ID_BACKUP_1
]);
await wait(1000)();

// Sanity, ensure these uploads are different before we continue
expect(firstUpload.bytes).not.to.equal(secondUpload.bytes);

// Ensure all files were uploaded correctly
expect(firstUpload).not.to.be(null);
expect(secondUpload).not.to.be(null);

// Ensure all files were deleted correctly
expect(firstDelete).to.have.property("deleted");
expect(secondDelete).to.have.property("deleted");

// Get the asset ID and versions of the deleted asset
const getVersionsResp = await API_V2.resource(PUBLIC_ID_BACKUP_1, {
versions: true
});
const assetId = getVersionsResp.asset_id;

const firstAssetVersion = getVersionsResp.versions[0].version_id;
const secondAssetVersion = getVersionsResp.versions[1].version_id;

// Restore first version by passing in the asset ID, ensure it's equal to the upload size
await wait(1000)();
const firstVerRestore = await API_V2.restore_by_asset_ids([assetId], {
versions: [firstAssetVersion]
});

expect(firstVerRestore[assetId].bytes).to.eql(
firstUpload.bytes
);

// Restore second version by passing in the asset ID, ensure it's equal to the upload size
await wait(1000)();
const secondVerRestore = await API_V2.restore_by_asset_ids(
[assetId],
{ versions: [secondAssetVersion] }
);
expect(secondVerRestore[assetId].bytes).to.eql(
secondUpload.bytes
);

// Cleanup,
const finalDeleteResp = await API_V2.delete_resources([
PUBLIC_ID_BACKUP_1
]);
expect(finalDeleteResp).to.have.property("deleted");
});

it("should restore two different deleted assets when passed asset IDs", async () => {
// Upload two different files
const firstUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true
});
const secondUpload = await uploadImage({
public_id: PUBLIC_ID_BACKUP_2,
backup: true,
angle: "0"
});

// delete both resources
const deleteAll = await API_V2.delete_resources([
PUBLIC_ID_BACKUP_1,
PUBLIC_ID_BACKUP_2
]);

// Expect correct deletion of the assets
expect(deleteAll.deleted[PUBLIC_ID_BACKUP_1]).to.be("deleted");
expect(deleteAll.deleted[PUBLIC_ID_BACKUP_2]).to.be("deleted");

const getFirstAssetVersion = await API_V2.resource(
PUBLIC_ID_BACKUP_1,
{ versions: true }
);

const getSecondAssetVersion = await API_V2.resource(
PUBLIC_ID_BACKUP_2,
{ versions: true }
);

const firstAssetId = getFirstAssetVersion.asset_id;
const secondAssetId = getSecondAssetVersion.asset_id;

const firstAssetVersion =
getFirstAssetVersion.versions[0].version_id;
const secondAssetVersion =
getSecondAssetVersion.versions[0].version_id;

const IDS_TO_RESTORE = [firstAssetId, secondAssetId];
const VERSIONS_TO_RESTORE = [firstAssetVersion, secondAssetVersion];

const restore = await API_V2.restore_by_asset_ids(IDS_TO_RESTORE, {
versions: VERSIONS_TO_RESTORE
});

// Expect correct restorations
expect(restore[firstAssetId].bytes).to.equal(
firstUpload.bytes
);
expect(restore[secondAssetId].bytes).to.equal(
secondUpload.bytes
);

// Cleanup
const finalDelete = await API_V2.delete_resources([
PUBLIC_ID_BACKUP_1,
PUBLIC_ID_BACKUP_2
]);
// Expect correct deletion of the assets
expect(finalDelete.deleted[PUBLIC_ID_BACKUP_1]).to.be("deleted");
expect(finalDelete.deleted[PUBLIC_ID_BACKUP_2]).to.be("deleted");
});
});


describe('mapping', function () {
Expand Down
73 changes: 73 additions & 0 deletions test/unit/api_restore_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const assert = require('assert');
const sinon = require('sinon');

const cloudinary = require('../../lib/cloudinary');
const createTestConfig = require('../testUtils/createTestConfig');
const helper = require('../spechelper');
const api_http = require("https");
const ClientRequest = require('_http_client').ClientRequest;

describe('api restore handlers', function () {
const mocked = {};

beforeEach(function () {
cloudinary.config(createTestConfig());
mocked.xhr = sinon.useFakeXMLHttpRequest();
mocked.write = sinon.spy(ClientRequest.prototype, 'write');
mocked.request = sinon.spy(api_http, 'request');
});

afterEach(function () {
mocked.request.restore();
mocked.write.restore();
mocked.xhr.restore();
});

describe('.restore', function () {
it('sends public_ids and versions with JSON payload', function () {
const options = {
resource_type: 'video',
type: 'authenticated',
versions: ['ver-1', 'ver-2']
};

cloudinary.v2.api.restore(['pub-1', 'pub-2'], options);

sinon.assert.calledWith(mocked.request, sinon.match({
pathname: sinon.match('resources/video/authenticated/restore'),
method: sinon.match('POST')
}));

sinon.assert.calledWith(mocked.write, sinon.match(helper.apiJsonParamMatcher('public_ids', ['pub-1', 'pub-2'])));
sinon.assert.calledWith(mocked.write, sinon.match(helper.apiJsonParamMatcher('versions', ['ver-1', 'ver-2'])));
});
});

describe('.restore_by_asset_ids', function () {
it('sends asset_ids and versions with JSON payload', function () {
const options = { versions: ['ver-3'] };
const assetIds = ['asset-1', 'asset-2'];

cloudinary.v2.api.restore_by_asset_ids(assetIds, options);

sinon.assert.calledWith(mocked.request, sinon.match({
pathname: sinon.match('resources/restore'),
method: sinon.match('POST')
}));

sinon.assert.calledWith(mocked.write, sinon.match(helper.apiJsonParamMatcher('asset_ids', assetIds)));
sinon.assert.calledWith(mocked.write, sinon.match(helper.apiJsonParamMatcher('versions', ['ver-3'])));
});

it('wraps a single asset id into an array before calling the API', function () {
cloudinary.v2.api.restore_by_asset_ids('single-asset-id');

sinon.assert.calledWith(mocked.request, sinon.match({
pathname: sinon.match('resources/restore'),
method: sinon.match('POST')
}));

sinon.assert.calledWith(mocked.write, sinon.match(helper.apiJsonParamMatcher('asset_ids', ['single-asset-id'])));
});
});
});